Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions rust/ql/lib/change-notes/2025-11-05-poem.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added models for cookie methods in the `poem` crate.
22 changes: 22 additions & 0 deletions rust/ql/lib/codeql/rust/frameworks/poem.model.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
extensions:
- addsTo:
pack: codeql/rust-all
extensible: sinkModel
data:
- ["<poem::web::cookie::CookieJar>::add", "Argument[0]", "cookie-use", "manual"]
- ["<poem::web::cookie::SignedCookieJar>::add", "Argument[0]", "cookie-use", "manual"]
- ["<poem::web::cookie::PrivateCookieJar>::add", "Argument[0]", "cookie-use", "manual"]
- ["<poem::session::server_session::ServerSession>::new", "Argument[0]", "cookie-use", "manual"]
- addsTo:
pack: codeql/rust-all
extensible: summaryModel
data:
- ["<poem::web::cookie::Cookie>::set_secure", "Argument[self].OptionalBarrier[cookie-secure-arg0]", "Argument[self]", "taint", "manual"]
- ["<poem::session::cookie_config::CookieConfig>::secure", "Argument[self].OptionalBarrier[cookie-secure-arg0]", "ReturnValue", "taint", "manual"]
- ["<poem::session::cookie_config::CookieConfig>::partitioned", "Argument[self].OptionalBarrier[cookie-partitioned-arg0]", "ReturnValue", "taint", "manual"]
- ["<poem::session::cookie_config::CookieConfig>::name", "Argument[self]", "ReturnValue", "taint", "manual"]
- ["<poem::session::cookie_config::CookieConfig>::path", "Argument[self]", "ReturnValue", "taint", "manual"]
- ["<poem::session::cookie_config::CookieConfig>::domain", "Argument[self]", "ReturnValue", "taint", "manual"]
- ["<poem::session::cookie_config::CookieConfig>::http_only", "Argument[self]", "ReturnValue", "taint", "manual"]
- ["<poem::session::cookie_config::CookieConfig>::same_site", "Argument[self]", "ReturnValue", "taint", "manual"]
- ["<poem::session::cookie_config::CookieConfig>::max_age", "Argument[self]", "ReturnValue", "taint", "manual"]
6 changes: 3 additions & 3 deletions rust/ql/src/queries/security/CWE-614/InsecureCookie.ql
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ module InsecureCookieConfig implements DataFlow::ConfigSig {
node instanceof Sink
}

predicate isBarrier(DataFlow::Node node) {
// setting the 'secure' attribute to true
cookieSetNode(node, "secure", true)
predicate isBarrierIn(DataFlow::Node node) {
// setting the 'secure' attribute
cookieSetNode(node, "secure", _)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change because setting a cookie's security to false is a sink, and hence we want to make false a barrier as well, as otherwise two sources would flow to a sink?

What is the isBarrier -> isBarrierIn change for?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's about preventing excessive flows in a case such as this:

set_secure(false); // source
set_secure(false); // source
sink();

Making line 2 a barrier prevents flow from line 1 to 3, leaving us with just the shorter path from line 2 to 3. It's a fairly common pattern to make sources in-barriers, e.g. you'll see this in all of the rust/cleartext-* queries.

The reason I've changed it to an in barrier is simple - if I didn't, then flow from every source would be blocked immediately by that source itself being a barrier. As an in-barrier, the situation becomes something like this:

|barrier| set_secure(false);
|barrier| set_secure(false); -> flow ->
sink();

or
node instanceof Barrier
}
Expand Down
Loading