Split SecureCookies into query specific files

This commit is contained in:
Joe Farebrother
2025-11-17 16:15:10 +00:00
parent 5b702d963e
commit c6110ed541
4 changed files with 46 additions and 41 deletions

View File

@@ -1,4 +1,4 @@
/** Provides classes and predicates for identifying HTTP cookies with insecure attributes. */ /** Provides classes and predicates for identifying HTTP cookies without the `HttpOnly` attribute. */
import go import go
import semmle.go.concepts.HTTP import semmle.go.concepts.HTTP
@@ -31,21 +31,6 @@ private module SensitiveCookieNameConfig implements DataFlow::ConfigSig {
/** Tracks flow from sensitive names to HTTP cookie writes. */ /** Tracks flow from sensitive names to HTTP cookie writes. */
module SensitiveCookieNameFlow = TaintTracking::Global<SensitiveCookieNameConfig>; module SensitiveCookieNameFlow = TaintTracking::Global<SensitiveCookieNameConfig>;
private module BooleanCookieSecureConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.getType().getUnderlyingType() instanceof BoolType
}
predicate isSink(DataFlow::Node sink) { exists(Http::CookieWrite cw | sink = cw.getSecure()) }
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(Http::CookieOptionWrite co | co.getSecure() = pred and co.getCookieOutput() = succ)
}
}
/** Tracks flow from boolean expressions to the `Secure` attribute of HTTP cookie writes. */
module BooleanCookieSecureFlow = TaintTracking::Global<BooleanCookieSecureConfig>;
private module BooleanCookieHttpOnlyConfig implements DataFlow::ConfigSig { private module BooleanCookieHttpOnlyConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { predicate isSource(DataFlow::Node source) {
source.getType().getUnderlyingType() instanceof BoolType source.getType().getUnderlyingType() instanceof BoolType
@@ -61,23 +46,6 @@ private module BooleanCookieHttpOnlyConfig implements DataFlow::ConfigSig {
/** Tracks flow from boolean expressions to the `HttpOnly` attribute of HTTP cookie writes. */ /** Tracks flow from boolean expressions to the `HttpOnly` attribute of HTTP cookie writes. */
module BooleanCookieHttpOnlyFlow = TaintTracking::Global<BooleanCookieHttpOnlyConfig>; module BooleanCookieHttpOnlyFlow = TaintTracking::Global<BooleanCookieHttpOnlyConfig>;
/** Holds if `cw` has the `Secure` attribute left at its default value of `false`. */
predicate isInsecureDefault(Http::CookieWrite cw) {
not BooleanCookieSecureFlow::flow(_, cw.getSecure())
}
/** Holds if `cw` has the `Secure` attribute explicitly set to `false`, from the expression `boolFalse`. */
predicate isInsecureDirect(Http::CookieWrite cw, Expr boolFalse) {
BooleanCookieSecureFlow::flow(DataFlow::exprNode(boolFalse), cw.getSecure()) and
boolFalse.getBoolValue() = false
}
/** Holds if `cw` has the `Secure` attribute set to `false`, either explicitly or by default. */
predicate isInsecureCookie(Http::CookieWrite cw) {
isInsecureDefault(cw) or
isInsecureDirect(cw, _)
}
/** Holds if `cw` has the `HttpOnly` attribute left at its default value of `false`. */ /** Holds if `cw` has the `HttpOnly` attribute left at its default value of `false`. */
predicate isNonHttpOnlyDefault(Http::CookieWrite cw) { predicate isNonHttpOnlyDefault(Http::CookieWrite cw) {
not BooleanCookieHttpOnlyFlow::flow(_, cw.getHttpOnly()) not BooleanCookieHttpOnlyFlow::flow(_, cw.getHttpOnly())

View File

@@ -0,0 +1,37 @@
/** Provides classes and predicates for identifying HTTP cookies without the `Secure` attribute. */
import go
import semmle.go.concepts.HTTP
import semmle.go.dataflow.DataFlow
private module BooleanCookieSecureConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.getType().getUnderlyingType() instanceof BoolType
}
predicate isSink(DataFlow::Node sink) { exists(Http::CookieWrite cw | sink = cw.getSecure()) }
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(Http::CookieOptionWrite co | co.getSecure() = pred and co.getCookieOutput() = succ)
}
}
/** Tracks flow from boolean expressions to the `Secure` attribute of HTTP cookie writes. */
module BooleanCookieSecureFlow = TaintTracking::Global<BooleanCookieSecureConfig>;
/** Holds if `cw` has the `Secure` attribute left at its default value of `false`. */
predicate isInsecureDefault(Http::CookieWrite cw) {
not BooleanCookieSecureFlow::flow(_, cw.getSecure())
}
/** Holds if `cw` has the `Secure` attribute explicitly set to `false`, from the expression `boolFalse`. */
predicate isInsecureDirect(Http::CookieWrite cw, Expr boolFalse) {
BooleanCookieSecureFlow::flow(DataFlow::exprNode(boolFalse), cw.getSecure()) and
boolFalse.getBoolValue() = false
}
/** Holds if `cw` has the `Secure` attribute set to `false`, either explicitly or by default. */
predicate isInsecureCookie(Http::CookieWrite cw) {
isInsecureDefault(cw) or
isInsecureDirect(cw, _)
}

View File

@@ -12,14 +12,14 @@
*/ */
import go import go
import semmle.go.security.SecureCookies import semmle.go.security.CookieWithoutHttpOnly
import SensitiveCookieNameFlow::PathGraph import SensitiveCookieNameFlow::PathGraph
from from
Http::CookieWrite cw, Expr sensitiveNameExpr, string name, Http::CookieWrite cw, string name, SensitiveCookieNameFlow::PathNode source,
SensitiveCookieNameFlow::PathNode source, SensitiveCookieNameFlow::PathNode sink SensitiveCookieNameFlow::PathNode sink
where where
isSensitiveCookie(cw, sensitiveNameExpr, name, source, sink) and isSensitiveCookie(cw, name, source, sink) and
isNonHttpOnlyCookie(cw) isNonHttpOnlyCookie(cw)
select cw, source, sink, "Sensitive cookie $@ does not set HttpOnly attribute to true.", select cw, source, sink, "Sensitive cookie $@ does not set HttpOnly attribute to true.", source,
sensitiveNameExpr, name name

View File

@@ -5,14 +5,14 @@
* @kind problem * @kind problem
* @problem.severity warning * @problem.severity warning
* @precision high * @precision high
* @security-severity 5.0 * @security-severity 4.0
* @id go/cookie-secure-not-set * @id go/cookie-secure-not-set
* @tags security * @tags security
* external/cwe/cwe-614 * external/cwe/cwe-614
*/ */
import go import go
import semmle.go.security.SecureCookies import semmle.go.security.CookieWithoutSecure
from Http::CookieWrite cw from Http::CookieWrite cw
where isInsecureCookie(cw) where isInsecureCookie(cw)