Skip to content

Commit ee462fc

Browse files
committed
Make property read interprocedural and make the barrier more conservative
1 parent b48604e commit ee462fc

File tree

3 files changed

+31
-5
lines changed

3 files changed

+31
-5
lines changed

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ class CdsLogger extends MethodCallNode {
2222
string getName() { result = name }
2323
}
2424

25+
/**
26+
* A template literal that is not interpolated. It is basically a string literal
27+
* defined in backticks (\`\`).
28+
*/
2529
class ConstantOnlyTemplateLiteral extends TemplateLiteral {
2630
ConstantOnlyTemplateLiteral() {
2731
forall(Expr e | e = this.getAnElement() | e instanceof TemplateElement)
@@ -51,9 +55,21 @@ module CAPLogInjectionConfiguration implements DataFlow::ConfigSig {
5155
}
5256

5357
predicate isBarrier(DataFlow::Node node) {
58+
/*
59+
* This predicate includes cases such as:
60+
* 1. An CDS entity element lacking a type annotation.
61+
* - Possibly because it relies on a common aspect.
62+
* 2. An CDS entity element annotated with a non-string type listed above.
63+
*
64+
* Therefore, the data held by the handler parameter data (e.g. `req.data.X`)
65+
* has to be EXPLICITLY annotated as `String` or `LargeString` to be excluded
66+
* from the next condition.
67+
*/
68+
5469
exists(HandlerParameterData handlerParameterData |
5570
node = handlerParameterData and
56-
not handlerParameterData.getType() = ["cds.String", "cds.LargeString"]
71+
/* Note the use of `.. != ..` instead of `not .. = ..` below. */
72+
handlerParameterData.getType() != ["cds.String", "cds.LargeString"]
5773
)
5874
}
5975

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,12 @@ class ServiceInstanceFromConstructor extends ServiceInstance {
184184
* const cds = require("@sap/cds");
185185
* module.exports = class SomeService extends cds.ApplicationService {
186186
* init() {
187-
* this.on("SomeEvent", (req) => { ... } )
187+
* this.on("SomeEvent", (req) => { ... } )
188188
* }
189189
* }
190190
* ```
191191
* This class captures the access to the `this` variable as in `this.on(...)`.
192-
*
192+
*
193193
* e.g.2. Given this code:
194194
* ``` javascript
195195
* const cds = require('@sap/cds');
@@ -424,13 +424,14 @@ class HandlerRegistration extends MethodCallNode {
424424
* this.after("SomeEvent", "SomeEntity", (req, next) => { ... });
425425
* }
426426
* ```
427-
* All parameters named `req` above are captured. Also see `HandlerParameterOfExposedService`
427+
* All parameters named `req` above are captured. Also see
428+
* `RemoteflowSources::HandlerParameterOfExposedService`
428429
* for a subset of this class that is only about handlers exposed to some protocol.
429430
*/
430431
class HandlerParameter extends ParameterNode {
431432
Handler handler;
432433

433-
HandlerParameter() { this = handler.getParameter(0) }
434+
HandlerParameter() { this = isHandlerParameter(handler) }
434435

435436
Handler getHandler() { result = handler }
436437
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,12 @@ private SourceNode cdsApplicationServiceInstantiation(TypeTracker t) {
3939
SourceNode cdsApplicationServiceInstantiation() {
4040
result = cdsApplicationServiceInstantiation(TypeTracker::end())
4141
}
42+
43+
private SourceNode isHandlerParameter(TypeTracker t, Handler handler) {
44+
result = handler.getParameter(0) or
45+
exists(TypeTracker t2 | result = isHandlerParameter(t, handler).track(t2, t))
46+
}
47+
48+
SourceNode isHandlerParameter(Handler handler) {
49+
result = isHandlerParameter(TypeTracker::end(), handler)
50+
}

0 commit comments

Comments
 (0)