From 1acbdbaaa2ab211ae6f1d921836facefbf70809e Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 1 Apr 2025 09:29:51 +0100 Subject: [PATCH 1/5] Rust: Make all query sinks extend QuerySink::Range and import them into Stats.qll (this ensures that sink statistics are complete). --- .../rust/security/CleartextTransmissionExtensions.qll | 5 ++++- .../ql/lib/codeql/rust/security/TaintedPathExtensions.qll | 4 +++- .../rust/security/WeakSensitiveDataHashingExtensions.qll | 4 ++-- rust/ql/src/queries/summary/Stats.qll | 8 +++++--- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/rust/ql/lib/codeql/rust/security/CleartextTransmissionExtensions.qll b/rust/ql/lib/codeql/rust/security/CleartextTransmissionExtensions.qll index 73495cd1c0d..8a3892f2347 100644 --- a/rust/ql/lib/codeql/rust/security/CleartextTransmissionExtensions.qll +++ b/rust/ql/lib/codeql/rust/security/CleartextTransmissionExtensions.qll @@ -7,12 +7,15 @@ private import codeql.util.Unit private import rust private import codeql.rust.dataflow.DataFlow private import codeql.rust.dataflow.FlowSink +private import codeql.rust.Concepts /** * A data flow sink for cleartext transmission vulnerabilities. That is, * a `DataFlow::Node` of something that is transmitted over a network. */ -abstract class CleartextTransmissionSink extends DataFlow::Node { } +abstract class CleartextTransmissionSink extends QuerySink::Range { + override string getSinkType() { result = "CleartextTransmission" } +} /** * A barrier for cleartext transmission vulnerabilities. diff --git a/rust/ql/lib/codeql/rust/security/TaintedPathExtensions.qll b/rust/ql/lib/codeql/rust/security/TaintedPathExtensions.qll index df8c43212b3..5f8d8b77ee8 100644 --- a/rust/ql/lib/codeql/rust/security/TaintedPathExtensions.qll +++ b/rust/ql/lib/codeql/rust/security/TaintedPathExtensions.qll @@ -23,7 +23,9 @@ module TaintedPath { /** * A data flow sink for path injection vulnerabilities. */ - abstract class Sink extends DataFlow::Node { } + abstract class Sink extends QuerySink::Range { + override string getSinkType() { result = "TaintedPath" } + } /** * A barrier for path injection vulnerabilities. diff --git a/rust/ql/lib/codeql/rust/security/WeakSensitiveDataHashingExtensions.qll b/rust/ql/lib/codeql/rust/security/WeakSensitiveDataHashingExtensions.qll index b22e5153ce3..7b6b6c801d7 100644 --- a/rust/ql/lib/codeql/rust/security/WeakSensitiveDataHashingExtensions.qll +++ b/rust/ql/lib/codeql/rust/security/WeakSensitiveDataHashingExtensions.qll @@ -44,6 +44,8 @@ module NormalHashFunction { * hashing. That is, a broken or weak hashing algorithm. */ abstract class Sink extends QuerySink::Range { + override string getSinkType() { result = "WeakSensitiveDataHashing" } + /** * Gets the name of the weak hashing algorithm. */ @@ -76,8 +78,6 @@ module NormalHashFunction { class WeakHashingOperationInputAsSink extends Sink { Cryptography::HashingAlgorithm algorithm; - override string getSinkType() { result = "WeakSensitiveDataHashing" } - WeakHashingOperationInputAsSink() { exists(Cryptography::CryptographicOperation operation | algorithm.isWeak() and diff --git a/rust/ql/src/queries/summary/Stats.qll b/rust/ql/src/queries/summary/Stats.qll index a24a4eac9c9..45b5bffa8d1 100644 --- a/rust/ql/src/queries/summary/Stats.qll +++ b/rust/ql/src/queries/summary/Stats.qll @@ -15,10 +15,12 @@ private import codeql.rust.Diagnostics private import codeql.rust.security.SensitiveData private import TaintReach // import all query extensions files, so that all extensions of `QuerySink` are found -private import codeql.rust.security.CleartextLoggingExtensions -private import codeql.rust.security.SqlInjectionExtensions -private import codeql.rust.security.WeakSensitiveDataHashingExtensions private import codeql.rust.security.regex.RegexInjectionExtensions +private import codeql.rust.security.CleartextLoggingExtensions +private import codeql.rust.security.CleartextTransmissionExtensions +private import codeql.rust.security.SqlInjectionExtensions +private import codeql.rust.security.TaintedPathExtensions +private import codeql.rust.security.WeakSensitiveDataHashingExtensions /** * Gets a count of the total number of lines of code in the database. From 784ccb740b75092c8cbd0eed902cbec1857d5909 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 4 Apr 2025 18:02:21 +0100 Subject: [PATCH 2/5] Rust: Define Rust queries and extensions more consistently. --- .../security/CleartextLoggingExtensions.qll | 8 +- .../CleartextTransmissionExtensions.qll | 64 ++++++---- .../rust/security/SqlInjectionExtensions.qll | 8 +- .../regex/RegexInjectionExtensions.qll | 113 ++++++++++-------- .../security/CWE-020/RegexInjection.ql | 8 +- .../queries/security/CWE-089/SqlInjection.ql | 8 +- .../security/CWE-311/CleartextTransmission.ql | 10 +- .../security/CWE-020/RegexInjectionSink.ql | 2 +- 8 files changed, 129 insertions(+), 92 deletions(-) diff --git a/rust/ql/lib/codeql/rust/security/CleartextLoggingExtensions.qll b/rust/ql/lib/codeql/rust/security/CleartextLoggingExtensions.qll index e6bbc0d2a2b..559509ad9f8 100644 --- a/rust/ql/lib/codeql/rust/security/CleartextLoggingExtensions.qll +++ b/rust/ql/lib/codeql/rust/security/CleartextLoggingExtensions.qll @@ -36,8 +36,10 @@ module CleartextLogging { */ private class SensitiveDataAsSource extends Source instanceof SensitiveData { } - /** A sink for logging from model data. */ - private class ModelsAsDataSinks extends Sink { - ModelsAsDataSinks() { exists(string s | sinkNode(this, s) and s.matches("log-injection%")) } + /** + * A sink for logging from model data. + */ + private class ModelsAsDataSink extends Sink { + ModelsAsDataSink() { exists(string s | sinkNode(this, s) and s.matches("log-injection%")) } } } diff --git a/rust/ql/lib/codeql/rust/security/CleartextTransmissionExtensions.qll b/rust/ql/lib/codeql/rust/security/CleartextTransmissionExtensions.qll index 8a3892f2347..2c528dddd9e 100644 --- a/rust/ql/lib/codeql/rust/security/CleartextTransmissionExtensions.qll +++ b/rust/ql/lib/codeql/rust/security/CleartextTransmissionExtensions.qll @@ -10,32 +10,48 @@ private import codeql.rust.dataflow.FlowSink private import codeql.rust.Concepts /** - * A data flow sink for cleartext transmission vulnerabilities. That is, - * a `DataFlow::Node` of something that is transmitted over a network. + * Provides default sources, sinks and barriers for detecting cleartext transmission + * vulnerabilities, as well as extension points for adding your own. */ -abstract class CleartextTransmissionSink extends QuerySink::Range { - override string getSinkType() { result = "CleartextTransmission" } -} - -/** - * A barrier for cleartext transmission vulnerabilities. - */ -abstract class CleartextTransmissionBarrier extends DataFlow::Node { } - -/** - * A unit class for adding additional flow steps. - */ -class CleartextTransmissionAdditionalFlowStep extends Unit { +module CleartextTransmission { /** - * Holds if the step from `node1` to `node2` should be considered a flow - * step for paths related to cleartext transmission vulnerabilities. + * A data flow source for cleartext transmission vulnerabilities. */ - abstract predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo); -} + abstract class Source extends DataFlow::Node { } -/** - * A sink defined through MaD. - */ -private class MadCleartextTransmissionSink extends CleartextTransmissionSink { - MadCleartextTransmissionSink() { sinkNode(this, "transmission") } + /** + * A data flow sink for cleartext transmission vulnerabilities. That is, + * a `DataFlow::Node` of something that is transmitted over a network. + */ + abstract class Sink extends QuerySink::Range { + override string getSinkType() { result = "CleartextTransmission" } + } + + /** + * A barrier for cleartext transmission vulnerabilities. + */ + abstract class Barrier extends DataFlow::Node { } + + /** + * A unit class for adding additional flow steps. + */ + class AdditionalFlowStep extends Unit { + /** + * Holds if the step from `node1` to `node2` should be considered a flow + * step for paths related to cleartext transmission vulnerabilities. + */ + abstract predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo); + } + + /** + * Sensitive data, considered as a flow source. + */ + private class SensitiveDataAsSource extends Source instanceof SensitiveData { } + + /** + * A sink defined through MaD. + */ + private class ModelsAsDataSink extends Sink { + ModelsAsDataSink() { sinkNode(this, "transmission") } + } } diff --git a/rust/ql/lib/codeql/rust/security/SqlInjectionExtensions.qll b/rust/ql/lib/codeql/rust/security/SqlInjectionExtensions.qll index 9c61fe4aa52..8ead5ac684a 100644 --- a/rust/ql/lib/codeql/rust/security/SqlInjectionExtensions.qll +++ b/rust/ql/lib/codeql/rust/security/SqlInjectionExtensions.qll @@ -51,8 +51,10 @@ module SqlInjection { SqlExecutionAsSink() { this = any(SqlExecution e).getSql() } } - /** A sink for sql-injection from model data. */ - private class ModelsAsDataSinks extends Sink { - ModelsAsDataSinks() { sinkNode(this, "sql-injection") } + /** + * A sink for sql-injection from model data. + */ + private class ModelsAsDataSink extends Sink { + ModelsAsDataSink() { sinkNode(this, "sql-injection") } } } diff --git a/rust/ql/lib/codeql/rust/security/regex/RegexInjectionExtensions.qll b/rust/ql/lib/codeql/rust/security/regex/RegexInjectionExtensions.qll index f1e4060a5cf..5c0f8b616b6 100644 --- a/rust/ql/lib/codeql/rust/security/regex/RegexInjectionExtensions.qll +++ b/rust/ql/lib/codeql/rust/security/regex/RegexInjectionExtensions.qll @@ -11,60 +11,71 @@ private import codeql.rust.dataflow.FlowSink private import codeql.rust.Concepts /** - * A data flow sink for regular expression injection vulnerabilities. + * Provides default sources, sinks and barriers for detecting regular expression + * injection vulnerabilities, as well as extension points for adding your own. */ -abstract class RegexInjectionSink extends QuerySink::Range { - override string getSinkType() { result = "RegexInjection" } -} - -/** - * A barrier for regular expression injection vulnerabilities. - */ -abstract class RegexInjectionBarrier extends DataFlow::Node { } - -/** A sink for `a` in `Regex::new(a)` when `a` is not a literal. */ -private class NewRegexInjectionSink extends RegexInjectionSink { - NewRegexInjectionSink() { - exists(CallExprCfgNode call, PathExpr path | - path = call.getFunction().getExpr() and - path.getResolvedCrateOrigin() = "repo:https://github.com/rust-lang/regex:regex" and - path.getResolvedPath() = "::new" and - this.asExpr() = call.getArgument(0) and - not this.asExpr() instanceof LiteralExprCfgNode - ) - } -} - -private class MadRegexInjectionSink extends RegexInjectionSink { - MadRegexInjectionSink() { sinkNode(this, "regex-use") } -} - -/** - * A unit class for adding additional flow steps. - */ -class RegexInjectionAdditionalFlowStep extends Unit { +module RegexInjection { /** - * Holds if the step from `node1` to `node2` should be considered a flow - * step for paths related to regular expression injection vulnerabilities. + * A data flow sink for regular expression injection vulnerabilities. */ - abstract predicate step(DataFlow::Node node1, DataFlow::Node node2); -} + abstract class Sink extends QuerySink::Range { + override string getSinkType() { result = "RegexInjection" } + } -/** - * An escape barrier for regular expression injection vulnerabilities. - */ -private class RegexInjectionDefaultBarrier extends RegexInjectionBarrier { - RegexInjectionDefaultBarrier() { - // A barrier is any call to a function named `escape`, in particular this - // makes calls to `regex::escape` a barrier. - this.asExpr() - .getExpr() - .(CallExpr) - .getFunction() - .(PathExpr) - .getPath() - .getSegment() - .getIdentifier() - .getText() = "escape" + /** + * A barrier for regular expression injection vulnerabilities. + */ + abstract class Barrier extends DataFlow::Node { } + + /** + * A sink for `a` in `Regex::new(a)` when `a` is not a literal. + */ + private class NewSink extends Sink { + NewSink() { + exists(CallExprCfgNode call, PathExpr path | + path = call.getFunction().getExpr() and + path.getResolvedCrateOrigin() = "repo:https://github.com/rust-lang/regex:regex" and + path.getResolvedPath() = "::new" and + this.asExpr() = call.getArgument(0) and + not this.asExpr() instanceof LiteralExprCfgNode + ) + } + } + + /** + * A sink for regular expression injection from model data. + */ + private class ModelsAsDataSink extends Sink { + ModelsAsDataSink() { sinkNode(this, "regex-use") } + } + + /** + * A unit class for adding additional flow steps. + */ + class AdditionalFlowStep extends Unit { + /** + * Holds if the step from `node1` to `node2` should be considered a flow + * step for paths related to regular expression injection vulnerabilities. + */ + abstract predicate step(DataFlow::Node node1, DataFlow::Node node2); + } + + /** + * An escape barrier for regular expression injection vulnerabilities. + */ + private class DefaultBarrier extends Barrier { + DefaultBarrier() { + // A barrier is any call to a function named `escape`, in particular this + // makes calls to `regex::escape` a barrier. + this.asExpr() + .getExpr() + .(CallExpr) + .getFunction() + .(PathExpr) + .getPath() + .getSegment() + .getIdentifier() + .getText() = "escape" + } } } diff --git a/rust/ql/src/queries/security/CWE-020/RegexInjection.ql b/rust/ql/src/queries/security/CWE-020/RegexInjection.ql index b49d08969f6..075f6e99d11 100644 --- a/rust/ql/src/queries/security/CWE-020/RegexInjection.ql +++ b/rust/ql/src/queries/security/CWE-020/RegexInjection.ql @@ -24,14 +24,16 @@ private import codeql.rust.security.regex.RegexInjectionExtensions * A taint configuration for detecting regular expression injection vulnerabilities. */ module RegexInjectionConfig implements DataFlow::ConfigSig { + import RegexInjection + predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource } - predicate isSink(DataFlow::Node sink) { sink instanceof RegexInjectionSink } + predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - predicate isBarrier(DataFlow::Node barrier) { barrier instanceof RegexInjectionBarrier } + predicate isBarrier(DataFlow::Node barrier) { barrier instanceof Barrier } predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { - any(RegexInjectionAdditionalFlowStep s).step(nodeFrom, nodeTo) + any(AdditionalFlowStep s).step(nodeFrom, nodeTo) } } diff --git a/rust/ql/src/queries/security/CWE-089/SqlInjection.ql b/rust/ql/src/queries/security/CWE-089/SqlInjection.ql index ee2a3d14486..803cb67e33e 100644 --- a/rust/ql/src/queries/security/CWE-089/SqlInjection.ql +++ b/rust/ql/src/queries/security/CWE-089/SqlInjection.ql @@ -20,11 +20,13 @@ import SqlInjectionFlow::PathGraph * A taint configuration for tainted data that reaches a SQL sink. */ module SqlInjectionConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node node) { node instanceof SqlInjection::Source } + import SqlInjection - predicate isSink(DataFlow::Node node) { node instanceof SqlInjection::Sink } + predicate isSource(DataFlow::Node node) { node instanceof Source } - predicate isBarrier(DataFlow::Node barrier) { barrier instanceof SqlInjection::Barrier } + predicate isSink(DataFlow::Node node) { node instanceof Sink } + + predicate isBarrier(DataFlow::Node barrier) { barrier instanceof Barrier } } module SqlInjectionFlow = TaintTracking::Global; diff --git a/rust/ql/src/queries/security/CWE-311/CleartextTransmission.ql b/rust/ql/src/queries/security/CWE-311/CleartextTransmission.ql index ccf01f6fdda..84b88c3f145 100644 --- a/rust/ql/src/queries/security/CWE-311/CleartextTransmission.ql +++ b/rust/ql/src/queries/security/CWE-311/CleartextTransmission.ql @@ -22,14 +22,16 @@ import codeql.rust.security.CleartextTransmissionExtensions * transmitted over a network. */ module CleartextTransmissionConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node node) { node instanceof SensitiveData } + import CleartextTransmission - predicate isSink(DataFlow::Node node) { node instanceof CleartextTransmissionSink } + predicate isSource(DataFlow::Node node) { node instanceof Source } - predicate isBarrier(DataFlow::Node barrier) { barrier instanceof CleartextTransmissionBarrier } + predicate isSink(DataFlow::Node node) { node instanceof Sink } + + predicate isBarrier(DataFlow::Node barrier) { barrier instanceof Barrier } predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { - any(CleartextTransmissionAdditionalFlowStep s).step(nodeFrom, nodeTo) + any(AdditionalFlowStep s).step(nodeFrom, nodeTo) } predicate isBarrierIn(DataFlow::Node node) { diff --git a/rust/ql/test/query-tests/security/CWE-020/RegexInjectionSink.ql b/rust/ql/test/query-tests/security/CWE-020/RegexInjectionSink.ql index 0723ec5bb5b..c7da47a1172 100644 --- a/rust/ql/test/query-tests/security/CWE-020/RegexInjectionSink.ql +++ b/rust/ql/test/query-tests/security/CWE-020/RegexInjectionSink.ql @@ -1,4 +1,4 @@ private import codeql.rust.dataflow.DataFlow private import codeql.rust.security.regex.RegexInjectionExtensions -query predicate regexInjectionSink(DataFlow::Node node) { node instanceof RegexInjectionSink } +query predicate regexInjectionSink(DataFlow::Node node) { node instanceof RegexInjection::Sink } From 0db551032c21dabe50b2ec0c48ad28b7dc98973e Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 4 Apr 2025 18:23:53 +0100 Subject: [PATCH 3/5] Rust: Make imports consistent and correct. --- .../rust/security/CleartextTransmissionExtensions.qll | 1 + rust/ql/src/queries/security/CWE-022/TaintedPath.ql | 7 ++++--- rust/ql/src/queries/security/CWE-089/SqlInjection.ql | 3 ++- .../src/queries/security/CWE-311/CleartextTransmission.ql | 1 - rust/ql/src/queries/security/CWE-312/CleartextLogging.ql | 2 +- .../queries/security/CWE-328/WeakSensitiveDataHashing.ql | 2 +- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/rust/ql/lib/codeql/rust/security/CleartextTransmissionExtensions.qll b/rust/ql/lib/codeql/rust/security/CleartextTransmissionExtensions.qll index 2c528dddd9e..2dfe77ee8ba 100644 --- a/rust/ql/lib/codeql/rust/security/CleartextTransmissionExtensions.qll +++ b/rust/ql/lib/codeql/rust/security/CleartextTransmissionExtensions.qll @@ -7,6 +7,7 @@ private import codeql.util.Unit private import rust private import codeql.rust.dataflow.DataFlow private import codeql.rust.dataflow.FlowSink +private import codeql.rust.security.SensitiveData private import codeql.rust.Concepts /** diff --git a/rust/ql/src/queries/security/CWE-022/TaintedPath.ql b/rust/ql/src/queries/security/CWE-022/TaintedPath.ql index fcc1c89ef66..8896cf60842 100644 --- a/rust/ql/src/queries/security/CWE-022/TaintedPath.ql +++ b/rust/ql/src/queries/security/CWE-022/TaintedPath.ql @@ -16,11 +16,10 @@ import rust import codeql.rust.dataflow.DataFlow -import codeql.rust.dataflow.internal.DataFlowImpl as DataflowImpl import codeql.rust.dataflow.TaintTracking +import codeql.rust.dataflow.internal.DataFlowImpl as DataflowImpl +import codeql.rust.Concepts import codeql.rust.security.TaintedPathExtensions -import TaintedPathFlow::PathGraph -private import codeql.rust.Concepts newtype NormalizationState = /** A state signifying that the file path has not been normalized. */ @@ -84,6 +83,8 @@ module TaintedPathConfig implements DataFlow::StateConfigSig { module TaintedPathFlow = TaintTracking::GlobalWithState; +import TaintedPathFlow::PathGraph + from TaintedPathFlow::PathNode source, TaintedPathFlow::PathNode sink where TaintedPathFlow::flowPath(source, sink) select sink.getNode(), source, sink, "This path depends on a $@.", source.getNode(), diff --git a/rust/ql/src/queries/security/CWE-089/SqlInjection.ql b/rust/ql/src/queries/security/CWE-089/SqlInjection.ql index 803cb67e33e..f61295263bf 100644 --- a/rust/ql/src/queries/security/CWE-089/SqlInjection.ql +++ b/rust/ql/src/queries/security/CWE-089/SqlInjection.ql @@ -14,7 +14,6 @@ import rust import codeql.rust.dataflow.DataFlow import codeql.rust.dataflow.TaintTracking import codeql.rust.security.SqlInjectionExtensions -import SqlInjectionFlow::PathGraph /** * A taint configuration for tainted data that reaches a SQL sink. @@ -31,6 +30,8 @@ module SqlInjectionConfig implements DataFlow::ConfigSig { module SqlInjectionFlow = TaintTracking::Global; +import SqlInjectionFlow::PathGraph + from SqlInjectionFlow::PathNode sourceNode, SqlInjectionFlow::PathNode sinkNode where SqlInjectionFlow::flowPath(sourceNode, sinkNode) select sinkNode.getNode(), sourceNode, sinkNode, "This query depends on a $@.", diff --git a/rust/ql/src/queries/security/CWE-311/CleartextTransmission.ql b/rust/ql/src/queries/security/CWE-311/CleartextTransmission.ql index 84b88c3f145..739dca0f418 100644 --- a/rust/ql/src/queries/security/CWE-311/CleartextTransmission.ql +++ b/rust/ql/src/queries/security/CWE-311/CleartextTransmission.ql @@ -13,7 +13,6 @@ import rust import codeql.rust.dataflow.DataFlow -import codeql.rust.security.SensitiveData import codeql.rust.dataflow.TaintTracking import codeql.rust.security.CleartextTransmissionExtensions diff --git a/rust/ql/src/queries/security/CWE-312/CleartextLogging.ql b/rust/ql/src/queries/security/CWE-312/CleartextLogging.ql index fd6d538f13f..75bd47e76dc 100644 --- a/rust/ql/src/queries/security/CWE-312/CleartextLogging.ql +++ b/rust/ql/src/queries/security/CWE-312/CleartextLogging.ql @@ -14,9 +14,9 @@ */ import rust -import codeql.rust.security.CleartextLoggingExtensions import codeql.rust.dataflow.DataFlow import codeql.rust.dataflow.TaintTracking +import codeql.rust.security.CleartextLoggingExtensions /** * A taint-tracking configuration for cleartext logging vulnerabilities. diff --git a/rust/ql/src/queries/security/CWE-328/WeakSensitiveDataHashing.ql b/rust/ql/src/queries/security/CWE-328/WeakSensitiveDataHashing.ql index b22fe576212..0f8d23fbc29 100755 --- a/rust/ql/src/queries/security/CWE-328/WeakSensitiveDataHashing.ql +++ b/rust/ql/src/queries/security/CWE-328/WeakSensitiveDataHashing.ql @@ -13,9 +13,9 @@ */ import rust -import codeql.rust.security.WeakSensitiveDataHashingExtensions import codeql.rust.dataflow.DataFlow import codeql.rust.dataflow.TaintTracking +import codeql.rust.security.WeakSensitiveDataHashingExtensions /** * Provides a taint-tracking configuration for detecting use of a broken or weak From 47ee6c6b815b1ecd86a265c8d6972315b23f767d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 4 Apr 2025 18:27:16 +0100 Subject: [PATCH 4/5] Rust: Give regex injection extendable sources as well. --- .../rust/security/regex/RegexInjectionExtensions.qll | 10 ++++++++++ rust/ql/src/queries/security/CWE-020/RegexInjection.ql | 3 +-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/rust/ql/lib/codeql/rust/security/regex/RegexInjectionExtensions.qll b/rust/ql/lib/codeql/rust/security/regex/RegexInjectionExtensions.qll index 5c0f8b616b6..36ae9116724 100644 --- a/rust/ql/lib/codeql/rust/security/regex/RegexInjectionExtensions.qll +++ b/rust/ql/lib/codeql/rust/security/regex/RegexInjectionExtensions.qll @@ -15,6 +15,11 @@ private import codeql.rust.Concepts * injection vulnerabilities, as well as extension points for adding your own. */ module RegexInjection { + /** + * A data flow source for regular expression injection vulnerabilities. + */ + abstract class Source extends DataFlow::Node { } + /** * A data flow sink for regular expression injection vulnerabilities. */ @@ -27,6 +32,11 @@ module RegexInjection { */ abstract class Barrier extends DataFlow::Node { } + /** + * An active threat-model source, considered as a flow source. + */ + private class ActiveThreatModelSourceAsSource extends Source, ActiveThreatModelSource { } + /** * A sink for `a` in `Regex::new(a)` when `a` is not a literal. */ diff --git a/rust/ql/src/queries/security/CWE-020/RegexInjection.ql b/rust/ql/src/queries/security/CWE-020/RegexInjection.ql index 075f6e99d11..14d6d8e167e 100644 --- a/rust/ql/src/queries/security/CWE-020/RegexInjection.ql +++ b/rust/ql/src/queries/security/CWE-020/RegexInjection.ql @@ -17,7 +17,6 @@ private import rust private import codeql.rust.dataflow.DataFlow private import codeql.rust.dataflow.TaintTracking -private import codeql.rust.Concepts private import codeql.rust.security.regex.RegexInjectionExtensions /** @@ -26,7 +25,7 @@ private import codeql.rust.security.regex.RegexInjectionExtensions module RegexInjectionConfig implements DataFlow::ConfigSig { import RegexInjection - predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource } + predicate isSource(DataFlow::Node source) { source instanceof Source } predicate isSink(DataFlow::Node sink) { sink instanceof Sink } From ff78c45e500aa52bc33e1682536f3320e6a361e9 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 4 Apr 2025 18:33:27 +0100 Subject: [PATCH 5/5] Rust: Abstractions then implementations. --- .../regex/RegexInjectionExtensions.qll | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/rust/ql/lib/codeql/rust/security/regex/RegexInjectionExtensions.qll b/rust/ql/lib/codeql/rust/security/regex/RegexInjectionExtensions.qll index 36ae9116724..4daff543b98 100644 --- a/rust/ql/lib/codeql/rust/security/regex/RegexInjectionExtensions.qll +++ b/rust/ql/lib/codeql/rust/security/regex/RegexInjectionExtensions.qll @@ -32,6 +32,17 @@ module RegexInjection { */ abstract class Barrier extends DataFlow::Node { } + /** + * A unit class for adding additional flow steps. + */ + class AdditionalFlowStep extends Unit { + /** + * Holds if the step from `node1` to `node2` should be considered a flow + * step for paths related to regular expression injection vulnerabilities. + */ + abstract predicate step(DataFlow::Node node1, DataFlow::Node node2); + } + /** * An active threat-model source, considered as a flow source. */ @@ -59,17 +70,6 @@ module RegexInjection { ModelsAsDataSink() { sinkNode(this, "regex-use") } } - /** - * A unit class for adding additional flow steps. - */ - class AdditionalFlowStep extends Unit { - /** - * Holds if the step from `node1` to `node2` should be considered a flow - * step for paths related to regular expression injection vulnerabilities. - */ - abstract predicate step(DataFlow::Node node1, DataFlow::Node node2); - } - /** * An escape barrier for regular expression injection vulnerabilities. */