JS: Ignore document.all checks explicitly

This commit is contained in:
Asger Feldthaus
2020-06-05 11:34:43 +01:00
parent 696d19cb14
commit ea3560fe07
3 changed files with 44 additions and 5 deletions

View File

@@ -13,19 +13,43 @@
import javascript
import semmle.javascript.DefensiveProgramming
/**
* Holds if `e` looks like a check for `document.all`, which is an unusual browser object which coerces
* to `false` and has typeof `undefined`.
*/
predicate isFalsyObjectCheck(LogicalBinaryExpr e) {
exists(Variable v |
e.getAnOperand().(DefensiveExpressionTest::TypeofUndefinedTest).getOperand() = v.getAnAccess() and
e.getAnOperand().(DefensiveExpressionTest::UndefinedComparison).getOperand() = v.getAnAccess()
)
}
/**
* Holds if `e` is part of a check for `document.all`.
*/
predicate isPartOfFalsyObjectCheck(Expr e) {
exists(LogicalBinaryExpr binary |
isFalsyObjectCheck(binary) and
e = binary.getAnOperand()
)
or
isFalsyObjectCheck(e)
}
from DefensiveExpressionTest e, boolean cv
where
not isPartOfFalsyObjectCheck(e.asExpr()) and
e.getTheTestResult() = cv and
// whitelist
not (
// module environment detection
exists(VarAccess access, string name | name = "exports" or name = "module" |
e.asExpr().(Internal::TypeofUndefinedTest).getOperand() = access and
e.asExpr().(DefensiveExpressionTest::TypeofUndefinedTest).getOperand() = access and
access.getName() = name and
not exists(access.getVariable().getADeclaration())
)
or
// too benign in practice
e instanceof Internal::DefensiveInit
e instanceof DefensiveExpressionTest::DefensiveInit
)
select e, "This guard always evaluates to " + cv + "."