diff --git a/rust/ql/lib/codeql/rust/security/SqlInjectionExtensions.qll b/rust/ql/lib/codeql/rust/security/SqlInjectionExtensions.qll index fbec5c04433..99d79642e78 100644 --- a/rust/ql/lib/codeql/rust/security/SqlInjectionExtensions.qll +++ b/rust/ql/lib/codeql/rust/security/SqlInjectionExtensions.qll @@ -135,19 +135,25 @@ module SqlInjection { * Holds if `guard` is an OR expression where both operands compare `node` * with string literals when `branch` is true. */ - private predicate stringConstCompareOr(CfgNodes::AstCfgNode guard, Cfg::CfgNode node, boolean branch) { - exists(LogicalOrExpr orExpr | + private predicate stringConstCompareOr( + CfgNodes::AstCfgNode guard, Cfg::CfgNode node, boolean branch + ) { + exists(LogicalOrExpr orExpr, EqualsOperation eqLeft, EqualsOperation eqRight | guard = orExpr.getACfgNode() and branch = true and - // Both sides of OR must be string constant comparisons of the same node - stringConstCompare(orExpr.getLhs().getACfgNode(), node, true) and - stringConstCompare(orExpr.getRhs().getACfgNode(), node, true) and - // Ensure both sides compare the same node - exists(Cfg::CfgNode leftNode, Cfg::CfgNode rightNode | - stringConstCompare(orExpr.getLhs().getACfgNode(), leftNode, true) and - stringConstCompare(orExpr.getRhs().getACfgNode(), rightNode, true) and - leftNode = rightNode and - leftNode = node + eqLeft.getACfgNode() = orExpr.getLhs().getACfgNode() and + eqRight.getACfgNode() = orExpr.getRhs().getACfgNode() and + // Both sides must compare the same node against string literals + ( + node = eqLeft.getLhs().getACfgNode() and + node = eqRight.getLhs().getACfgNode() and + eqLeft.getRhs() instanceof StringLiteralExpr and + eqRight.getRhs() instanceof StringLiteralExpr + or + node = eqLeft.getRhs().getACfgNode() and + node = eqRight.getRhs().getACfgNode() and + eqLeft.getLhs() instanceof StringLiteralExpr and + eqRight.getLhs() instanceof StringLiteralExpr ) ) } diff --git a/rust/ql/src/change-notes/2025-10-30-sql-injection-barriers.md b/rust/ql/src/change-notes/2025-10-30-sql-injection-barriers.md new file mode 100644 index 00000000000..16d7a85a6f3 --- /dev/null +++ b/rust/ql/src/change-notes/2025-10-30-sql-injection-barriers.md @@ -0,0 +1,7 @@ +--- +category: minorAnalysis +--- +* The `rust/sql-injection` query now includes taint flow barriers to reduce false positives. Specifically: + * Data parsed to numeric types (e.g., `.parse::()`) is now recognized as safe. + * Data validated against one or more constant string values (e.g., `if x == "admin"` or `if x == "user" || x == "guest"`) is now recognized as safe within the validated branch. + * Data validated using collection membership checks against string literals (e.g., `if ["admin", "user"].contains(&x)`) is now recognized as safe within the validated branch.