Skip to content

Commit caac1ae

Browse files
committed
Add some comments and docstrings
1 parent 5d52200 commit caac1ae

File tree

1 file changed

+62
-4
lines changed

1 file changed

+62
-4
lines changed

javascript/frameworks/cap/lib/advanced_security/javascript/frameworks/cap/CAPCqlInjectionQuery.qll

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,15 @@ class CqlClauseWithStringConcatParameter instanceof CqlClause {
2121
(
2222
if this instanceof CqlInsertClause or this instanceof CqlUpsertClause
2323
then
24-
queryParameter = this.getArgument().flow() or
24+
queryParameter = this.getArgument().flow()
25+
or
26+
/*
27+
* Account for cases where an object with a string concatenation is passed. e.g.
28+
* ``` javascript
29+
* let insertQuery = INSERT.into`SomeEntity`.entries({col1: "column_" + col});
30+
* ```
31+
*/
32+
2533
queryParameter = this.getArgument().flow().(SourceNode).getAPropertyWrite().getRhs()
2634
else queryParameter = this.getArgument().flow()
2735
) and
@@ -34,6 +42,10 @@ class CqlClauseWithStringConcatParameter instanceof CqlClause {
3442
string toString() { result = super.toString() }
3543
}
3644

45+
/**
46+
* An await expression that has as its operand a CQL clause that includes a
47+
* string concatenation operation.
48+
*/
3749
class AwaitCqlClauseWithStringConcatParameter extends CqlInjectionSink {
3850
DataFlow::Node queryParameter;
3951
DataFlow::Node query;
@@ -49,17 +61,46 @@ class AwaitCqlClauseWithStringConcatParameter extends CqlInjectionSink {
4961
override DataFlow::Node getQuery() { result = cqlClauseWithStringConcat.(CqlClause).flow() }
5062
}
5163

52-
class ParameterOfCqlRunMethodQueryArgument extends CqlInjectionSink {
64+
/**
65+
* The first argument passed to the call to `cds.run`, `cds.db.run`, or `srv.run`
66+
* whose value is a CQL query object that includes a string concatenation. e.g.
67+
* ``` javascript
68+
* // 1. CQN object constructed from Fluent API
69+
* const query = SELECT.from`Entity1`.where("ID=" + id);
70+
* cds.run(query);
71+
*
72+
* // 2. CQN object parsed from a string
73+
* const query = cds.parse.cql("SELECT * from Entity1 where ID =" + id);
74+
* cds.run(query);
75+
*
76+
* // 3. An unparsed CQL string (only valid in old versions of CAP)
77+
* const query = "SELECT * from Entity1 where ID =" + id;
78+
* Service2.run(query);
79+
* ```
80+
* The `getQuery/0` member predicate gets the `query` argument of the above calls
81+
* to `run`
82+
*/
83+
class StringConcatParameterOfCqlRunMethodQueryArgument extends CqlInjectionSink {
5384
CqlRunMethodCall cqlRunMethodCall;
5485

55-
ParameterOfCqlRunMethodQueryArgument() { this = cqlRunMethodCall.getAQueryParameter() }
86+
StringConcatParameterOfCqlRunMethodQueryArgument() {
87+
this = cqlRunMethodCall.getAQueryParameter()
88+
}
5689

5790
override DataFlow::Node getQuery() { result = this }
5891
}
5992

6093
/**
6194
* A CQL shortcut method call (`read`, `create`, ...) parameterized with a string
62-
* concatenation expression.
95+
* concatenation expression. e.g.
96+
* ``` javascript
97+
* cds.read("Entity1").where(`ID=${id}`); // Notice the surrounding parentheses!
98+
* cds.create("Entity1").entries({id: "" + id});
99+
* cds.update("Entity1").set("col1 = col1" + amount).where("col1 = " + id);
100+
* cds.insert("Entity1").entries({id: "" + id});
101+
* cds.upsert("Entity1").entries({id: "" + id});
102+
* cds.delete("Entity1").where("ID =" + id);
103+
* ```
63104
*/
64105
class CqlShortcutMethodCallWithStringConcat instanceof CqlShortcutMethodCall {
65106
DataFlow::Node stringConcatParameter;
@@ -76,6 +117,23 @@ class CqlShortcutMethodCallWithStringConcat instanceof CqlShortcutMethodCall {
76117
DataFlow::Node getStringConcatParameter() { result = stringConcatParameter }
77118
}
78119

120+
/**
121+
* A string concatenation expression included in a CQL shortcut method call. e.g.
122+
* ``` javascript
123+
* cds.read("Entity1").where(`ID=${id}`); // Notice the surrounding parentheses!
124+
* cds.create("Entity1").entries({id: "" + id});
125+
* cds.update("Entity1").set("col1 = col1" + amount).where("col1 = " + id);
126+
* cds.insert("Entity1").entries({id: "" + id});
127+
* cds.upsert("Entity1").entries({id: "" + id});
128+
* cds.delete("Entity1").where("ID =" + id);
129+
* ```
130+
* This class captures the string concatenation expressions appearing above:
131+
* 1. `ID=${id}`
132+
* 2. `"" + id`
133+
* 3. `"col1 = col1" + amount`
134+
* 4. `"col1 = " + id`
135+
* 5. `"ID =" + id`
136+
*/
79137
class StringConcatParameterOfCqlShortcutMethodCall extends CqlInjectionSink {
80138
CqlShortcutMethodCallWithStringConcat cqlShortcutMethodCallWithStringConcat;
81139

0 commit comments

Comments
 (0)