Skip to content

Commit 53d61c4

Browse files
committed
Use custom Sink
1 parent 36cc7b5 commit 53d61c4

4 files changed

Lines changed: 26 additions & 6 deletions

File tree

python/ql/src/experimental/Security/CWE-730/RegexInjection.ql

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@ import python
1616
import experimental.semmle.python.security.injection.RegexInjection
1717
import DataFlow::PathGraph
1818

19-
from RegexInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
20-
where config.hasFlowPath(source, sink)
21-
select sink.getNode(), source, sink, "$@ regular expression is constructed from a $@.",
22-
sink.getNode(), "This", source.getNode(), "user-provided value"
19+
from
20+
RegexInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink,
21+
Attribute sinkAttribute
22+
where
23+
config.hasFlowPath(source, sink) and
24+
sinkAttribute = sink.getNode().(RegexInjectionSink).getRegexMethod()
25+
select sink.getNode(), source, sink,
26+
"$@ regular expression is constructed from a $@ and executed by $@.", sink.getNode(), "This",
27+
source.getNode(), "user-provided value", sinkAttribute,
28+
sinkAttribute.getObject().toString() + "." + sinkAttribute.getName()

python/ql/src/experimental/semmle/python/Concepts.qll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,16 @@ class RegexEscape extends DataFlow::Node {
7676

7777
DataFlow::CallCfgNode getEscapeMethod() { result = range.getEscapeMethod() }
7878
}
79+
80+
class RegexInjectionSink extends DataFlow::Node {
81+
Attribute regexMethod;
82+
83+
RegexInjectionSink() {
84+
exists(RegexExecution reExec |
85+
this = reExec.getRegexNode() and
86+
regexMethod = reExec.getRegexMethod().getFunction().asExpr().(Attribute)
87+
)
88+
}
89+
90+
Attribute getRegexMethod() { result = regexMethod }
91+
}

python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ private module Re {
2424
DataFlow::CallCfgNode regexMethod;
2525

2626
DirectRegex() {
27+
// this.getLocation().getFile().getBaseName().regexpMatch("^re_(good|bad)\\.py$") and // debug
2728
this = API::moduleImport("re").getMember(any(ReMethods m)).getACall() and
2829
regexNode = this.getArg(0) and
2930
regexMethod = this
@@ -41,6 +42,7 @@ private module Re {
4142

4243
CompiledRegex() {
4344
exists(DataFlow::CallCfgNode patternCall, DataFlow::AttrRead reMethod |
45+
// this.getLocation().getFile().getBaseName().regexpMatch("^re_(good|bad)\\.py$") and // debug
4446
this.getFunction() = reMethod and
4547
patternCall = API::moduleImport("re").getMember("compile").getACall() and
4648
patternCall = reMethod.getObject().getALocalSource() and

python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import experimental.semmle.python.Concepts
88
import semmle.python.dataflow.new.DataFlow
99
import semmle.python.dataflow.new.TaintTracking
1010
import semmle.python.dataflow.new.RemoteFlowSources
11-
import semmle.python.ApiGraphs
1211

1312
/**
1413
* A taint-tracking configuration for detecting regular expression injections.
@@ -18,7 +17,7 @@ class RegexInjectionFlowConfig extends TaintTracking::Configuration {
1817

1918
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
2019

21-
override predicate isSink(DataFlow::Node sink) { sink = any(RegexExecution re).getRegexNode() }
20+
override predicate isSink(DataFlow::Node sink) { sink instanceof RegexInjectionSink }
2221

2322
override predicate isSanitizer(DataFlow::Node sanitizer) {
2423
sanitizer = any(RegexEscape reEscape).getRegexNode()

0 commit comments

Comments
 (0)