Skip to content

Commit 461bc0d

Browse files
committed
Ruby: configsig rb/unsafe-code-construction
1 parent 3e23a6e commit 461bc0d

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed

ruby/ql/lib/codeql/ruby/security/UnsafeCodeConstructionQuery.qll

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
* Provides a taint-tracking configuration for reasoning about code
33
* constructed from library input vulnerabilities.
44
*
5-
* Note, for performance reasons: only import this file if `Configuration` is needed,
6-
* otherwise `UnsafeCodeConstructionCustomizations` should be imported instead.
5+
* Note, for performance reasons: only import this file if
6+
* `UnsafeCodeConstructionFlow` is needed, otherwise
7+
* `UnsafeCodeConstructionCustomizations` should be imported instead.
78
*/
89

910
import codeql.ruby.DataFlow
@@ -13,8 +14,9 @@ private import codeql.ruby.dataflow.BarrierGuards
1314

1415
/**
1516
* A taint-tracking configuration for detecting code constructed from library input vulnerabilities.
17+
* DEPRECATED: Use `UnsafeCodeConstructionFlow`
1618
*/
17-
class Configuration extends TaintTracking::Configuration {
19+
deprecated class Configuration extends TaintTracking::Configuration {
1820
Configuration() { this = "UnsafeShellCommandConstruction" }
1921

2022
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -37,3 +39,28 @@ class Configuration extends TaintTracking::Configuration {
3739
set.isElementOfTypeOrUnknown("int")
3840
}
3941
}
42+
43+
private module UnsafeCodeConstructionConfig implements DataFlow::ConfigSig {
44+
predicate isSource(DataFlow::Node source) { source instanceof Source }
45+
46+
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
47+
48+
predicate isBarrier(DataFlow::Node node) {
49+
node instanceof StringConstCompareBarrier or
50+
node instanceof StringConstArrayInclusionCallBarrier
51+
}
52+
53+
// override to require the path doesn't have unmatched return steps
54+
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
55+
56+
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet set) {
57+
// allow implicit reads of array elements
58+
isSink(node) and
59+
set.isElementOfTypeOrUnknown("int")
60+
}
61+
}
62+
63+
/**
64+
* Taint-tracking for detecting code constructed from library input vulnerabilities.
65+
*/
66+
module UnsafeCodeConstructionFlow = TaintTracking::Global<UnsafeCodeConstructionConfig>;

ruby/ql/src/queries/security/cwe-094/UnsafeCodeConstruction.ql

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414
*/
1515

1616
import codeql.ruby.security.UnsafeCodeConstructionQuery
17-
import DataFlow::PathGraph
17+
import UnsafeCodeConstructionFlow::PathGraph
1818

19-
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode
20-
where cfg.hasFlowPath(source, sink) and sinkNode = sink.getNode()
19+
from
20+
UnsafeCodeConstructionFlow::PathNode source, UnsafeCodeConstructionFlow::PathNode sink,
21+
Sink sinkNode
22+
where UnsafeCodeConstructionFlow::flowPath(source, sink) and sinkNode = sink.getNode()
2123
select sink.getNode(), source, sink,
2224
"This " + sinkNode.getSinkType() + " which depends on $@ is later $@.", source.getNode(),
2325
"library input", sinkNode.getCodeSink(), "interpreted as code"

0 commit comments

Comments
 (0)