Skip to content

Commit b72e2aa

Browse files
committed
JS: address comments and introduce LabeledBarrierGuardNode
1 parent da3e960 commit b72e2aa

File tree

6 files changed

+37
-37
lines changed

6 files changed

+37
-37
lines changed

javascript/ql/src/semmle/javascript/dataflow/Configuration.qll

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ abstract class Configuration extends string {
9393
}
9494

9595
/**
96-
* Holds if `source` is a source of flow labelled with `lbl` that is relevant
96+
* Holds if `source` is a source of flow labeled with `lbl` that is relevant
9797
* for this configuration.
9898
*/
9999
predicate isSource(DataFlow::Node source, FlowLabel lbl) {
@@ -108,7 +108,7 @@ abstract class Configuration extends string {
108108
}
109109

110110
/**
111-
* Holds if `sink` is a sink of flow labelled with `lbl` that is relevant
111+
* Holds if `sink` is a sink of flow labeled with `lbl` that is relevant
112112
* for this configuration.
113113
*/
114114
predicate isSink(DataFlow::Node sink, FlowLabel lbl) {
@@ -146,7 +146,7 @@ abstract class Configuration extends string {
146146
*/
147147
predicate isBarrier(DataFlow::Node node) {
148148
exists (BarrierGuardNode guard |
149-
guard.blocksAllLabels() and
149+
not guard instanceof LabeledBarrierGuardNode and
150150
isBarrierGuard(guard) and
151151
guard.blocks(node)
152152
)
@@ -165,9 +165,9 @@ abstract class Configuration extends string {
165165
/**
166166
* Holds if flow with label `lbl` cannot flow into `node`.
167167
*/
168-
predicate isBarrierForLabel(DataFlow::Node node, FlowLabel lbl) {
169-
exists (BarrierGuardNode guard |
170-
guard.blocksSpecificLabel(lbl) and
168+
predicate isLabeledBarrier(DataFlow::Node node, FlowLabel lbl) {
169+
exists (LabeledBarrierGuardNode guard |
170+
lbl = guard.getALabel() and
171171
isBarrierGuard(guard) and
172172
guard.blocks(node)
173173
)
@@ -309,21 +309,16 @@ abstract class BarrierGuardNode extends DataFlow::Node {
309309
* Holds if this node blocks expression `e` provided it evaluates to `outcome`.
310310
*/
311311
abstract predicate blocks(boolean outcome, Expr e);
312+
}
312313

314+
/**
315+
* A guard node that only blocks specific labels.
316+
*/
317+
abstract class LabeledBarrierGuardNode extends BarrierGuardNode {
313318
/**
314-
* Holds if this barrier guard should block all labels.
315-
*
316-
* To block specific labels only, subclasses should override this with `none()` and
317-
* also override `blocksSpecificLabel`.
318-
*/
319-
predicate blocksAllLabels() { any() }
320-
321-
/**
322-
* Holds if this barrier guard only blocks specific labels, and `label` is one of them.
323-
*
324-
* Subclasses that override this predicate should also override `blocksAllLabels`.
319+
* Get a flow label blocked by this guard node.
325320
*/
326-
predicate blocksSpecificLabel(FlowLabel label) { none() }
321+
abstract FlowLabel getALabel();
327322
}
328323

329324
/**
@@ -597,7 +592,7 @@ private predicate flowThroughCall(DataFlow::Node input, DataFlow::Node invk,
597592
calls(invk, f) and // Do not consider partial calls
598593
reachableFromInput(f, invk, input, ret, cfg, summary) and
599594
not cfg.isBarrier(ret, invk) and
600-
not cfg.isBarrierForLabel(invk, summary.getEndLabel())
595+
not cfg.isLabeledBarrier(invk, summary.getEndLabel())
601596
)
602597
}
603598

@@ -669,7 +664,7 @@ private predicate flowStep(DataFlow::Node pred, DataFlow::Configuration cfg,
669664
) and
670665
not cfg.isBarrier(succ) and
671666
not cfg.isBarrier(pred, succ) and
672-
not cfg.isBarrierForLabel(succ, summary.getEndLabel())
667+
not cfg.isLabeledBarrier(succ, summary.getEndLabel())
673668
}
674669

675670
/**
@@ -694,7 +689,7 @@ private predicate reachableFromSource(DataFlow::Node nd, DataFlow::Configuration
694689
exists (FlowLabel lbl |
695690
isSource(nd, cfg, lbl) and
696691
not cfg.isBarrier(nd) and
697-
not cfg.isBarrierForLabel(nd, lbl) and
692+
not cfg.isLabeledBarrier(nd, lbl) and
698693
summary = MkPathSummary(false, false, lbl, lbl)
699694
)
700695
or
@@ -714,7 +709,7 @@ private predicate onPath(DataFlow::Node nd, DataFlow::Configuration cfg,
714709
reachableFromSource(nd, cfg, summary) and
715710
isSink(nd, cfg, summary.getEndLabel()) and
716711
not cfg.isBarrier(nd) and
717-
not cfg.isBarrierForLabel(nd, summary.getEndLabel())
712+
not cfg.isLabeledBarrier(nd, summary.getEndLabel())
718713
or
719714
exists (DataFlow::Node mid, PathSummary stepSummary |
720715
reachableFromSource(nd, cfg, summary) and

javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ module TaintTracking {
159159

160160
}
161161

162+
/**
163+
* A sanitizer guard node that only blocks specific flow labels.
164+
*/
165+
abstract class LabeledSanitizerGuardNode extends SanitizerGuardNode, DataFlow::LabeledBarrierGuardNode {
166+
}
167+
162168
/**
163169
* DEPRECATED: Override `Configuration::isAdditionalTaintStep` or use
164170
* `AdditionalTaintStep` instead.

javascript/ql/src/semmle/javascript/frameworks/Express.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -489,18 +489,18 @@ module Express {
489489
result = kind
490490
}
491491

492-
override predicate isDeepObject() {
492+
override predicate isUserControlledObject() {
493493
kind = "body" and
494494
exists (ExpressLibraries::BodyParser bodyParser, RouteHandlerExpr expr |
495495
expr.getBody() = rh and
496-
bodyParser.isDeepObject() and
496+
bodyParser.producesUserControlledObjects() and
497497
bodyParser.flowsToExpr(expr.getAMatchingAncestor())
498498
)
499499
or
500500
// If we can't find the middlewares for the route handler,
501501
// but all known body parsers are deep, assume req.body is a deep object.
502502
kind = "body" and
503-
forall(ExpressLibraries::BodyParser bodyParser | bodyParser.isDeepObject())
503+
forall(ExpressLibraries::BodyParser bodyParser | bodyParser.producesUserControlledObjects())
504504
or
505505
kind = "parameter" and
506506
exists (DataFlow::Node request | request = DataFlow::valueNode(rh.getARequestExpr()) |

javascript/ql/src/semmle/javascript/frameworks/ExpressModules.qll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,9 +271,10 @@ module ExpressLibraries {
271271
}
272272

273273
/**
274-
* Holds if this parses the input as JSON or extended URL-encoding.
274+
* Holds if this parses the input as JSON or extended URL-encoding, resulting
275+
* in user-controlled objects (as opposed to user-controlled strings).
275276
*/
276-
predicate isDeepObject() {
277+
predicate producesUserControlledObjects() {
277278
isJson() or isExtendedUrlEncoded()
278279
}
279280
}

javascript/ql/src/semmle/javascript/security/TaintedObject.qll

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ module TaintedObject {
2424
/**
2525
* Gets the flow label representing a deeply tainted object.
2626
*
27-
* A "tainted object" is an array or object whose properties values are all assumed to be tainted as well.
27+
* A "tainted object" is an array or object whose property values are all assumed to be tainted as well.
2828
*
2929
* Note that the presence of the this label generally implies the presence of the `taint` label as well.
3030
*/
@@ -70,25 +70,23 @@ module TaintedObject {
7070
}
7171

7272
/**
73-
* A source of a user-controlled deep object object.
73+
* A source of a user-controlled deep object.
7474
*/
7575
abstract class Source extends DataFlow::Node {}
7676

7777
/** Request input accesses as a JSON source. */
7878
private class RequestInputAsSource extends Source {
7979
RequestInputAsSource() {
80-
this.(HTTP::RequestInputAccess).isDeepObject()
80+
this.(HTTP::RequestInputAccess).isUserControlledObject()
8181
}
8282
}
8383

8484
/**
8585
* Sanitizer guard that blocks deep object taint.
8686
*/
87-
abstract class SanitizerGuard extends TaintTracking::SanitizerGuardNode {
88-
override predicate blocksAllLabels() { none() }
89-
90-
override predicate blocksSpecificLabel(FlowLabel label) {
91-
label = label()
87+
abstract class SanitizerGuard extends TaintTracking::LabeledSanitizerGuardNode {
88+
override FlowLabel getALabel() {
89+
result = label()
9290
}
9391
}
9492

javascript/ql/src/semmle/javascript/security/dataflow/RemoteFlowSources.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ abstract class RemoteFlowSource extends DataFlow::Node {
1212
abstract string getSourceType();
1313

1414
/**
15-
* Holds if this can be a user-controlled deep object, such as a JSON object parsed from user-controlled data.
15+
* Holds if this can be a user-controlled object, such as a JSON object parsed from user-controlled data.
1616
*/
17-
predicate isDeepObject() { none() }
17+
predicate isUserControlledObject() { none() }
1818
}
1919

2020
/**

0 commit comments

Comments
 (0)