Merge branch 'main' of github.com:github/codeql into htmlReg

This commit is contained in:
Erik Krogh Kristensen
2021-10-26 14:46:27 +02:00
2275 changed files with 216237 additions and 23741 deletions

View File

@@ -0,0 +1,25 @@
/**
* Provides classes and predicates for the 'js/unused-local-variable' query.
*/
import javascript
import LanguageFeatures.UnusedIndexVariable
/**
* A local variable that is neither used nor exported, and is not a parameter
* or a function name.
*/
class UnusedLocal extends LocalVariable {
UnusedLocal() {
not exists(getAnAccess()) and
not exists(Parameter p | this = p.getAVariable()) and
not exists(FunctionExpr fe | this = fe.getVariable()) and
not exists(ClassExpr ce | this = ce.getVariable()) and
not exists(ExportDeclaration ed | ed.exportsAs(this, _)) and
not exists(LocalVarTypeAccess type | type.getVariable() = this) and
// avoid double reporting
not unusedIndexVariable(_, this, _) and
// common convention: variables with leading underscore are intentionally unused
getName().charAt(0) != "_"
}
}

View File

@@ -0,0 +1,18 @@
/**
* Provides predicates for working with the DOM type hierarchy.
*/
import semmle.javascript.Externs
/** Holds if `et` is a root interface of the DOM type hierarchy. */
predicate isDOMRootType(ExternalType et) {
exists(string n | n = et.getName() | n = "EventTarget" or n = "StyleSheet")
}
/** Holds if `p` is declared as a property of a DOM class or interface. */
pragma[nomagic]
predicate isDOMProperty(string p) {
exists(ExternalMemberDecl emd | emd.getName() = p |
isDOMRootType(emd.getDeclaringType().getASupertype*())
)
}

View File

@@ -0,0 +1,170 @@
/**
* Provides classes and predicates for the 'js/useless-expression' query.
*/
import javascript
import DOMProperties
import semmle.javascript.frameworks.xUnit
/**
* Holds if `e` appears in a syntactic context where its value is discarded.
*/
predicate inVoidContext(Expr e) {
exists(ExprStmt parent |
// e is a toplevel expression in an expression statement
parent = e.getParent() and
// but it isn't an HTML attribute or a configuration object
not exists(TopLevel tl | tl = parent.getParent() |
tl instanceof CodeInAttribute
or
// if the toplevel in its entirety is of the form `({ ... })`,
// it is probably a configuration object (e.g., a require.js build configuration)
tl.getNumChildStmt() = 1 and e.stripParens() instanceof ObjectExpr
)
)
or
exists(SeqExpr seq, int i, int n |
e = seq.getOperand(i) and
n = seq.getNumOperands()
|
i < n - 1 or inVoidContext(seq)
)
or
exists(ForStmt stmt | e = stmt.getUpdate())
or
exists(ForStmt stmt | e = stmt.getInit() |
// Allow the pattern `for(i; i < 10; i++)`
not e instanceof VarAccess
)
or
exists(LogicalBinaryExpr logical | e = logical.getRightOperand() and inVoidContext(logical))
}
/**
* Holds if `e` is of the form `x;` or `e.p;` and has a JSDoc comment containing a tag.
* In that case, it is probably meant as a declaration and shouldn't be flagged by this query.
*
* This will still flag cases where the JSDoc comment contains no tag at all (and hence carries
* no semantic information), and expression statements with an ordinary (non-JSDoc) comment
* attached to them.
*/
predicate isDeclaration(Expr e) {
(e instanceof VarAccess or e instanceof PropAccess) and
exists(e.getParent().(ExprStmt).getDocumentation().getATag())
}
/**
* Holds if there exists a getter for a property called `name` anywhere in the program.
*/
predicate isGetterProperty(string name) {
// there is a call of the form `Object.defineProperty(..., name, descriptor)` ...
exists(CallToObjectDefineProperty defProp | name = defProp.getPropertyName() |
// ... where `descriptor` defines a getter
defProp.hasPropertyAttributeWrite("get", _)
or
// ... where `descriptor` may define a getter
exists(DataFlow::SourceNode descriptor | descriptor.flowsTo(defProp.getPropertyDescriptor()) |
descriptor.isIncomplete(_)
or
// minimal escape analysis for the descriptor
exists(DataFlow::InvokeNode invk |
not invk = defProp and
descriptor.flowsTo(invk.getAnArgument())
)
)
)
or
// there is an object expression with a getter property `name`
exists(ObjectExpr obj | obj.getPropertyByName(name) instanceof PropertyGetter)
}
/**
* A property access that may invoke a getter.
*/
class GetterPropertyAccess extends PropAccess {
override predicate isImpure() { isGetterProperty(getPropertyName()) }
}
/**
* Holds if `c` is an indirect eval call of the form `(dummy, eval)(...)`, where
* `dummy` is some expression whose value is discarded, and which simply
* exists to prevent the call from being interpreted as a direct eval.
*/
predicate isIndirectEval(CallExpr c, Expr dummy) {
exists(SeqExpr seq | seq = c.getCallee().stripParens() |
dummy = seq.getOperand(0) and
seq.getOperand(1).(GlobalVarAccess).getName() = "eval" and
seq.getNumOperands() = 2
)
}
/**
* Holds if `c` is a call of the form `(dummy, e[p])(...)`, where `dummy` is
* some expression whose value is discarded, and which simply exists
* to prevent the call from being interpreted as a method call.
*/
predicate isReceiverSuppressingCall(CallExpr c, Expr dummy, PropAccess callee) {
exists(SeqExpr seq | seq = c.getCallee().stripParens() |
dummy = seq.getOperand(0) and
seq.getOperand(1) = callee and
seq.getNumOperands() = 2
)
}
/**
* Holds if evaluating `e` has no side effects (except potentially allocating
* and initializing a new object).
*
* For calls, we do not check whether their arguments have any side effects:
* even if they do, the call itself is useless and should be flagged by this
* query.
*/
predicate noSideEffects(Expr e) {
e.isPure()
or
// `new Error(...)`, `new SyntaxError(...)`, etc.
forex(Function f | f = e.flow().(DataFlow::NewNode).getACallee() |
f.(ExternalType).getASupertype*().getName() = "Error"
)
}
/**
* Holds if the expression `e` should be reported as having no effect.
*/
predicate hasNoEffect(Expr e) {
noSideEffects(e) and
inVoidContext(e) and
// disregard pure expressions wrapped in a void(...)
not e instanceof VoidExpr and
// filter out directives (unknown directives are handled by UnknownDirective.ql)
not exists(Directive d | e = d.getExpr()) and
// or about externs
not e.inExternsFile() and
// don't complain about declarations
not isDeclaration(e) and
// exclude DOM properties, which sometimes have magical auto-update properties
not isDOMProperty(e.(PropAccess).getPropertyName()) and
// exclude xUnit.js annotations
not e instanceof XUnitAnnotation and
// exclude common patterns that are most likely intentional
not isIndirectEval(_, e) and
not isReceiverSuppressingCall(_, e, _) and
// exclude anonymous function expressions as statements; these can only arise
// from a syntax error we already flag
not exists(FunctionExpr fe, ExprStmt es | fe = e |
fe = es.getExpr() and
not exists(fe.getName())
) and
// exclude block-level flow type annotations. For example: `(name: empty)`.
not e.(ParExpr).getExpression().getLastToken().getNextToken().getValue() = ":" and
// exclude the first statement of a try block
not e = any(TryStmt stmt).getBody().getStmt(0).(ExprStmt).getExpr() and
// exclude expressions that are alone in a file, and file doesn't contain a function.
not exists(TopLevel top |
top = e.getParent().(ExprStmt).getParent() and
top.getNumChild() = 1 and
not exists(Function fun | fun.getEnclosingContainer() = top)
) and
// ignore Angular templates
not e.getTopLevel() instanceof Angular2::TemplateTopLevel
}

View File

@@ -0,0 +1,40 @@
/**
* Provides a predicate for identifying unused index variables in loops.
*/
import javascript
/**
* Holds if `arr` is of the form `base[idx]` and is nested inside loop `fs`.
*/
private predicate arrayIndexInLoop(IndexExpr arr, Variable base, Expr idx, ForStmt fs) {
arr.getEnclosingStmt().getParentStmt*() = fs.getBody() and
arr.getBase() = base.getAnAccess() and
arr.getIndex() = idx
}
/**
* Gets `e` or a sub-expression `s` resulting from `e` by peeling off unary and binary
* operators, increments, decrements, type assertions, parentheses, sequence expressions,
* and assignments.
*/
private Expr unwrap(Expr e) {
result = e or
result = unwrap(e.(UpdateExpr).getOperand()) or
result = unwrap(e.(UnaryExpr).getOperand()) or
result = unwrap(e.(BinaryExpr).getAnOperand()) or
result = unwrap(e.getUnderlyingValue())
}
/**
* Holds if `rel` is a for-loop condition of the form `idx <= v.length`, but all array
* indices `v[c]` inside the loop body (of which there must be at least one) use a constant
* index `c` instead of an index based on `idx`.
*/
predicate unusedIndexVariable(RelationalComparison rel, Variable idx, Variable v) {
exists(ForStmt fs | fs.getTest() = rel |
unwrap(rel.getLesserOperand()) = idx.getAnAccess() and
rel.getGreaterOperand().(PropAccess).accesses(v.getAnAccess(), "length") and
forex(IndexExpr arr, Expr e | arrayIndexInLoop(arr, v, e, fs) | exists(e.getIntValue()))
)
}

View File

@@ -179,15 +179,7 @@ module DOM {
eltName = attr.getElement().getName() and
attrName = attr.getName()
|
(
eltName = "script" or
eltName = "iframe" or
eltName = "embed" or
eltName = "video" or
eltName = "audio" or
eltName = "source" or
eltName = "track"
) and
eltName = ["script", "iframe", "embed", "video", "audio", "source", "track"] and
attrName = "src"
or
(
@@ -258,11 +250,11 @@ module DOM {
/** Gets a call that queries the DOM for a collection of DOM nodes. */
private DataFlow::SourceNode domElementCollection() {
exists(string collectionName |
collectionName = "getElementsByClassName" or
collectionName = "getElementsByName" or
collectionName = "getElementsByTagName" or
collectionName = "getElementsByTagNameNS" or
collectionName = "querySelectorAll"
collectionName =
[
"getElementsByClassName", "getElementsByName", "getElementsByTagName",
"getElementsByTagNameNS", "querySelectorAll"
]
|
(
result = documentRef().getAMethodCall(collectionName) or
@@ -274,11 +266,8 @@ module DOM {
/** Gets a call that creates a DOM node or queries the DOM for a DOM node. */
private DataFlow::SourceNode domElementCreationOrQuery() {
exists(string methodName |
methodName = "createElement" or
methodName = "createElementNS" or
methodName = "createRange" or
methodName = "getElementById" or
methodName = "querySelector"
methodName =
["createElement", "createElementNS", "createRange", "getElementById", "querySelector"]
|
result = documentRef().getAMethodCall(methodName) or
result = DataFlow::globalVarRef(methodName).getACall()
@@ -465,11 +454,7 @@ module DOM {
private class DefaultRange extends Range {
DefaultRange() {
exists(string propName | this = documentRef().getAPropertyRead(propName) |
propName = "documentURI" or
propName = "documentURIObject" or
propName = "location" or
propName = "referrer" or
propName = "URL"
propName = ["documentURI", "documentURIObject", "location", "referrer", "URL"]
)
or
this = DOM::domValueRef().getAPropertyRead("baseUri")

View File

@@ -14,7 +14,7 @@ private import semmle.javascript.dataflow.internal.FlowSteps
SourceNode getAnEnumeratedArrayElement(SourceNode array) {
exists(MethodCallNode call, string name |
call = array.getAMethodCall(name) and
(name = "forEach" or name = "map") and
name = ["forEach", "map"] and
result = call.getCallback(0).getParameter(0)
)
or

View File

@@ -34,7 +34,7 @@ abstract class Container extends @container {
/**
* Gets a URL representing the location of this container.
*
* For more information see [Providing URLs](https://help.semmle.com/QL/learn-ql/ql/locations.html#providing-urls).
* For more information see [Providing URLs](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/#providing-urls).
*/
abstract string getURL();
@@ -246,13 +246,7 @@ class File extends Container, @file {
* A file type.
*/
class FileType extends string {
FileType() {
this = "javascript" or
this = "html" or
this = "typescript" or
this = "json" or
this = "yaml"
}
FileType() { this = ["javascript", "html", "typescript", "json", "yaml"] }
/**
* Holds if this is the JavaScript file type.

View File

@@ -291,13 +291,7 @@ class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
override predicate isNumbery() {
exists(string name | name = getName() |
name = "number" or
name = "Number" or
name = "double" or
name = "Double" or
name = "int" or
name = "integer" or
name = "Integer"
name = ["number", "Number", "double", "Double", "int", "integer", "Integer"]
)
}

View File

@@ -6,7 +6,7 @@ import javascript
* A location as given by a file, a start line, a start column,
* an end line, and an end column.
*
* For more information about locations see [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* For more information about locations see [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
class Location extends @location {
/** Gets the file for this location. */
@@ -70,7 +70,7 @@ class Location extends @location {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -30,7 +30,11 @@ private DataFlow::Node getAValueExportedByPackage() {
getAnExportFromModule(any(PackageJSON pack | exists(pack.getPackageName())).getMainModule())
or
// module.exports.bar.baz = result;
result = getAValueExportedByPackage().(DataFlow::PropWrite).getRhs()
exists(DataFlow::PropWrite write |
write = getAValueExportedByPackage() and
write.getPropertyName() = publicPropertyName() and
result = write.getRhs()
)
or
// class Foo {
// bar() {} // <- result
@@ -39,15 +43,17 @@ private DataFlow::Node getAValueExportedByPackage() {
exists(DataFlow::SourceNode callee |
callee = getAValueExportedByPackage().(DataFlow::NewNode).getCalleeNode().getALocalSource()
|
result = callee.getAPropertyRead("prototype").getAPropertyWrite().getRhs()
result = callee.getAPropertyRead("prototype").getAPropertyWrite(publicPropertyName()).getRhs()
or
result = callee.(DataFlow::ClassNode).getAnInstanceMethod()
result = callee.(DataFlow::ClassNode).getInstanceMethod(publicPropertyName()) and
not isPrivateMethodDeclaration(result)
)
or
result = getAValueExportedByPackage().getALocalSource()
or
// Nested property reads.
result = getAValueExportedByPackage().(DataFlow::SourceNode).getAPropertyReference()
result =
getAValueExportedByPackage().(DataFlow::SourceNode).getAPropertyReference(publicPropertyName())
or
// module.exports.foo = require("./other-module.js");
exists(Module mod |
@@ -61,9 +67,12 @@ private DataFlow::Node getAValueExportedByPackage() {
// static baz() {} // <- result
// constructor() {} // <- result
// };
exists(DataFlow::ClassNode cla | cla = getAValueExportedByPackage() |
result = cla.getAnInstanceMethod() or
result = cla.getAStaticMethod() or
exists(DataFlow::ClassNode cla |
cla = getAValueExportedByPackage() and
not isPrivateMethodDeclaration(result)
|
result = cla.getInstanceMethod(publicPropertyName()) or
result = cla.getStaticMethod(publicPropertyName()) or
result = cla.getConstructor()
)
or
@@ -120,7 +129,8 @@ private DataFlow::Node getAValueExportedByPackage() {
or
// Object.defineProperty
exists(CallToObjectDefineProperty call |
[call, call.getBaseObject()] = getAValueExportedByPackage()
[call, call.getBaseObject()] = getAValueExportedByPackage() and
call.getPropertyName() = publicPropertyName()
|
result = call.getPropertyDescriptor().getALocalSource().getAPropertyReference("value")
or
@@ -164,9 +174,31 @@ private DataFlow::Node getAValueExportedByPackage() {
* Gets an exported node from the module `mod`.
*/
private DataFlow::Node getAnExportFromModule(Module mod) {
result = mod.getAnExportedValue(_)
result = mod.getAnExportedValue(publicPropertyName())
or
result = mod.getABulkExportedNode()
or
result.analyze().getAValue() = TAbstractModuleObject(mod)
}
/**
* Gets a property name that we consider to be public.
*
* This only allows properties whose first character is a letter or number.
*/
bindingset[result]
private string publicPropertyName() { result.regexpMatch("[a-zA-Z0-9].*") }
/**
* Holds if the given function is part of a private (or protected) method declaration.
*/
private predicate isPrivateMethodDeclaration(DataFlow::FunctionNode func) {
exists(MethodDeclaration decl |
decl.getBody() = func.getFunction() and
(
decl.isPrivate()
or
decl.isProtected()
)
)
}

View File

@@ -236,10 +236,9 @@ module RangeAnalysis {
) {
if exists(r.getImmediatePredecessor())
then linearDefinitionSum(r.getImmediatePredecessor(), xroot, xsign, yroot, ysign, bias)
else
if exists(r.asExpr().getIntValue())
then none() // do not model constants as sums
else (
else (
not exists(r.asExpr().getIntValue()) and // do not model constants as sums
(
exists(AddExpr add, int bias1, int bias2 | r.asExpr() = add |
// r = r1 + r2
linearDefinition(add.getLeftOperand().flow(), xroot, xsign, bias1) and
@@ -257,6 +256,7 @@ module RangeAnalysis {
linearDefinitionSum(r.asExpr().(NegExpr).getOperand().flow(), xroot, -xsign, yroot, -ysign,
-bias)
)
)
}
/**

View File

@@ -14,7 +14,7 @@ class FirstLineOf extends Locatable {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -43,7 +43,7 @@ class LastLineOf extends Locatable {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -417,7 +417,7 @@ class SsaVariable extends TSsaDefinition {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -482,7 +482,7 @@ class SsaDefinition extends TSsaDefinition {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
abstract predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -55,13 +55,7 @@ private class ArrayIterationCallbackAsPartialInvoke extends DataFlow::PartialInv
getNumArgument() = 2 and
// Filter out library methods named 'forEach' etc
not DataFlow::moduleImport(_).flowsTo(getReceiver()) and
exists(string name | name = getMethodName() |
name = "filter" or
name = "forEach" or
name = "map" or
name = "some" or
name = "every"
)
getMethodName() = ["filter", "forEach", "map", "some", "every"]
}
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {

View File

@@ -24,7 +24,7 @@ class XMLLocatable extends @xmllocatable, TXMLLocatable {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -108,7 +108,7 @@ class XMLParent extends @xmlparent {
}
/** Gets the text value contained in this XML parent. */
string getTextValue() { result = allCharactersString() }
string getTextValue() { result = this.allCharactersString() }
/** Gets a printable representation of this XML parent. */
string toString() { result = this.getName() }
@@ -119,7 +119,7 @@ class XMLFile extends XMLParent, File {
XMLFile() { xmlEncoding(this, _) }
/** Gets a printable representation of this XML file. */
override string toString() { result = getName() }
override string toString() { result = this.getName() }
/** Gets the name of this XML file. */
override string getName() { result = File.super.getAbsolutePath() }
@@ -129,14 +129,14 @@ class XMLFile extends XMLParent, File {
*
* Gets the path of this XML file.
*/
deprecated string getPath() { result = getAbsolutePath() }
deprecated string getPath() { result = this.getAbsolutePath() }
/**
* DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead.
*
* Gets the path of the folder that contains this XML file.
*/
deprecated string getFolder() { result = getParentContainer().getAbsolutePath() }
deprecated string getFolder() { result = this.getParentContainer().getAbsolutePath() }
/** Gets the encoding of this XML file. */
string getEncoding() { xmlEncoding(this, result) }
@@ -200,7 +200,7 @@ class XMLDTD extends XMLLocatable, @xmldtd {
*/
class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
/** Holds if this XML element has the given `name`. */
predicate hasName(string name) { name = getName() }
predicate hasName(string name) { name = this.getName() }
/** Gets the name of this XML element. */
override string getName() { xmlElements(this, result, _, _, _) }
@@ -239,7 +239,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
string getAttributeValue(string name) { result = this.getAttribute(name).getValue() }
/** Gets a printable representation of this XML element. */
override string toString() { result = getName() }
override string toString() { result = this.getName() }
}
/**

View File

@@ -109,7 +109,7 @@ class AbstractValue extends TAbstractValue {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `f`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(string f, int startline, int startcolumn, int endline, int endcolumn) {
f = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0

View File

@@ -1776,7 +1776,7 @@ class PathNode extends TPathNode {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -148,7 +148,7 @@ module DataFlow {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
cached
predicate hasLocationInfo(
@@ -1405,14 +1405,7 @@ module DataFlow {
*/
class Incompleteness extends string {
Incompleteness() {
this = "await" or
this = "call" or
this = "eval" or
this = "global" or
this = "heap" or
this = "import" or
this = "namespace" or
this = "yield"
this = ["await", "call", "eval", "global", "heap", "import", "namespace", "yield"]
}
}

View File

@@ -29,13 +29,7 @@ newtype TypeTag =
*/
class TypeofTag extends string {
TypeofTag() {
this = "undefined" or
this = "boolean" or
this = "number" or
this = "string" or
this = "function" or
this = "object" or
this = "symbol"
this = ["undefined", "boolean", "number", "string", "function", "object", "symbol"]
}
}

View File

@@ -924,13 +924,11 @@ module TaintTracking {
pred = invoke.getArgument(0) and
succ = invoke
|
name = "Error" or
name = "EvalError" or
name = "RangeError" or
name = "ReferenceError" or
name = "SyntaxError" or
name = "TypeError" or
name = "URIError"
name =
[
"Error", "EvalError", "RangeError", "ReferenceError", "SyntaxError", "TypeError",
"URIError"
]
)
}
}

View File

@@ -0,0 +1,87 @@
/**
* Provides classes and predicates for classifying files as containing
* generated code, test code, externs declarations, library code or
* template code.
*/
import semmle.javascript.GeneratedCode
import semmle.javascript.frameworks.Testing
import semmle.javascript.frameworks.Templating
import semmle.javascript.dependencies.FrameworkLibraries
/**
* Holds if `e` may be caused by parsing a template file as plain HTML or JavaScript.
*
* We use two heuristics: check for the presence of a known template delimiter preceding
* the error on the same line, and check whether the file name contains `template` or
* `templates`.
*/
predicate maybeCausedByTemplate(JSParseError e) {
exists(File f | f = e.getFile() |
e.getLine().indexOf(Templating::getADelimiter()) <= e.getLocation().getStartColumn()
or
f.getAbsolutePath().regexpMatch("(?i).*\\btemplates?\\b.*")
)
}
/**
* Holds if `e` is an expression in the form `o.p1.p2.p3....pn`.
*/
private predicate isNestedDotExpr(DotExpr e) {
e.getBase() instanceof VarAccess or
isNestedDotExpr(e.getBase())
}
/**
* Holds if `tl` only contains variable declarations and field reads.
*/
private predicate looksLikeExterns(TopLevel tl) {
forex(Stmt s | s.getParent() = tl |
exists(VarDeclStmt vds | vds = s |
forall(VariableDeclarator vd | vd = vds.getADecl() | not exists(vd.getInit()))
)
or
isNestedDotExpr(s.(ExprStmt).getExpr())
)
}
/**
* Holds if `f` is classified as belonging to `category`.
*
* There are currently four categories:
* - `"generated"`: `f` contains generated or minified code;
* - `"test"`: `f` contains test code;
* - `"externs"`: `f` contains externs declarations;
* - `"library"`: `f` contains library code;
* - `"template"`: `f` contains template code.
*/
predicate classify(File f, string category) {
isGenerated(f.getATopLevel()) and category = "generated"
or
(
exists(Test t | t.getFile() = f)
or
exists(string stemExt | stemExt = "test" or stemExt = "spec" |
f = getTestFile(any(File orig), stemExt)
)
or
f.getAbsolutePath().regexpMatch(".*/__(mocks|tests)__/.*")
) and
category = "test"
or
(f.getATopLevel().isExterns() or looksLikeExterns(f.getATopLevel())) and
category = "externs"
or
f.getATopLevel() instanceof FrameworkLibraryInstance and category = "library"
or
exists(JSParseError err | maybeCausedByTemplate(err) |
f = err.getFile() and category = "template"
)
or
// Polymer templates
exists(HTML::Element elt | elt.getName() = "template" |
f = elt.getFile() and
category = "template" and
not f.getExtension() = "vue"
)
}

View File

@@ -152,7 +152,7 @@ module Angular2 {
/** A value that is about to be promoted to a trusted script value. */
private class AngularCodeInjectionSink extends CodeInjection::Sink {
AngularCodeInjectionSink() {
this = domSanitizer().getAMethodCall(["bypassSecurityTrustScript"]).getArgument(0)
this = domSanitizer().getAMethodCall("bypassSecurityTrustScript").getArgument(0)
}
}

View File

@@ -177,15 +177,10 @@ class ModuleApiCallDependencyInjection extends DependencyInjection {
* This method excludes the method names that are also present on the AngularJS '$provide' object.
*/
private int injectableArgPos() {
(
methodName = "directive" or
methodName = "filter" or
methodName = "controller" or
methodName = "animation"
) and
methodName = ["directive", "filter", "controller", "animation"] and
result = 1
or
(methodName = "config" or methodName = "run") and
methodName = ["config", "run"] and
result = 0
}
@@ -199,64 +194,17 @@ class ModuleApiCallDependencyInjection extends DependencyInjection {
* (cf. https://docs.angularjs.org/api/ng/directive/).
*/
private predicate builtinDirective(string name) {
name = "ngApp" or
name = "ngBind" or
name = "ngBindHtml" or
name = "ngBindTemplate" or
name = "ngBlur" or
name = "ngChange" or
name = "ngChecked" or
name = "ngClass" or
name = "ngClassEven" or
name = "ngClassOdd" or
name = "ngClick" or
name = "ngCloak" or
name = "ngController" or
name = "ngCopy" or
name = "ngCsp" or
name = "ngCut" or
name = "ngDblclick" or
name = "ngDisabled" or
name = "ngFocus" or
name = "ngForm" or
name = "ngHide" or
name = "ngHref" or
name = "ngIf" or
name = "ngInclude" or
name = "ngInit" or
name = "ngJq" or
name = "ngKeydown" or
name = "ngKeypress" or
name = "ngKeyup" or
name = "ngList" or
name = "ngMaxlength" or
name = "ngMinlength" or
name = "ngModel" or
name = "ngModelOptions" or
name = "ngMousedown" or
name = "ngMouseenter" or
name = "ngMouseleave" or
name = "ngMousemove" or
name = "ngMouseover" or
name = "ngMouseup" or
name = "ngNonBindable" or
name = "ngOpen" or
name = "ngOptions" or
name = "ngPaste" or
name = "ngPattern" or
name = "ngPluralize" or
name = "ngReadonly" or
name = "ngRepeat" or
name = "ngRequired" or
name = "ngSelected" or
name = "ngShow" or
name = "ngSrc" or
name = "ngSrcset" or
name = "ngStyle" or
name = "ngSubmit" or
name = "ngSwitch" or
name = "ngTransclude" or
name = "ngValue"
name =
[
"ngApp", "ngBind", "ngBindHtml", "ngBindTemplate", "ngBlur", "ngChange", "ngChecked",
"ngClass", "ngClassEven", "ngClassOdd", "ngClick", "ngCloak", "ngController", "ngCopy",
"ngCsp", "ngCut", "ngDblclick", "ngDisabled", "ngFocus", "ngForm", "ngHide", "ngHref", "ngIf",
"ngInclude", "ngInit", "ngJq", "ngKeydown", "ngKeypress", "ngKeyup", "ngList", "ngMaxlength",
"ngMinlength", "ngModel", "ngModelOptions", "ngMousedown", "ngMouseenter", "ngMouseleave",
"ngMousemove", "ngMouseover", "ngMouseup", "ngNonBindable", "ngOpen", "ngOptions", "ngPaste",
"ngPattern", "ngPluralize", "ngReadonly", "ngRepeat", "ngRequired", "ngSelected", "ngShow",
"ngSrc", "ngSrcset", "ngStyle", "ngSubmit", "ngSwitch", "ngTransclude", "ngValue"
]
}
private newtype TDirectiveInstance =
@@ -676,10 +624,7 @@ private class JQLiteObject extends JQuery::ObjectSource::Range {
)
)
or
exists(ServiceReference element |
element.getName() = "$rootElement" or
element.getName() = "$document"
|
exists(ServiceReference element | element.getName() = ["$rootElement", "$document"] |
this = element.getAReference()
)
}
@@ -780,23 +725,17 @@ private class BuiltinServiceCall extends AngularJSCall {
override predicate interpretsArgumentAsCode(Expr e) {
exists(ScopeServiceReference scope, string methodName |
methodName = "$apply" or
methodName = "$applyAsync" or
methodName = "$eval" or
methodName = "$evalAsync" or
methodName = "$watch" or
methodName = "$watchCollection" or
methodName = "$watchGroup"
methodName =
[
"$apply", "$applyAsync", "$eval", "$evalAsync", "$watch", "$watchCollection",
"$watchGroup"
]
|
call = scope.getAMethodCall(methodName) and
e = call.getArgument(0)
)
or
exists(ServiceReference service |
service.getName() = "$compile" or
service.getName() = "$parse" or
service.getName() = "$interpolate"
|
exists(ServiceReference service | service.getName() = ["$compile", "$parse", "$interpolate"] |
call = service.getACall() and
e = call.getArgument(0)
)
@@ -952,7 +891,7 @@ class ElementScope extends AngularScope, MkElementScope {
DataFlow::SourceNode routeProviderRef() {
result = builtinServiceRef("$routeProvider")
or
exists(string m | m = "when" or m = "otherwise" | result = routeProviderRef().getAMethodCall(m))
exists(string m | m = ["when", "otherwise"] | result = routeProviderRef().getAMethodCall(m))
}
/**

View File

@@ -277,24 +277,11 @@ private module Lexer {
override string getPattern() {
result =
concat(string op |
op = "===" or
op = "!==" or
op = "==" or
op = "!=" or
op = "<=" or
op = ">=" or
op = "&&" or
op = "||" or
op = "*" or
op = "!" or
op = "=" or
op = "<" or
op = ">" or
op = "+" or
op = "-" or
op = "/" or
op = "%" or
op = "|"
op =
[
"===", "!==", "==", "!=", "<=", ">=", "&&", "||", "*", "!", "=", "<", ">", "+", "-",
"/", "%", "|"
]
|
"\\Q" + op + "\\E", "|" order by op.length() desc
)

View File

@@ -103,25 +103,12 @@ module AsyncPackage {
IterationCall() {
this = memberVariant(name).getACall() and
(
name = "concat" or
name = "detect" or
name = "each" or
name = "eachOf" or
name = "forEach" or
name = "forEachOf" or
name = "every" or
name = "filter" or
name = "groupBy" or
name = "map" or
name = "mapValues" or
name = "reduce" or
name = "reduceRight" or
name = "reject" or
name = "some" or
name = "sortBy" or
name = "transform"
)
name =
[
"concat", "detect", "each", "eachOf", "forEach", "forEachOf", "every", "filter",
"groupBy", "map", "mapValues", "reduce", "reduceRight", "reject", "some", "sortBy",
"transform"
]
}
/**
@@ -176,10 +163,7 @@ module AsyncPackage {
pred = getLastParameter(iteratee).getACall().getArgument(i) and
succ = final.getParameter(i) and
exists(string name | name = call.getName() |
name = "concat" or
name = "map" or
name = "reduce" or
name = "reduceRight"
name = ["concat", "map", "reduce", "reduceRight"]
)
)
}

View File

@@ -82,7 +82,7 @@ module FunctionCompositionCall {
/** A call whose arguments are functions `f,g,h` which are composed into `f(g(h(...))` */
private class RightToLeft extends WithArrayOverloading {
RightToLeft() {
this = DataFlow::moduleImport(["compose-function"]).getACall()
this = DataFlow::moduleImport("compose-function").getACall()
or
this =
DataFlow::moduleMember(["redux", "ramda", "@reduxjs/toolkit", "recompose"], "compose")

View File

@@ -408,14 +408,7 @@ private module Forge {
this = mod.getAPropertyRead("cipher").getAMemberCall(createName) and
getArgument(0).asExpr().mayHaveStringValue(cipherName) and
cipherName = cipherPrefix + "-" + cipherSuffix and
(
cipherSuffix = "CBC" or
cipherSuffix = "CFB" or
cipherSuffix = "CTR" or
cipherSuffix = "ECB" or
cipherSuffix = "GCM" or
cipherSuffix = "OFB"
) and
cipherSuffix = ["CBC", "CFB", "CTR", "ECB", "GCM", "OFB"] and
algorithmName = cipherPrefix and
key = getArgument(1)
)

View File

@@ -11,13 +11,7 @@ module EventEmitter {
}
/** Gets the name of a method on `EventEmitter` that registers an event handler. */
string on() {
result = "addListener" or
result = "on" or
result = "once" or
result = "prependListener" or
result = "prependOnceListener"
}
string on() { result = ["addListener", "on", "once", "prependListener", "prependOnceListener"] }
/**
* Gets a node that refers to an EventEmitter object.

View File

@@ -378,23 +378,11 @@ module Express {
*/
private predicate isChainableResponseMethodCall(RouteHandler handler, MethodCallExpr call) {
exists(string name | call.calls(handler.getAResponseExpr(), name) |
name = "append" or
name = "attachment" or
name = "clearCookie" or
name = "contentType" or
name = "cookie" or
name = "format" or
name = "header" or
name = "json" or
name = "jsonp" or
name = "links" or
name = "location" or
name = "send" or
name = "sendStatus" or
name = "set" or
name = "status" or
name = "type" or
name = "vary"
name =
[
"append", "attachment", "location", "send", "sendStatus", "set", "status", "type", "vary",
"clearCookie", "contentType", "cookie", "format", "header", "json", "jsonp", "links"
]
)
}

View File

@@ -429,12 +429,7 @@ private class LibraryAccess extends FileSystemAccess, DataFlow::InvokeNode {
this =
DataFlow::moduleMember("node-dir",
any(string s |
s = "readFiles" or
s = "readFilesStream" or
s = "files" or
s = "promiseFiles" or
s = "subdirs" or
s = "paths"
s = ["readFiles", "readFilesStream", "files", "promiseFiles", "subdirs", "paths"]
)).getACall()
)
or

View File

@@ -81,29 +81,12 @@ module HTTP {
*/
class RequestMethodName extends string {
RequestMethodName() {
this = "CHECKOUT" or
this = "COPY" or
this = "DELETE" or
this = "GET" or
this = "HEAD" or
this = "LOCK" or
this = "MERGE" or
this = "MKACTIVITY" or
this = "MKCOL" or
this = "MOVE" or
this = "M-SEARCH" or
this = "NOTIFY" or
this = "OPTIONS" or
this = "PATCH" or
this = "POST" or
this = "PURGE" or
this = "PUT" or
this = "REPORT" or
this = "SEARCH" or
this = "SUBSCRIBE" or
this = "TRACE" or
this = "UNLOCK" or
this = "UNSUBSCRIBE"
this =
[
"CHECKOUT", "COPY", "DELETE", "GET", "HEAD", "LOCK", "MERGE", "MKACTIVITY", "MKCOL",
"MOVE", "M-SEARCH", "NOTIFY", "OPTIONS", "PATCH", "POST", "PURGE", "PUT", "REPORT",
"SEARCH", "SUBSCRIBE", "TRACE", "UNLOCK", "UNSUBSCRIBE"
]
}
/**
@@ -111,14 +94,7 @@ module HTTP {
* such as for `GET` and `HEAD` requests.
*/
predicate isSafe() {
this = "GET" or
this = "HEAD" or
this = "OPTIONS" or
this = "PRI" or
this = "PROPFIND" or
this = "REPORT" or
this = "SEARCH" or
this = "TRACE"
this = ["GET", "HEAD", "OPTIONS", "PRI", "PROPFIND", "REPORT", "SEARCH", "TRACE"]
}
}
@@ -477,13 +453,7 @@ module HTTP {
* Headers are never considered third-party controllable by this predicate, although the
* third party does have some control over the the Referer and Origin headers.
*/
predicate isThirdPartyControllable() {
exists(string kind | kind = getKind() |
kind = "parameter" or
kind = "url" or
kind = "body"
)
}
predicate isThirdPartyControllable() { getKind() = ["parameter", "url", "body"] }
}
/**

View File

@@ -47,312 +47,50 @@ module LodashUnderscore {
*/
private predicate isLodashMember(string name) {
// Can be generated using Object.keys(require('lodash'))
name = "templateSettings" or
name = "after" or
name = "ary" or
name = "assign" or
name = "assignIn" or
name = "assignInWith" or
name = "assignWith" or
name = "at" or
name = "before" or
name = "bind" or
name = "bindAll" or
name = "bindKey" or
name = "castArray" or
name = "chain" or
name = "chunk" or
name = "compact" or
name = "concat" or
name = "cond" or
name = "conforms" or
name = "constant" or
name = "countBy" or
name = "create" or
name = "curry" or
name = "curryRight" or
name = "debounce" or
name = "defaults" or
name = "defaultsDeep" or
name = "defer" or
name = "delay" or
name = "difference" or
name = "differenceBy" or
name = "differenceWith" or
name = "drop" or
name = "dropRight" or
name = "dropRightWhile" or
name = "dropWhile" or
name = "fill" or
name = "filter" or
name = "flatMap" or
name = "flatMapDeep" or
name = "flatMapDepth" or
name = "flatten" or
name = "flattenDeep" or
name = "flattenDepth" or
name = "flip" or
name = "flow" or
name = "flowRight" or
name = "fromPairs" or
name = "functions" or
name = "functionsIn" or
name = "groupBy" or
name = "initial" or
name = "intersection" or
name = "intersectionBy" or
name = "intersectionWith" or
name = "invert" or
name = "invertBy" or
name = "invokeMap" or
name = "iteratee" or
name = "keyBy" or
name = "keys" or
name = "keysIn" or
name = "map" or
name = "mapKeys" or
name = "mapValues" or
name = "matches" or
name = "matchesProperty" or
name = "memoize" or
name = "merge" or
name = "mergeWith" or
name = "method" or
name = "methodOf" or
name = "mixin" or
name = "negate" or
name = "nthArg" or
name = "omit" or
name = "omitBy" or
name = "once" or
name = "orderBy" or
name = "over" or
name = "overArgs" or
name = "overEvery" or
name = "overSome" or
name = "partial" or
name = "partialRight" or
name = "partition" or
name = "pick" or
name = "pickBy" or
name = "property" or
name = "propertyOf" or
name = "pull" or
name = "pullAll" or
name = "pullAllBy" or
name = "pullAllWith" or
name = "pullAt" or
name = "range" or
name = "rangeRight" or
name = "rearg" or
name = "reject" or
name = "remove" or
name = "rest" or
name = "reverse" or
name = "sampleSize" or
name = "set" or
name = "setWith" or
name = "shuffle" or
name = "slice" or
name = "sortBy" or
name = "sortedUniq" or
name = "sortedUniqBy" or
name = "split" or
name = "spread" or
name = "tail" or
name = "take" or
name = "takeRight" or
name = "takeRightWhile" or
name = "takeWhile" or
name = "tap" or
name = "throttle" or
name = "thru" or
name = "toArray" or
name = "toPairs" or
name = "toPairsIn" or
name = "toPath" or
name = "toPlainObject" or
name = "transform" or
name = "unary" or
name = "union" or
name = "unionBy" or
name = "unionWith" or
name = "uniq" or
name = "uniqBy" or
name = "uniqWith" or
name = "unset" or
name = "unzip" or
name = "unzipWith" or
name = "update" or
name = "updateWith" or
name = "values" or
name = "valuesIn" or
name = "without" or
name = "words" or
name = "wrap" or
name = "xor" or
name = "xorBy" or
name = "xorWith" or
name = "zip" or
name = "zipObject" or
name = "zipObjectDeep" or
name = "zipWith" or
name = "entries" or
name = "entriesIn" or
name = "extend" or
name = "extendWith" or
name = "add" or
name = "attempt" or
name = "camelCase" or
name = "capitalize" or
name = "ceil" or
name = "clamp" or
name = "clone" or
name = "cloneDeep" or
name = "cloneDeepWith" or
name = "cloneWith" or
name = "conformsTo" or
name = "deburr" or
name = "defaultTo" or
name = "divide" or
name = "endsWith" or
name = "eq" or
name = "escape" or
name = "escapeRegExp" or
name = "every" or
name = "find" or
name = "findIndex" or
name = "findKey" or
name = "findLast" or
name = "findLastIndex" or
name = "findLastKey" or
name = "floor" or
name = "forEach" or
name = "forEachRight" or
name = "forIn" or
name = "forInRight" or
name = "forOwn" or
name = "forOwnRight" or
name = "get" or
name = "gt" or
name = "gte" or
name = "has" or
name = "hasIn" or
name = "head" or
name = "identity" or
name = "includes" or
name = "indexOf" or
name = "inRange" or
name = "invoke" or
name = "isArguments" or
name = "isArray" or
name = "isArrayBuffer" or
name = "isArrayLike" or
name = "isArrayLikeObject" or
name = "isBoolean" or
name = "isBuffer" or
name = "isDate" or
name = "isElement" or
name = "isEmpty" or
name = "isEqual" or
name = "isEqualWith" or
name = "isError" or
name = "isFinite" or
name = "isFunction" or
name = "isInteger" or
name = "isLength" or
name = "isMap" or
name = "isMatch" or
name = "isMatchWith" or
name = "isNaN" or
name = "isNative" or
name = "isNil" or
name = "isNull" or
name = "isNumber" or
name = "isObject" or
name = "isObjectLike" or
name = "isPlainObject" or
name = "isRegExp" or
name = "isSafeInteger" or
name = "isSet" or
name = "isString" or
name = "isSymbol" or
name = "isTypedArray" or
name = "isUndefined" or
name = "isWeakMap" or
name = "isWeakSet" or
name = "join" or
name = "kebabCase" or
name = "last" or
name = "lastIndexOf" or
name = "lowerCase" or
name = "lowerFirst" or
name = "lt" or
name = "lte" or
name = "max" or
name = "maxBy" or
name = "mean" or
name = "meanBy" or
name = "min" or
name = "minBy" or
name = "stubArray" or
name = "stubFalse" or
name = "stubObject" or
name = "stubString" or
name = "stubTrue" or
name = "multiply" or
name = "nth" or
name = "noConflict" or
name = "noop" or
name = "now" or
name = "pad" or
name = "padEnd" or
name = "padStart" or
name = "parseInt" or
name = "random" or
name = "reduce" or
name = "reduceRight" or
name = "repeat" or
name = "replace" or
name = "result" or
name = "round" or
name = "runInContext" or
name = "sample" or
name = "size" or
name = "snakeCase" or
name = "some" or
name = "sortedIndex" or
name = "sortedIndexBy" or
name = "sortedIndexOf" or
name = "sortedLastIndex" or
name = "sortedLastIndexBy" or
name = "sortedLastIndexOf" or
name = "startCase" or
name = "startsWith" or
name = "subtract" or
name = "sum" or
name = "sumBy" or
name = "template" or
name = "times" or
name = "toFinite" or
name = "toInteger" or
name = "toLength" or
name = "toLower" or
name = "toNumber" or
name = "toSafeInteger" or
name = "toString" or
name = "toUpper" or
name = "trim" or
name = "trimEnd" or
name = "trimStart" or
name = "truncate" or
name = "unescape" or
name = "uniqueId" or
name = "upperCase" or
name = "upperFirst" or
name = "each" or
name = "eachRight" or
name = "first"
name =
[
"templateSettings", "after", "ary", "assign", "assignIn", "assignInWith", "assignWith",
"at", "before", "bind", "bindAll", "bindKey", "castArray", "chain", "chunk", "compact",
"concat", "cond", "conforms", "constant", "countBy", "create", "curry", "curryRight",
"debounce", "defaults", "defaultsDeep", "defer", "delay", "difference", "differenceBy",
"differenceWith", "drop", "dropRight", "dropRightWhile", "dropWhile", "fill", "filter",
"flatMap", "flatMapDeep", "flatMapDepth", "flatten", "flattenDeep", "flattenDepth", "flip",
"flow", "flowRight", "fromPairs", "functions", "functionsIn", "groupBy", "initial",
"intersection", "intersectionBy", "intersectionWith", "invert", "invertBy", "invokeMap",
"iteratee", "keyBy", "keys", "keysIn", "map", "mapKeys", "mapValues", "matches",
"matchesProperty", "memoize", "merge", "mergeWith", "method", "methodOf", "mixin", "negate",
"nthArg", "omit", "omitBy", "once", "orderBy", "over", "overArgs", "overEvery", "overSome",
"partial", "partialRight", "partition", "pick", "pickBy", "property", "propertyOf", "pull",
"pullAll", "pullAllBy", "pullAllWith", "pullAt", "range", "rangeRight", "rearg", "reject",
"remove", "rest", "reverse", "sampleSize", "set", "setWith", "shuffle", "slice", "sortBy",
"sortedUniq", "sortedUniqBy", "split", "spread", "tail", "take", "takeRight",
"takeRightWhile", "takeWhile", "tap", "throttle", "thru", "toArray", "toPairs", "toPairsIn",
"toPath", "toPlainObject", "transform", "unary", "union", "unionBy", "unionWith", "uniq",
"uniqBy", "uniqWith", "unset", "unzip", "unzipWith", "update", "updateWith", "values",
"valuesIn", "without", "words", "wrap", "xor", "xorBy", "xorWith", "zip", "zipObject",
"zipObjectDeep", "zipWith", "entries", "entriesIn", "extend", "extendWith", "add",
"attempt", "camelCase", "capitalize", "ceil", "clamp", "clone", "cloneDeep",
"cloneDeepWith", "cloneWith", "conformsTo", "deburr", "defaultTo", "divide", "endsWith",
"eq", "escape", "escapeRegExp", "every", "find", "findIndex", "findKey", "findLast",
"findLastIndex", "findLastKey", "floor", "forEach", "forEachRight", "forIn", "forInRight",
"forOwn", "forOwnRight", "get", "gt", "gte", "has", "hasIn", "head", "identity", "includes",
"indexOf", "inRange", "invoke", "isArguments", "isArray", "isArrayBuffer", "isArrayLike",
"isArrayLikeObject", "isBoolean", "isBuffer", "isDate", "isElement", "isEmpty", "isEqual",
"isEqualWith", "isError", "isFinite", "isFunction", "isInteger", "isLength", "isMap",
"isMatch", "isMatchWith", "isNaN", "isNative", "isNil", "isNull", "isNumber", "isObject",
"isObjectLike", "isPlainObject", "isRegExp", "isSafeInteger", "isSet", "isString",
"isSymbol", "isTypedArray", "isUndefined", "isWeakMap", "isWeakSet", "join", "kebabCase",
"last", "lastIndexOf", "lowerCase", "lowerFirst", "lt", "lte", "max", "maxBy", "mean",
"meanBy", "min", "minBy", "stubArray", "stubFalse", "stubObject", "stubString", "stubTrue",
"multiply", "nth", "noConflict", "noop", "now", "pad", "padEnd", "padStart", "parseInt",
"random", "reduce", "reduceRight", "repeat", "replace", "result", "round", "runInContext",
"sample", "size", "snakeCase", "some", "sortedIndex", "sortedIndexBy", "sortedIndexOf",
"sortedLastIndex", "sortedLastIndexBy", "sortedLastIndexOf", "startCase", "startsWith",
"subtract", "sum", "sumBy", "template", "times", "toFinite", "toInteger", "toLength",
"toLower", "toNumber", "toSafeInteger", "toString", "toUpper", "trim", "trimEnd",
"trimStart", "truncate", "unescape", "uniqueId", "upperCase", "upperFirst", "each",
"eachRight", "first"
]
}
/**
@@ -363,27 +101,15 @@ module LodashUnderscore {
exists(DataFlow::CallNode call, string name |
// Members ending with By, With, or While indicate that they are a variant of
// another function that takes a callback.
name.matches("%By") or
name.matches("%With") or
name.matches("%While") or
name.matches(["%By", "%With", "%While"])
or
// Other members that don't fit the above pattern.
name = "each" or
name = "eachRight" or
name = "every" or
name = "filter" or
name = "find" or
name = "findLast" or
name = "flatMap" or
name = "flatMapDeep" or
name = "flatMapDepth" or
name = "forEach" or
name = "forEachRight" or
name = "partition" or
name = "reduce" or
name = "reduceRight" or
name = "replace" or
name = "some" or
name = "transform"
name =
[
"each", "eachRight", "every", "filter", "find", "findLast", "flatMap", "flatMapDeep",
"flatMapDepth", "forEach", "forEachRight", "partition", "reduce", "reduceRight",
"replace", "some", "transform"
]
|
call = member(name).getACall() and
pred = call.getAnArgument().(DataFlow::FunctionNode).getExceptionalReturn() and
@@ -461,91 +187,30 @@ private class LodashCallbackAsPartialInvoke extends DataFlow::PartialInvokeNode:
this = LodashUnderscore::member(name).getACall() and
getNumArgument() = argumentCount
|
(
name = "bind" or
name = "callback" or
name = "iteratee"
) and
name = ["bind", "callback", "iteratee"] and
callbackIndex = 0 and
contextIndex = 1 and
argumentCount = 2
or
(
name = "all" or
name = "any" or
name = "collect" or
name = "countBy" or
name = "detect" or
name = "dropRightWhile" or
name = "dropWhile" or
name = "each" or
name = "eachRight" or
name = "every" or
name = "filter" or
name = "find" or
name = "findIndex" or
name = "findKey" or
name = "findLast" or
name = "findLastIndex" or
name = "findLastKey" or
name = "forEach" or
name = "forEachRight" or
name = "forIn" or
name = "forInRight" or
name = "groupBy" or
name = "indexBy" or
name = "map" or
name = "mapKeys" or
name = "mapValues" or
name = "max" or
name = "min" or
name = "omit" or
name = "partition" or
name = "pick" or
name = "reject" or
name = "remove" or
name = "select" or
name = "some" or
name = "sortBy" or
name = "sum" or
name = "takeRightWhile" or
name = "takeWhile" or
name = "tap" or
name = "thru" or
name = "times" or
name = "unzipWith" or
name = "zipWith"
) and
name =
[
"all", "any", "collect", "countBy", "detect", "dropRightWhile", "dropWhile", "each",
"eachRight", "every", "filter", "find", "findIndex", "findKey", "findLast",
"findLastIndex", "findLastKey", "forEach", "forEachRight", "forIn", "forInRight",
"groupBy", "indexBy", "map", "mapKeys", "mapValues", "max", "min", "omit", "partition",
"pick", "reject", "remove", "select", "some", "sortBy", "sum", "takeRightWhile",
"takeWhile", "tap", "thru", "times", "unzipWith", "zipWith"
] and
callbackIndex = 1 and
contextIndex = 2 and
argumentCount = 3
or
(
name = "foldl" or
name = "foldr" or
name = "inject" or
name = "reduce" or
name = "reduceRight" or
name = "transform"
) and
name = ["foldl", "foldr", "inject", "reduce", "reduceRight", "transform"] and
callbackIndex = 1 and
contextIndex = 3 and
argumentCount = 4
or
(
name = "sortedlastIndex"
or
name = "assign"
or
name = "eq"
or
name = "extend"
or
name = "merge"
or
name = "sortedIndex" and
name = "uniq"
) and
name = ["sortedlastIndex", "assign", "eq", "extend", "merge", "sortedIndex", "uniq"] and
callbackIndex = 2 and
contextIndex = 3 and
argumentCount = 4

View File

@@ -18,19 +18,11 @@ abstract class LoggerCall extends DataFlow::CallNode {
* Gets a log level name that is used in RFC5424, `npm`, `console`.
*/
string getAStandardLoggerMethodName() {
result = "crit" or
result = "dir" or
result = "debug" or
result = "error" or
result = "emerg" or
result = "fatal" or
result = "info" or
result = "log" or
result = "notice" or
result = "silly" or
result = "trace" or
result = "verbose" or
result = "warn"
result =
[
"crit", "dir", "trace", "verbose", "warn", "debug", "error", "emerg", "fatal", "info", "log",
"notice", "silly"
]
}
/**

View File

@@ -35,7 +35,7 @@ module MooTools {
predicate interpretsNodeAsHtml(DataFlow::Node node) {
exists(Element e |
node = e.getAnElementPropertyValue("html") or
node = e.getAMethodCall(["appendHtml"]).getArgument(0)
node = e.getAMethodCall("appendHtml").getArgument(0)
)
}
}

View File

@@ -252,28 +252,13 @@ private module Mongoose {
* Holds if Model method `name` returns a Query.
*/
predicate returnsQuery(string name) {
name = "$where" or
name = "count" or
name = "countDocuments" or
name = "deleteMany" or
name = "deleteOne" or
name = "find" or
name = "findById" or
name = "findByIdAndDelete" or
name = "findByIdAndRemove" or
name = "findByIdAndUpdate" or
name = "findOne" or
name = "findOneAndDelete" or
name = "findOneAndRemove" or
name = "findOneAndReplace" or
name = "findOneAndUpdate" or
name = "geosearch" or
name = "remove" or
name = "replaceOne" or
name = "update" or
name = "updateMany" or
name = "updateOne" or
name = "where"
name =
[
"$where", "count", "findOne", "findOneAndDelete", "findOneAndRemove",
"findOneAndReplace", "findOneAndUpdate", "geosearch", "remove", "replaceOne", "update",
"updateMany", "countDocuments", "updateOne", "where", "deleteMany", "deleteOne", "find",
"findById", "findByIdAndDelete", "findByIdAndRemove", "findByIdAndUpdate"
]
}
/**
@@ -347,117 +332,34 @@ private module Mongoose {
*/
predicate interpretsArgumentAsQuery(string name, int n) {
n = 0 and
(
name = "and" or
name = "count" or
name = "countDocuments" or
name = "deleteMany" or
name = "deleteOne" or
name = "elemMatch" or
name = "find" or
name = "findOne" or
name = "findOneAndDelete" or
name = "findOneAndRemove" or
name = "findOneAndReplace" or
name = "findOneAndUpdate" or
name = "merge" or
name = "nor" or
name = "or" or
name = "remove" or
name = "replaceOne" or
name = "setQuery" or
name = "setUpdate" or
name = "update" or
name = "updateMany" or
name = "updateOne" or
name = "where"
)
name =
[
"and", "count", "findOneAndReplace", "findOneAndUpdate", "merge", "nor", "or", "remove",
"replaceOne", "setQuery", "setUpdate", "update", "countDocuments", "updateMany",
"updateOne", "where", "deleteMany", "deleteOne", "elemMatch", "find", "findOne",
"findOneAndDelete", "findOneAndRemove"
]
or
n = 1 and
(
name = "distinct" or
name = "findOneAndUpdate" or
name = "update" or
name = "updateMany" or
name = "updateOne"
)
name = ["distinct", "findOneAndUpdate", "update", "updateMany", "updateOne"]
}
/**
* Holds if Query method `name` returns a Query.
*/
predicate returnsQuery(string name) {
name = "$where" or
name = "J" or
name = "all" or
name = "and" or
name = "batchsize" or
name = "box" or
name = "center" or
name = "centerSphere" or
name = "circle" or
name = "collation" or
name = "comment" or
name = "count" or
name = "countDocuments" or
name = "distinct" or
name = "elemMatch" or
name = "equals" or
name = "error" or
name = "estimatedDocumentCount" or
name = "exists" or
name = "explain" or
name = "find" or
name = "findById" or
name = "findOne" or
name = "findOneAndRemove" or
name = "findOneAndUpdate" or
name = "geometry" or
name = "get" or
name = "gt" or
name = "gte" or
name = "hint" or
name = "in" or
name = "intersects" or
name = "lean" or
name = "limit" or
name = "lt" or
name = "lte" or
name = "map" or
name = "map" or
name = "maxDistance" or
name = "maxTimeMS" or
name = "maxscan" or
name = "mod" or
name = "ne" or
name = "near" or
name = "nearSphere" or
name = "nin" or
name = "or" or
name = "orFail" or
name = "polygon" or
name = "populate" or
name = "read" or
name = "readConcern" or
name = "regexp" or
name = "remove" or
name = "select" or
name = "session" or
name = "set" or
name = "setOptions" or
name = "setQuery" or
name = "setUpdate" or
name = "size" or
name = "skip" or
name = "slaveOk" or
name = "slice" or
name = "snapshot" or
name = "sort" or
name = "update" or
name = "w" or
name = "where" or
name = "within" or
name = "wtimeout"
name =
[
"$where", "J", "comment", "count", "countDocuments", "distinct", "elemMatch", "equals",
"error", "estimatedDocumentCount", "exists", "explain", "all", "find", "findById",
"findOne", "findOneAndRemove", "findOneAndUpdate", "geometry", "get", "gt", "gte",
"hint", "and", "in", "intersects", "lean", "limit", "lt", "lte", "map", "map",
"maxDistance", "maxTimeMS", "batchsize", "maxscan", "mod", "ne", "near", "nearSphere",
"nin", "or", "orFail", "polygon", "populate", "box", "read", "readConcern", "regexp",
"remove", "select", "session", "set", "setOptions", "setQuery", "setUpdate", "center",
"size", "skip", "slaveOk", "slice", "snapshot", "sort", "update", "w", "where",
"within", "centerSphere", "wtimeout", "circle", "collation"
]
}
/**

View File

@@ -523,14 +523,11 @@ module NodeJSLib {
/** A write to the file system. */
private class NodeJSFileSystemAccessWrite extends FileSystemWriteAccess, NodeJSFileSystemAccess {
NodeJSFileSystemAccessWrite() {
methodName = "appendFile" or
methodName = "appendFileSync" or
methodName = "write" or
methodName = "writeFile" or
methodName = "writeFileSync" or
methodName = "writeSync" or
methodName = "link" or
methodName = "linkSync"
methodName =
[
"appendFile", "appendFileSync", "write", "writeFile", "writeFileSync", "writeSync",
"link", "linkSync"
]
}
override DataFlow::Node getADataNode() {
@@ -699,13 +696,7 @@ module NodeJSLib {
)
or
shell = false and
(
methodName = "execFile" or
methodName = "execFileSync" or
methodName = "spawn" or
methodName = "spawnSync" or
methodName = "fork"
)
methodName = ["execFile", "execFileSync", "spawn", "spawnSync", "fork"]
) and
// all of the above methods take the command as their first argument
result = getParameter(0).getARhs()
@@ -716,18 +707,12 @@ module NodeJSLib {
override predicate isShellInterpreted(DataFlow::Node arg) { arg = getACommandArgument(true) }
override DataFlow::Node getArgumentList() {
(
methodName = "execFile" or
methodName = "execFileSync" or
methodName = "fork" or
methodName = "spawn" or
methodName = "spawnSync"
) and
methodName = ["execFile", "execFileSync", "fork", "spawn", "spawnSync"] and
// all of the above methods take the argument list as their second argument
result = getParameter(1).getARhs()
}
override predicate isSync() { "Sync" = methodName.suffix(methodName.length() - 4) }
override predicate isSync() { methodName.matches("%Sync") }
override DataFlow::Node getOptionsArg() {
not result.getALocalSource() instanceof DataFlow::FunctionNode and // looks like callback

View File

@@ -11,17 +11,11 @@ module PkgCloud {
private predicate takesConfigurationObject(DataFlow::InvokeNode invk, int i) {
exists(DataFlow::ModuleImportNode mod, DataFlow::SourceNode receiver, string type |
mod.getPath() = "pkgcloud" and
(
type = "compute" or
type = "storage" or
type = "database" or
type = "dns" or
type = "blockstorage" or
type = "loadbalancer" or
type = "network" or
type = "orchestration" or
type = "cdn"
) and
type =
[
"compute", "storage", "database", "dns", "blockstorage", "loadbalancer", "network",
"orchestration", "cdn"
] and
(
// require('pkgcloud').compute
receiver = mod.getAPropertyRead(type)

View File

@@ -80,17 +80,7 @@ module ShellJS {
*/
private class ShellJSGenericFileAccess extends FileSystemAccess, ShellJSCall {
ShellJSGenericFileAccess() {
name = "cd" or
name = "cp" or
name = "chmod" or
name = "pushd" or
name = "find" or
name = "ls" or
name = "ln" or
name = "mkdir" or
name = "mv" or
name = "rm" or
name = "touch"
name = ["cd", "cp", "touch", "chmod", "pushd", "find", "ls", "ln", "mkdir", "mv", "rm"]
}
override DataFlow::Node getAPathArgument() { result = getAnArgument() }
@@ -110,13 +100,7 @@ module ShellJS {
* A file system access that returns the contents of a file.
*/
private class ShellJSRead extends FileSystemReadAccess, ShellJSCall {
ShellJSRead() {
name = "cat" or
name = "head" or
name = "sort" or
name = "tail" or
name = "uniq"
}
ShellJSRead() { name = ["cat", "head", "sort", "tail", "uniq"] }
override DataFlow::Node getAPathArgument() { result = getAnArgument() }

View File

@@ -34,14 +34,7 @@ private class LibraryFormatter extends PrintfStyleCall {
returns = false and
mod = "console" and
(
(
meth = "debug" or
meth = "error" or
meth = "info" or
meth = "log" or
meth = "trace" or
meth = "warn"
) and
meth = ["debug", "error", "info", "log", "trace", "warn"] and
formatIndex = 0
or
meth = "assert" and formatIndex = 1

View File

@@ -107,9 +107,7 @@ private class SystemCommandExecutors extends SystemCommandExecution, DataFlow::I
*/
bindingset[name]
private boolean getSync(string name) {
if name.suffix(name.length() - 4) = "Sync" or name.suffix(name.length() - 4) = "sync"
then result = true
else result = false
if name.matches("%Sync") or name.matches("%sync") then result = true else result = false
}
private class RemoteCommandExecutor extends SystemCommandExecution, DataFlow::InvokeNode {

View File

@@ -9,26 +9,11 @@ module Templating {
* Gets a string that is a known template delimiter.
*/
string getADelimiter() {
result = "<%" or
result = "%>" or
result = "{{" or
result = "}}" or
result = "{%" or
result = "%}" or
result = "<@" or
result = "@>" or
result = "<#" or
result = "#>" or
result = "{#" or
result = "#}" or
result = "{$" or
result = "$}" or
result = "[%" or
result = "%]" or
result = "[[" or
result = "]]" or
result = "<?" or
result = "?>"
result =
[
"<%", "%>", "{#", "#}", "{$", "$}", "[%", "%]", "[[", "]]", "<?", "?>", "{{", "}}", "{%",
"%}", "<@", "@>", "<#", "#>"
]
}
/**

View File

@@ -151,7 +151,7 @@ module Vue {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -640,7 +640,7 @@ module Vue {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -441,19 +441,11 @@ module JQuery {
* arguments as HTML.
*/
predicate isMethodArgumentInterpretedAsHtml(string name) {
name = "after" or
name = "append" or
name = "appendTo" or
name = "before" or
name = "html" or
name = "insertAfter" or
name = "insertBefore" or
name = "prepend" or
name = "prependTo" or
name = "replaceWith" or
name = "wrap" or
name = "wrapAll" or
name = "wrapInner"
name =
[
"after", "append", "wrap", "wrapAll", "wrapInner", "appendTo", "before", "html",
"insertAfter", "insertBefore", "prepend", "prependTo", "replaceWith"
]
}
/**
@@ -461,13 +453,7 @@ module JQuery {
* arguments as a selector.
*/
predicate isMethodArgumentInterpretedAsSelector(string name) {
name = "appendTo" or
name = "insertAfter" or
name = "insertBefore" or
name = "prependTo" or
name = "wrap" or
name = "wrapAll" or
name = "wrapInner"
name = ["appendTo", "insertAfter", "insertBefore", "prependTo", "wrap", "wrapAll", "wrapInner"]
}
module DollarSource {

View File

@@ -131,7 +131,7 @@ class XUnitAnnotation extends Expr {
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn

View File

@@ -153,90 +153,36 @@ class JSLintOptions extends JSLintDirective {
private string jsLintImplicitGlobal(string category) {
// cf. http://www.jslint.com/help.html#global
category = "browser" and
(
result = "clearInterval" or
result = "clearTimeout" or
result = "document" or
result = "event" or
result = "frames" or
result = "history" or
result = "Image" or
result = "location" or
result = "name" or
result = "navigator" or
result = "Option" or
result = "parent" or
result = "screen" or
result = "setInterval" or
result = "setTimeout" or
result = "window" or
result = "XMLHttpRequest"
)
result =
[
"clearInterval", "clearTimeout", "Option", "parent", "screen", "setInterval", "setTimeout",
"window", "XMLHttpRequest", "document", "event", "frames", "history", "Image", "location",
"name", "navigator"
]
or
category = "devel" and
(
result = "alert" or
result = "confirm" or
result = "console" or
result = "Debug" or
result = "opera" or
result = "prompt" or
result = "WSH"
)
result = ["alert", "confirm", "console", "Debug", "opera", "prompt", "WSH"]
or
category = "node" and
(
result = "Buffer" or
result = "clearInterval" or
result = "clearTimeout" or
result = "console" or
result = "exports" or
result = "result" or
result = "module" or
result = "process" or
result = "querystring" or
result = "require" or
result = "setInterval" or
result = "setTimeout" or
result = "__filename" or
result = "__dirname"
)
result =
[
"Buffer", "clearInterval", "setInterval", "setTimeout", "__filename", "__dirname",
"clearTimeout", "console", "exports", "result", "module", "process", "querystring", "require"
]
or
category = "couch" and
(
result = "emit" or
result = "getRow" or
result = "isArray" or
result = "log" or
result = "provides" or
result = "registerType" or
result = "require" or
result = "send" or
result = "start" or
result = "sum" or
result = "toJSON"
)
result =
[
"emit", "getRow", "toJSON", "isArray", "log", "provides", "registerType", "require", "send",
"start", "sum"
]
or
category = "rhino" and
(
result = "defineClass" or
result = "deserialize" or
result = "gc" or
result = "help" or
result = "load" or
result = "loadClass" or
result = "print" or
result = "quit" or
result = "readFile" or
result = "readUrl" or
result = "runCommand" or
result = "seal" or
result = "serialize" or
result = "spawn" or
result = "sync" or
result = "toint32" or
result = "version"
)
result =
[
"defineClass", "deserialize", "runCommand", "seal", "serialize", "spawn", "sync", "toint32",
"version", "gc", "help", "load", "loadClass", "print", "quit", "readFile", "readUrl"
]
}
/**

View File

@@ -15,68 +15,35 @@
*/
private module AlgorithmNames {
predicate isStrongHashingAlgorithm(string name) {
name = "DSA" or
name = "ED25519" or
name = "ES256" or
name = "ECDSA256" or
name = "ES384" or
name = "ECDSA384" or
name = "ES512" or
name = "ECDSA512" or
name = "SHA2" or
name = "SHA224" or
name = "SHA256" or
name = "SHA384" or
name = "SHA512" or
name = "SHA3"
name =
[
"DSA", "ED25519", "ES256", "ECDSA256", "ES384", "ECDSA384", "ES512", "ECDSA512", "SHA2",
"SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512"
]
}
predicate isWeakHashingAlgorithm(string name) {
name = "HAVEL128" or
name = "MD2" or
name = "MD4" or
name = "MD5" or
name = "PANAMA" or
name = "RIPEMD" or
name = "RIPEMD128" or
name = "RIPEMD256" or
name = "RIPEMD160" or
name = "RIPEMD320" or
name = "SHA0" or
name = "SHA1"
name =
[
"HAVEL128", "MD2", "MD4", "MD5", "PANAMA", "RIPEMD", "RIPEMD128", "RIPEMD256", "RIPEMD160",
"RIPEMD320", "SHA0", "SHA1"
]
}
predicate isStrongEncryptionAlgorithm(string name) {
name = "AES" or
name = "AES128" or
name = "AES192" or
name = "AES256" or
name = "AES512" or
name = "RSA" or
name = "RABBIT" or
name = "BLOWFISH"
name = ["AES", "AES128", "AES192", "AES256", "AES512", "RSA", "RABBIT", "BLOWFISH"]
}
predicate isWeakEncryptionAlgorithm(string name) {
name = "DES" or
name = "3DES" or
name = "TRIPLEDES" or
name = "TDEA" or
name = "TRIPLEDEA" or
name = "ARC2" or
name = "RC2" or
name = "ARC4" or
name = "RC4" or
name = "ARCFOUR" or
name = "ARC5" or
name = "RC5"
name =
[
"DES", "3DES", "TRIPLEDES", "TDEA", "TRIPLEDEA", "ARC2", "RC2", "ARC4", "RC4", "ARCFOUR",
"ARC5", "RC5"
]
}
predicate isStrongPasswordHashingAlgorithm(string name) {
name = "ARGON2" or
name = "PBKDF2" or
name = "BCRYPT" or
name = "SCRYPT"
name = ["ARGON2", "PBKDF2", "BCRYPT", "SCRYPT"]
}
predicate isWeakPasswordHashingAlgorithm(string name) { none() }

View File

@@ -29,20 +29,11 @@ module TaintedUrlSuffix {
/** Holds for `pred -> succ` is a step of form `x -> x.p` */
private predicate isSafeLocationProp(DataFlow::PropRead read) {
// Ignore properties that refer to the scheme, domain, port, auth, or path.
exists(string name | name = read.getPropertyName() |
name = "protocol" or
name = "scheme" or
name = "host" or
name = "hostname" or
name = "domain" or
name = "origin" or
name = "port" or
name = "path" or
name = "pathname" or
name = "username" or
name = "password" or
name = "auth"
)
read.getPropertyName() =
[
"protocol", "scheme", "host", "hostname", "domain", "origin", "port", "path", "pathname",
"username", "password", "auth"
]
}
/**

View File

@@ -303,14 +303,11 @@ module PrettyPrintCatCall {
bindingset[str]
private string createSimplifiedStringConcat(string str) {
// Remove an initial ""+ (e.g. in `""+file`)
if str.prefix(5) = "\"\" + "
if str.matches("\"\" + %")
then result = str.suffix(5)
else
// prettify `${newpath}` to just newpath
if
str.prefix(3) = "`${" and
str.suffix(str.length() - 2) = "}`" and
not str.suffix(3).matches("%{%")
if str.matches("`${%") and str.matches("%}`") and not str.suffix(3).matches("%{%")
then result = str.prefix(str.length() - 2).suffix(3)
else result = str
}

View File

@@ -88,12 +88,7 @@ module ClientSideUrlRedirect {
class LocationSink extends Sink, DataFlow::ValueNode {
LocationSink() {
// A call to a `window.navigate` or `window.open`
exists(string name |
name = "navigate" or
name = "open" or
name = "openDialog" or
name = "showModalDialog"
|
exists(string name | name = ["navigate", "open", "openDialog", "showModalDialog"] |
this = DataFlow::globalVarRef(name).getACall().getArgument(0)
)
or
@@ -102,7 +97,7 @@ module ClientSideUrlRedirect {
locationCall = DOM::locationRef().getAMethodCall(name) and
this = locationCall.getArgument(0)
|
name = "replace" or name = "assign"
name = ["replace", "assign"]
)
or
// An assignment to `location`
@@ -113,7 +108,7 @@ module ClientSideUrlRedirect {
pw = DOM::locationRef().getAPropertyWrite(propName) and
this = pw.getRhs()
|
propName = "href" or propName = "protocol" or propName = "hostname"
propName = ["href", "protocol", "hostname"]
)
or
// A redirection using the AngularJS `$location` service
@@ -153,9 +148,8 @@ module ClientSideUrlRedirect {
*/
class SrcAttributeUrlSink extends ScriptUrlSink, DataFlow::ValueNode {
SrcAttributeUrlSink() {
exists(DOM::AttributeDefinition attr, string eltName |
attr.getElement().getName() = eltName and
(eltName = "script" or eltName = "iframe") and
exists(DOM::AttributeDefinition attr |
attr.getElement().getName() = ["script", "iframe"] and
attr.getName() = "src" and
this = attr.getValueNode()
)

View File

@@ -88,14 +88,7 @@ class DomMethodCallExpr extends MethodCallExpr {
name = "setAttributeNS" and argPos = 2
) and
// restrict to potentially dangerous attributes
exists(string attr |
attr = "action" or
attr = "formaction" or
attr = "href" or
attr = "src" or
attr = "xlink:href" or
attr = "data"
|
exists(string attr | attr = ["action", "formaction", "href", "src", "xlink:href", "data"] |
getArgument(argPos - 1).getStringValue().toLowerCase() = attr
)
)

View File

@@ -115,66 +115,18 @@ module LoopBoundInjection {
* Holds if `name` is a method from lodash vulnerable to a DoS attack if called with a tainted object.
*/
predicate loopableLodashMethod(string name) {
name = "chunk" or
name = "compact" or
name = "difference" or
name = "differenceBy" or
name = "differenceWith" or
name = "drop" or
name = "dropRight" or
name = "dropRightWhile" or
name = "dropWhile" or
name = "fill" or
name = "findIndex" or
name = "findLastIndex" or
name = "flatten" or
name = "flattenDeep" or
name = "flattenDepth" or
name = "initial" or
name = "intersection" or
name = "intersectionBy" or
name = "intersectionWith" or
name = "join" or
name = "remove" or
name = "reverse" or
name = "slice" or
name = "sortedUniq" or
name = "sortedUniqBy" or
name = "tail" or
name = "union" or
name = "unionBy" or
name = "unionWith" or
name = "uniqBy" or
name = "unzip" or
name = "unzipWith" or
name = "without" or
name = "zip" or
name = "zipObject" or
name = "zipObjectDeep" or
name = "zipWith" or
name = "countBy" or
name = "each" or
name = "forEach" or
name = "eachRight" or
name = "forEachRight" or
name = "filter" or
name = "find" or
name = "findLast" or
name = "flatMap" or
name = "flatMapDeep" or
name = "flatMapDepth" or
name = "forEach" or
name = "forEachRight" or
name = "groupBy" or
name = "invokeMap" or
name = "keyBy" or
name = "map" or
name = "orderBy" or
name = "partition" or
name = "reduce" or
name = "reduceRight" or
name = "reject" or
name = "sortBy"
name =
[
"chunk", "compact", "difference", "differenceBy", "differenceWith", "drop", "dropRight",
"dropRightWhile", "dropWhile", "fill", "findIndex", "findLastIndex", "flatten",
"flattenDeep", "flattenDepth", "initial", "intersection", "intersectionBy",
"intersectionWith", "join", "remove", "reverse", "slice", "sortedUniq", "sortedUniqBy",
"tail", "union", "unionBy", "unionWith", "uniqBy", "unzip", "unzipWith", "without", "zip",
"zipObject", "zipObjectDeep", "zipWith", "countBy", "each", "forEach", "eachRight",
"forEachRight", "filter", "find", "findLast", "flatMap", "flatMapDeep", "flatMapDepth",
"forEach", "forEachRight", "groupBy", "invokeMap", "keyBy", "map", "orderBy", "partition",
"reduce", "reduceRight", "reject", "sortBy"
]
}
/**

View File

@@ -751,13 +751,11 @@ module TaintedPath {
exists(mcn.getAnArgument().asExpr().getIntValue())
or
exists(string argumentlessMethodName |
argumentlessMethodName = "toLocaleLowerCase" or
argumentlessMethodName = "toLocaleUpperCase" or
argumentlessMethodName = "toLowerCase" or
argumentlessMethodName = "toUpperCase" or
argumentlessMethodName = "trim" or
argumentlessMethodName = "trimLeft" or
argumentlessMethodName = "trimRight"
argumentlessMethodName =
[
"toLocaleLowerCase", "toLocaleUpperCase", "toLowerCase", "toUpperCase", "trim",
"trimLeft", "trimRight"
]
|
name = argumentlessMethodName
)

View File

@@ -39,11 +39,7 @@ module TypeConfusionThroughParameterTampering {
private class StringArrayAmbiguousMethodCall extends Sink {
StringArrayAmbiguousMethodCall() {
exists(string name, DataFlow::MethodCallNode mc |
name = "concat" or
name = "includes" or
name = "indexOf" or
name = "lastIndexOf" or
name = "slice"
name = ["concat", "includes", "indexOf", "lastIndexOf", "slice"]
|
mc.calls(this, name) and
// ignore patterns that are innocent in practice

View File

@@ -67,14 +67,7 @@ module PolynomialReDoS {
|
this = mcn.getArgument(0) and
regexp = mcn.getReceiver() and
(
name = "match" or
name = "split" or
name = "matchAll" or
name = "replace" or
name = "replaceAll" or
name = "search"
)
name = ["match", "split", "matchAll", "replace", "replaceAll", "search"]
or
this = mcn.getReceiver() and
regexp = mcn.getArgument(0) and

View File

@@ -139,8 +139,6 @@ class RegExpRoot extends RegExpTerm {
predicate isRelevant() {
// there is at least one repetition
getRoot(any(InfiniteRepetitionQuantifier q)) = this and
// there are no lookbehinds
not exists(RegExpLookbehind lbh | getRoot(lbh) = this) and
// is actually used as a RegExp
isUsedAsRegExp() and
// not excluded for library specific reasons
@@ -479,7 +477,7 @@ private module CharacterClasses {
result = ["0", "9"]
or
cc.getValue() = "s" and
result = [" "]
result = " "
or
cc.getValue() = "w" and
result = ["a", "Z", "_", "0", "9"]
@@ -492,7 +490,7 @@ private module CharacterClasses {
result = "9"
or
cc.getValue() = "s" and
result = [" "]
result = " "
or
cc.getValue() = "w" and
result = "a"

File diff suppressed because it is too large Load Diff