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). --- .../codeql/rust/security/CleartextTransmissionExtensions.qll | 5 ++++- rust/ql/lib/codeql/rust/security/TaintedPathExtensions.qll | 4 +++- .../rust/security/WeakSensitiveDataHashingExtensions.qll | 4 ++-- rust/ql/src/queries/summary/Stats.qll | 4 +++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/rust/ql/lib/codeql/rust/security/CleartextTransmissionExtensions.qll b/rust/ql/lib/codeql/rust/security/CleartextTransmissionExtensions.qll index 73495cd1c0d3..8a3892f23474 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 df8c43212b34..5f8d8b77ee82 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 b22e5153ce3a..7b6b6c801d75 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 a24a4eac9c96..45b5bffa8d1d 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.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 -private import codeql.rust.security.regex.RegexInjectionExtensions /** * 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 | 60 ++++++---- .../rust/security/SqlInjectionExtensions.qll | 8 +- .../regex/RegexInjectionExtensions.qll | 103 ++++++++++-------- .../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, 122 insertions(+), 85 deletions(-) diff --git a/rust/ql/lib/codeql/rust/security/CleartextLoggingExtensions.qll b/rust/ql/lib/codeql/rust/security/CleartextLoggingExtensions.qll index e6bbc0d2a2be..559509ad9f8e 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 8a3892f23474..2c528dddd9e4 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" } -} +module CleartextTransmission { + /** + * A data flow source for cleartext transmission vulnerabilities. + */ + abstract class Source extends DataFlow::Node { } -/** - * A barrier for cleartext transmission vulnerabilities. - */ -abstract class CleartextTransmissionBarrier extends DataFlow::Node { } + /** + * 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 unit class for adding additional flow steps. - */ -class CleartextTransmissionAdditionalFlowStep extends Unit { /** - * Holds if the step from `node1` to `node2` should be considered a flow - * step for paths related to cleartext transmission vulnerabilities. + * A barrier for cleartext transmission vulnerabilities. */ - abstract predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo); -} + abstract class Barrier extends DataFlow::Node { } -/** - * A sink defined through MaD. - */ -private class MadCleartextTransmissionSink extends CleartextTransmissionSink { - MadCleartextTransmissionSink() { sinkNode(this, "transmission") } + /** + * 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 9c61fe4aa52d..8ead5ac684ac 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 f1e4060a5cf4..5c0f8b616b6d 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" } -} +module RegexInjection { + /** + * A data flow sink for regular expression injection vulnerabilities. + */ + abstract class Sink extends QuerySink::Range { + override string getSinkType() { result = "RegexInjection" } + } -/** - * A barrier for regular expression injection vulnerabilities. - */ -abstract class RegexInjectionBarrier extends DataFlow::Node { } + /** + * 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 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 - ) + /** + * 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 + ) + } } -} -private class MadRegexInjectionSink extends RegexInjectionSink { - MadRegexInjectionSink() { sinkNode(this, "regex-use") } -} + /** + * 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 RegexInjectionAdditionalFlowStep extends Unit { /** - * Holds if the step from `node1` to `node2` should be considered a flow - * step for paths related to regular expression injection vulnerabilities. + * A unit class for adding additional flow steps. */ - abstract predicate step(DataFlow::Node node1, DataFlow::Node node2); -} + 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 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" + /** + * 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 b49d08969f62..075f6e99d11a 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 ee2a3d144868..803cb67e33e8 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 ccf01f6fddad..84b88c3f145d 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 0723ec5bb5b7..c7da47a11722 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 2c528dddd9e4..2dfe77ee8ba1 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 fcc1c89ef662..8896cf608427 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 803cb67e33e8..f61295263bfb 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 84b88c3f145d..739dca0f4185 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 fd6d538f13f2..75bd47e76dc9 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 b22fe5762128..0f8d23fbc29c 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 5c0f8b616b6d..36ae9116724b 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 075f6e99d11a..14d6d8e167ed 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 36ae9116724b..4daff543b980 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. */