@@ -4,6 +4,14 @@ import advanced_security.javascript.frameworks.cap.CQL
44import advanced_security.javascript.frameworks.cap.RemoteFlowSources
55import advanced_security.javascript.frameworks.cap.dataflow.FlowSteps
66
7+ abstract class CqlInjectionSink extends DataFlow:: Node {
8+ /**
9+ * Gets the data flow node that represents the query being run, for
10+ * accurate reporting.
11+ */
12+ abstract DataFlow:: Node getQuery ( ) ;
13+ }
14+
715/**
816 * A CQL clause parameterized with a string concatentation expression.
917 */
@@ -26,12 +34,35 @@ class CqlClauseWithStringConcatParameter instanceof CqlClause {
2634 string toString ( ) { result = super .toString ( ) }
2735}
2836
37+ class AwaitCqlClauseWithStringConcatParameter extends CqlInjectionSink {
38+ DataFlow:: Node queryParameter ;
39+ DataFlow:: Node query ;
40+ CqlClauseWithStringConcatParameter cqlClauseWithStringConcat ;
41+
42+ AwaitCqlClauseWithStringConcatParameter ( ) {
43+ exists ( AwaitExpr await |
44+ this = await .flow ( ) and
45+ await .getOperand ( ) = cqlClauseWithStringConcat .( CqlClause ) .asExpr ( )
46+ )
47+ }
48+
49+ override DataFlow:: Node getQuery ( ) { result = cqlClauseWithStringConcat .( CqlClause ) .flow ( ) }
50+ }
51+
52+ class ParameterOfCqlRunMethodQueryArgument extends CqlInjectionSink {
53+ CqlRunMethodCall cqlRunMethodCall ;
54+
55+ ParameterOfCqlRunMethodQueryArgument ( ) { this = cqlRunMethodCall .getAQueryParameter ( ) }
56+
57+ override DataFlow:: Node getQuery ( ) { result = this }
58+ }
59+
2960/**
3061 * A CQL shortcut method call (`read`, `create`, ...) parameterized with a string
3162 * concatenation expression.
3263 */
3364class CqlShortcutMethodCallWithStringConcat instanceof CqlShortcutMethodCall {
34- DataFlow:: Node stringConcatParameter ;
65+ DataFlow:: Node stringConcatParameter ;
3566
3667 CqlShortcutMethodCallWithStringConcat ( ) {
3768 stringConcatParameter = super .getAQueryParameter ( ) and
@@ -45,6 +76,16 @@ class CqlShortcutMethodCallWithStringConcat instanceof CqlShortcutMethodCall {
4576 DataFlow:: Node getStringConcatParameter ( ) { result = stringConcatParameter }
4677}
4778
79+ class StringConcatParameterOfCqlShortcutMethodCall extends CqlInjectionSink {
80+ CqlShortcutMethodCallWithStringConcat cqlShortcutMethodCallWithStringConcat ;
81+
82+ StringConcatParameterOfCqlShortcutMethodCall ( ) {
83+ this = cqlShortcutMethodCallWithStringConcat .getStringConcatParameter ( )
84+ }
85+
86+ override DataFlow:: Node getQuery ( ) { result = cqlShortcutMethodCallWithStringConcat }
87+ }
88+
4889/**
4990 * A CQL parser call (`cds.ql`, `cds.parse.cql`, ...) parameterized with a string
5091 * conatenation expression.
@@ -65,20 +106,7 @@ class CqlInjectionConfiguration extends TaintTracking::Configuration {
65106
66107 override predicate isSource ( DataFlow:: Node source ) { source instanceof RemoteFlowSource }
67108
68- override predicate isSink ( DataFlow:: Node node ) {
69- exists ( CqlRunMethodCall cqlRunMethodCall |
70- node = cqlRunMethodCall .( CqlRunMethodCall ) .getAQueryParameter ( )
71- )
72- or
73- exists ( CqlShortcutMethodCallWithStringConcat queryRunnerCall |
74- node = queryRunnerCall .getStringConcatParameter ( )
75- )
76- or
77- exists ( AwaitExpr await , CqlClauseWithStringConcatParameter cqlClauseWithStringConcat |
78- node = await .flow ( ) and
79- await .getOperand ( ) = cqlClauseWithStringConcat .( CqlClause ) .asExpr ( )
80- )
81- }
109+ override predicate isSink ( DataFlow:: Node node ) { node instanceof CqlInjectionSink }
82110
83111 override predicate isSanitizer ( DataFlow:: Node node ) { node instanceof SqlInjection:: Sanitizer }
84112
0 commit comments