@@ -261,22 +261,24 @@ class PropNameTracking extends DataFlow::Configuration {
261261 }
262262
263263 override predicate isBarrierGuard ( DataFlow:: BarrierGuardNode node ) {
264- node instanceof EqualityGuard or
264+ node instanceof BlacklistEqualityGuard or
265+ node instanceof WhitelistEqualityGuard or
265266 node instanceof HasOwnPropertyGuard or
266267 node instanceof InstanceOfGuard or
267268 node instanceof TypeofGuard or
268- node instanceof ArrayInclusionGuard
269+ node instanceof BlacklistInclusionGuard or
270+ node instanceof WhitelistInclusionGuard
269271 }
270272}
271273
272274/**
273275 * Sanitizer guard of form `x === "__proto__"` or `x === "constructor"`.
274276 */
275- class EqualityGuard extends DataFlow:: LabeledBarrierGuardNode , ValueNode {
277+ class BlacklistEqualityGuard extends DataFlow:: LabeledBarrierGuardNode , ValueNode {
276278 override EqualityTest astNode ;
277279 string propName ;
278280
279- EqualityGuard ( ) {
281+ BlacklistEqualityGuard ( ) {
280282 astNode .getAnOperand ( ) .getStringValue ( ) = propName and
281283 propName = unsafePropName ( )
282284 }
@@ -288,6 +290,24 @@ class EqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNode {
288290 }
289291}
290292
293+ /**
294+ * An equality test with something other than `__proto__` or `constructor`.
295+ */
296+ class WhitelistEqualityGuard extends DataFlow:: LabeledBarrierGuardNode , ValueNode {
297+ override EqualityTest astNode ;
298+
299+ WhitelistEqualityGuard ( ) {
300+ not astNode .getAnOperand ( ) .getStringValue ( ) = unsafePropName ( ) and
301+ astNode .getAnOperand ( ) instanceof Literal
302+ }
303+
304+ override predicate blocks ( boolean outcome , Expr e , FlowLabel label ) {
305+ e = astNode .getAnOperand ( ) and
306+ outcome = astNode .getPolarity ( ) and
307+ label instanceof UnsafePropLabel
308+ }
309+ }
310+
291311/**
292312 * Sanitizer guard for calls to `Object.prototype.hasOwnProperty`.
293313 *
@@ -371,10 +391,10 @@ class TypeofGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::ValueNode
371391/**
372392 * A check of form `["__proto__"].includes(x)` or similar.
373393 */
374- class ArrayInclusionGuard extends DataFlow:: LabeledBarrierGuardNode , InclusionTest {
394+ class BlacklistInclusionGuard extends DataFlow:: LabeledBarrierGuardNode , InclusionTest {
375395 UnsafePropLabel label ;
376396
377- ArrayInclusionGuard ( ) {
397+ BlacklistInclusionGuard ( ) {
378398 exists ( DataFlow:: ArrayCreationNode array |
379399 array .getAnElement ( ) .getStringValue ( ) = label and
380400 array .flowsTo ( getContainerNode ( ) )
@@ -388,6 +408,21 @@ class ArrayInclusionGuard extends DataFlow::LabeledBarrierGuardNode, InclusionTe
388408 }
389409}
390410
411+ /**
412+ * A check of form `xs.includes(x)` or similar, which sanitizes `x` in the true case.
413+ */
414+ class WhitelistInclusionGuard extends DataFlow:: LabeledBarrierGuardNode {
415+ WhitelistInclusionGuard ( ) {
416+ this instanceof TaintTracking:: PositiveIndexOfSanitizer or
417+ this instanceof TaintTracking:: InclusionSanitizer
418+ }
419+
420+ override predicate blocks ( boolean outcome , Expr e , DataFlow:: FlowLabel lbl ) {
421+ this .( TaintTracking:: AdditionalSanitizerGuardNode ) .sanitizes ( outcome , e ) and
422+ lbl instanceof UnsafePropLabel
423+ }
424+ }
425+
391426/**
392427 * Gets a meaningful name for `node` if possible.
393428 */
0 commit comments