@@ -46,6 +46,21 @@ module UnsafeShellCommandConstruction {
4646 */
4747 abstract class Sanitizer extends DataFlow:: Node { }
4848
49+ /**
50+ * A barrier guard for shell command constructed from library input vulnerabilities.
51+ */
52+ abstract class BarrierGuard extends DataFlow:: Node {
53+ /**
54+ * Holds if this node acts as a barrier for data flow, blocking further flow from `e` if `this` evaluates to `outcome`.
55+ */
56+ predicate blocksExpr ( boolean outcome , Expr e ) { none ( ) }
57+ }
58+
59+ /** A subclass of `BarrierGuard` that is used for backward compatibility with the old data flow library. */
60+ abstract class BarrierGuardLegacy extends BarrierGuard , TaintTracking:: SanitizerGuardNode {
61+ override predicate sanitizes ( boolean outcome , Expr e ) { this .blocksExpr ( outcome , e ) }
62+ }
63+
4964 /**
5065 * A parameter of an exported function, seen as a source for shell command constructed from library input.
5166 */
@@ -270,13 +285,13 @@ module UnsafeShellCommandConstruction {
270285 * A sanitizer that sanitizers paths that exist in the file-system.
271286 * For example: `x` is sanitized in `fs.existsSync(x)` or `fs.existsSync(x + "/suffix/path")`.
272287 */
273- class PathExistsSanitizerGuard extends TaintTracking :: SanitizerGuardNode , DataFlow:: CallNode {
288+ class PathExistsSanitizerGuard extends BarrierGuardLegacy , DataFlow:: CallNode {
274289 PathExistsSanitizerGuard ( ) {
275290 this = DataFlow:: moduleMember ( "path" , "exist" ) .getACall ( ) or
276291 this = DataFlow:: moduleMember ( "fs" , "existsSync" ) .getACall ( )
277292 }
278293
279- override predicate sanitizes ( boolean outcome , Expr e ) {
294+ override predicate blocksExpr ( boolean outcome , Expr e ) {
280295 outcome = true and
281296 (
282297 e = this .getArgument ( 0 ) .asExpr ( ) or
@@ -289,26 +304,26 @@ module UnsafeShellCommandConstruction {
289304 * A guard of the form `typeof x === "<T>"`, where `<T>` is "number", or "boolean",
290305 * which sanitizes `x` in its "then" branch.
291306 */
292- class TypeOfSanitizer extends TaintTracking :: SanitizerGuardNode , DataFlow:: ValueNode {
307+ class TypeOfSanitizer extends BarrierGuardLegacy , DataFlow:: ValueNode {
293308 Expr x ;
294309 override EqualityTest astNode ;
295310
296311 TypeOfSanitizer ( ) { TaintTracking:: isTypeofGuard ( astNode , x , [ "number" , "boolean" ] ) }
297312
298- override predicate sanitizes ( boolean outcome , Expr e ) {
313+ override predicate blocksExpr ( boolean outcome , Expr e ) {
299314 outcome = astNode .getPolarity ( ) and
300315 e = x
301316 }
302317 }
303318
304319 /** A guard that checks whether `x` is a number. */
305- class NumberGuard extends TaintTracking :: SanitizerGuardNode instanceof DataFlow:: CallNode {
320+ class NumberGuard extends BarrierGuardLegacy instanceof DataFlow:: CallNode {
306321 Expr x ;
307322 boolean polarity ;
308323
309324 NumberGuard ( ) { TaintTracking:: isNumberGuard ( this , x , polarity ) }
310325
311- override predicate sanitizes ( boolean outcome , Expr e ) { e = x and outcome = polarity }
326+ override predicate blocksExpr ( boolean outcome , Expr e ) { e = x and outcome = polarity }
312327 }
313328
314329 private import semmle.javascript.dataflow.internal.AccessPaths
0 commit comments