mirror of
https://github.com/github/codeql.git
synced 2026-05-02 04:05:14 +02:00
Merge branch 'master'
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
+ semmlecode-javascript-queries/RegExp/BackrefIntoNegativeLookahead.ql: /Correctness/Regular Expressions
|
||||
+ semmlecode-javascript-queries/RegExp/DuplicateCharacterInCharacterClass.ql: /Correctness/Regular Expressions
|
||||
+ semmlecode-javascript-queries/RegExp/EmptyCharacterClass.ql: /Correctness/Regular Expressions
|
||||
+ semmlecode-javascript-queries/RegExp/IdentityReplacement.ql: /Correctness/Regular Expressions
|
||||
+ semmlecode-javascript-queries/RegExp/UnboundBackref.ql: /Correctness/Regular Expressions
|
||||
+ semmlecode-javascript-queries/RegExp/UnmatchableCaret.ql: /Correctness/Regular Expressions
|
||||
+ semmlecode-javascript-queries/RegExp/UnmatchableDollar.ql: /Correctness/Regular Expressions
|
||||
|
||||
@@ -25,9 +25,11 @@
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {string=} message
|
||||
* @param {string=} message
|
||||
* @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-17189187
|
||||
*/
|
||||
function DOMException() {}
|
||||
function DOMException(message, name) {}
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
|
||||
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Semmle JavaScript Default Queries
|
||||
Bundle-SymbolicName: com.semmle.plugin.semmlecode.javascript.queries;singleton:=true
|
||||
Bundle-Version: 1.18.0.qualifier
|
||||
Bundle-Version: 1.18.1.qualifier
|
||||
Bundle-Vendor: Semmle Ltd.
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.0.qualifier, 1.18.0.qualifier]"
|
||||
Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.1.qualifier,1.18.1.qualifier]"
|
||||
|
||||
36
javascript/ql/src/RegExp/IdentityReplacement.qhelp
Normal file
36
javascript/ql/src/RegExp/IdentityReplacement.qhelp
Normal file
@@ -0,0 +1,36 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Replacing a substring with itself has no effect and usually indicates a mistake, such as
|
||||
misspelling a backslash escape.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Examine the string replacement to find and correct any typos.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following code snippet attempts to backslash-escape all double quotes in <code>raw</code>
|
||||
by replacing all instances of <code>"</code> with <code>\"</code>:
|
||||
</p>
|
||||
<sample src="examples/IdentityReplacement.js" />
|
||||
<p>
|
||||
However, the replacement string <code>'\"'</code> is actually the same as <code>'"'</code>,
|
||||
with <code>\"</code> interpreted as an identity escape, so the replacement does nothing.
|
||||
Instead, the replacement string should be <code>'\\"'</code>:
|
||||
</p>
|
||||
<sample src="examples/IdentityReplacementGood.js" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Mozilla Developer Network: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#Escape_notation">String escape notation</a>.</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
68
javascript/ql/src/RegExp/IdentityReplacement.ql
Normal file
68
javascript/ql/src/RegExp/IdentityReplacement.ql
Normal file
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @name Replacement of a substring with itself
|
||||
* @description Replacing a substring with itself has no effect and may indicate a mistake.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @id js/identity-replacement
|
||||
* @precision very-high
|
||||
* @tags correctness
|
||||
* security
|
||||
* external/cwe/cwe-116
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
/**
|
||||
* Holds if `e`, when used as the first argument of `String.prototype.replace`, matches
|
||||
* `s` and nothing else.
|
||||
*/
|
||||
predicate matchesString(Expr e, string s) {
|
||||
exists (RegExpLiteral rl |
|
||||
rl = e and
|
||||
not rl.isIgnoreCase() and
|
||||
regExpMatchesString(rl.getRoot(), s)
|
||||
)
|
||||
or
|
||||
s = e.getStringValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `t` matches `s` and nothing else.
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
predicate regExpMatchesString(RegExpTerm t, string s) {
|
||||
// constants match themselves
|
||||
s = t.(RegExpConstant).getValue()
|
||||
or
|
||||
// assertions match the empty string
|
||||
(t instanceof RegExpCaret or
|
||||
t instanceof RegExpDollar or
|
||||
t instanceof RegExpWordBoundary or
|
||||
t instanceof RegExpNonWordBoundary or
|
||||
t instanceof RegExpLookahead or
|
||||
t instanceof RegExpLookbehind) and
|
||||
s = ""
|
||||
or
|
||||
// groups match their content
|
||||
regExpMatchesString(t.(RegExpGroup).getAChild(), s)
|
||||
or
|
||||
// single-character classes match that character
|
||||
exists (RegExpCharacterClass recc | recc = t and not recc.isInverted() |
|
||||
recc.getNumChild() = 1 and
|
||||
regExpMatchesString(recc.getChild(0), s)
|
||||
)
|
||||
or
|
||||
// sequences match the concatenation of their elements
|
||||
exists (RegExpSequence seq | seq = t |
|
||||
s = concat(int i, RegExpTerm child | child = seq.getChild(i) |
|
||||
any(string subs | regExpMatchesString(child, subs)) order by i
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
from MethodCallExpr repl, string s, string friendly
|
||||
where repl.getMethodName() = "replace" and
|
||||
matchesString(repl.getArgument(0), s) and
|
||||
repl.getArgument(1).getStringValue() = s and
|
||||
(if s = "" then friendly = "the empty string" else friendly = "'" + s + "'")
|
||||
select repl.getArgument(0), "This replaces " + friendly + " with itself."
|
||||
1
javascript/ql/src/RegExp/examples/IdentityReplacement.js
Normal file
1
javascript/ql/src/RegExp/examples/IdentityReplacement.js
Normal file
@@ -0,0 +1 @@
|
||||
var escaped = raw.replace(/"/g, '\"');
|
||||
@@ -0,0 +1 @@
|
||||
var escaped = raw.replace(/"/g, '\\"');
|
||||
@@ -38,12 +38,15 @@ predicate hasCookieMiddleware(Express::RouteHandlerExpr expr, Express::RouteHand
|
||||
* // protected from CSRF
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* Currently the predicate only detects `csurf`-based protectors.
|
||||
*/
|
||||
DataFlow::CallNode csrfMiddlewareCreation() {
|
||||
exists (DataFlow::ModuleImportNode mod | result = mod.getACall() |
|
||||
mod.getPath() = "csurf"
|
||||
exists (DataFlow::SourceNode callee | result = callee.getACall() |
|
||||
callee = DataFlow::moduleImport("csurf")
|
||||
or
|
||||
callee = DataFlow::moduleImport("lusca") and
|
||||
exists(result.getOptionArgument(0, "csrf"))
|
||||
or
|
||||
callee = DataFlow::moduleMember("lusca", "csrf")
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.2"?>
|
||||
<plugin>
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="semmlecode-javascript-queries"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.javascript.library"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.javascript.dbscheme"/>
|
||||
<path value="/semmlecode.javascript.dbscheme"/>
|
||||
</extension>
|
||||
</plugin>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.2"?>
|
||||
<plugin>
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="semmlecode-javascript-queries"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.javascript.library"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.javascript.dbscheme"/>
|
||||
<path value="/semmlecode.javascript.dbscheme"/>
|
||||
</extension>
|
||||
</plugin>
|
||||
|
||||
@@ -6,7 +6,7 @@ import javascript
|
||||
|
||||
/** An XML element that has a location. */
|
||||
abstract class XMLLocatable extends @xmllocatable {
|
||||
/** The source location for this element. */
|
||||
/** Gets the source location for this element. */
|
||||
Location getLocation() { xmllocations(this,result) }
|
||||
|
||||
/**
|
||||
@@ -33,46 +33,49 @@ abstract class XMLLocatable extends @xmllocatable {
|
||||
*/
|
||||
class XMLParent extends @xmlparent {
|
||||
/**
|
||||
* A printable representation of this XML parent.
|
||||
* Gets a printable representation of this XML parent.
|
||||
* (Intended to be overridden in subclasses.)
|
||||
*/
|
||||
abstract string getName();
|
||||
|
||||
/** The file to which this XML parent belongs. */
|
||||
/** Gets the file to which this XML parent belongs. */
|
||||
XMLFile getFile() { result = this or xmlElements(this,_,_,_,result) }
|
||||
|
||||
/** The child element at a specified index of this XML parent. */
|
||||
/** Gets the child element at a specified index of this XML parent. */
|
||||
XMLElement getChild(int index) { xmlElements(result, _, this, index, _) }
|
||||
|
||||
/** A child element of this XML parent. */
|
||||
/** Gets a child element of this XML parent. */
|
||||
XMLElement getAChild() { xmlElements(result,_,this,_,_) }
|
||||
|
||||
/** A child element of this XML parent with the given `name`. */
|
||||
/** Gets a child element of this XML parent with the given `name`. */
|
||||
XMLElement getAChild(string name) { xmlElements(result,_,this,_,_) and result.hasName(name) }
|
||||
|
||||
/** A comment that is a child of this XML parent. */
|
||||
/** Gets a comment that is a child of this XML parent. */
|
||||
XMLComment getAComment() { xmlComments(result,_,this,_) }
|
||||
|
||||
/** A character sequence that is a child of this XML parent. */
|
||||
/** Gets a character sequence that is a child of this XML parent. */
|
||||
XMLCharacters getACharactersSet() { xmlChars(result,_,this,_,_,_) }
|
||||
|
||||
/** The depth in the tree. (Overridden in XMLElement.) */
|
||||
/** Gets the depth in the tree. (Overridden in XMLElement.) */
|
||||
int getDepth() { result = 0 }
|
||||
|
||||
/** The number of child XML elements of this XML parent. */
|
||||
/** Gets the number of child XML elements of this XML parent. */
|
||||
int getNumberOfChildren() {
|
||||
result = count(XMLElement e | xmlElements(e,_,this,_,_))
|
||||
}
|
||||
|
||||
/** The number of places in the body of this XML parent where text occurs. */
|
||||
/** Gets the number of places in the body of this XML parent where text occurs. */
|
||||
int getNumberOfCharacterSets() {
|
||||
result = count(int pos | xmlChars(_,_,this,pos,_,_))
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Internal.
|
||||
*
|
||||
* Append the character sequences of this XML parent from left to right, separated by a space,
|
||||
* up to a specified (zero-based) index.
|
||||
*/
|
||||
deprecated
|
||||
string charsSetUpTo(int n) {
|
||||
(n = 0 and xmlChars(_,result,this,0,_,_)) or
|
||||
(n > 0 and exists(string chars | xmlChars(_,chars,this,n,_,_) |
|
||||
@@ -81,18 +84,15 @@ class XMLParent extends @xmlparent {
|
||||
|
||||
/** Append all the character sequences of this XML parent from left to right, separated by a space. */
|
||||
string allCharactersString() {
|
||||
exists(int n | n = this.getNumberOfCharacterSets() |
|
||||
(n = 0 and result = "") or
|
||||
(n > 0 and result = this.charsSetUpTo(n-1))
|
||||
)
|
||||
result = concat(string chars, int pos | xmlChars(_, chars, this, pos, _, _) | chars, " " order by pos)
|
||||
}
|
||||
|
||||
/** The text value contained in this XML parent. */
|
||||
/** Gets the text value contained in this XML parent. */
|
||||
string getTextValue() {
|
||||
result = allCharactersString()
|
||||
}
|
||||
|
||||
/** A printable representation of this XML parent. */
|
||||
/** Gets a printable representation of this XML parent. */
|
||||
string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
@@ -102,46 +102,46 @@ class XMLFile extends XMLParent, File {
|
||||
xmlEncoding(this,_)
|
||||
}
|
||||
|
||||
/** A printable representation of this XML file. */
|
||||
/** Gets a printable representation of this XML file. */
|
||||
override
|
||||
string toString() { result = XMLParent.super.toString() }
|
||||
|
||||
/** The name of this XML file. */
|
||||
/** Gets the name of this XML file. */
|
||||
override
|
||||
string getName() { result = File.super.getAbsolutePath() }
|
||||
|
||||
/** The encoding of this XML file. */
|
||||
/** Gets the encoding of this XML file. */
|
||||
string getEncoding() { xmlEncoding(this,result) }
|
||||
|
||||
/** The XML file itself. */
|
||||
/** Gets the XML file itself. */
|
||||
override
|
||||
XMLFile getFile() { result = this }
|
||||
|
||||
/** A top-most element in an XML file. */
|
||||
/** Gets a top-most element in an XML file. */
|
||||
XMLElement getARootElement() { result = this.getAChild() }
|
||||
|
||||
/** A DTD associated with this XML file. */
|
||||
/** Gets a DTD associated with this XML file. */
|
||||
XMLDTD getADTD() { xmlDTDs(result,_,_,_,this) }
|
||||
}
|
||||
|
||||
/** A "Document Type Definition" of an XML file. */
|
||||
class XMLDTD extends @xmldtd {
|
||||
/** The name of the root element of this DTD. */
|
||||
/** Gets the name of the root element of this DTD. */
|
||||
string getRoot() { xmlDTDs(this,result,_,_,_) }
|
||||
|
||||
/** The public ID of this DTD. */
|
||||
/** Gets the public ID of this DTD. */
|
||||
string getPublicId() { xmlDTDs(this,_,result,_,_) }
|
||||
|
||||
/** The system ID of this DTD. */
|
||||
/** Gets the system ID of this DTD. */
|
||||
string getSystemId() { xmlDTDs(this,_,_,result,_) }
|
||||
|
||||
/** Holds if this DTD is public. */
|
||||
predicate isPublic() { not xmlDTDs(this,_,"",_,_) }
|
||||
|
||||
/** The parent of this DTD. */
|
||||
/** Gets the parent of this DTD. */
|
||||
XMLParent getParent() { xmlDTDs(this,_,_,_,result) }
|
||||
|
||||
/** A printable representation of this DTD. */
|
||||
/** Gets a printable representation of this DTD. */
|
||||
string toString() {
|
||||
(this.isPublic() and result = this.getRoot() + " PUBLIC '" +
|
||||
this.getPublicId() + "' '" +
|
||||
@@ -157,37 +157,37 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
|
||||
/** Holds if this XML element has the given `name`. */
|
||||
predicate hasName(string name) { name = getName() }
|
||||
|
||||
/** The name of this XML element. */
|
||||
/** Gets the name of this XML element. */
|
||||
override
|
||||
string getName() { xmlElements(this,result,_,_,_) }
|
||||
|
||||
/** The XML file in which this XML element occurs. */
|
||||
/** Gets the XML file in which this XML element occurs. */
|
||||
override
|
||||
XMLFile getFile() { xmlElements(this,_,_,_,result) }
|
||||
|
||||
/** The parent of this XML element. */
|
||||
/** Gets the parent of this XML element. */
|
||||
XMLParent getParent() { xmlElements(this,_,result,_,_) }
|
||||
|
||||
/** The index of this XML element among its parent's children. */
|
||||
/** Gets the index of this XML element among its parent's children. */
|
||||
int getIndex() { xmlElements(this, _, _, result, _) }
|
||||
|
||||
/** Holds if this XML element has a namespace. */
|
||||
predicate hasNamespace() { xmlHasNs(this,_,_) }
|
||||
|
||||
/** The namespace of this XML element, if any. */
|
||||
/** Gets the namespace of this XML element, if any. */
|
||||
XMLNamespace getNamespace() { xmlHasNs(this,result,_) }
|
||||
|
||||
/** The index of this XML element among its parent's children. */
|
||||
/** Gets the index of this XML element among its parent's children. */
|
||||
int getElementPositionIndex() { xmlElements(this,_,_,result,_) }
|
||||
|
||||
/** The depth of this element within the XML file tree structure. */
|
||||
/** Gets the depth of this element within the XML file tree structure. */
|
||||
override
|
||||
int getDepth() { result = this.getParent().getDepth() + 1 }
|
||||
|
||||
/** An XML attribute of this XML element. */
|
||||
/** Gets an XML attribute of this XML element. */
|
||||
XMLAttribute getAnAttribute() { result.getElement() = this }
|
||||
|
||||
/** The attribute with the specified `name`, if any. */
|
||||
/** Gets the attribute with the specified `name`, if any. */
|
||||
XMLAttribute getAttribute(string name) {
|
||||
result.getElement() = this and result.getName() = name
|
||||
}
|
||||
@@ -197,49 +197,49 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
|
||||
exists(XMLAttribute a| a = this.getAttribute(name))
|
||||
}
|
||||
|
||||
/** The value of the attribute with the specified `name`, if any. */
|
||||
/** Gets the value of the attribute with the specified `name`, if any. */
|
||||
string getAttributeValue(string name) {
|
||||
result = this.getAttribute(name).getValue()
|
||||
}
|
||||
|
||||
/** A printable representation of this XML element. */
|
||||
/** Gets a printable representation of this XML element. */
|
||||
override
|
||||
string toString() { result = XMLParent.super.toString() }
|
||||
}
|
||||
|
||||
/** An attribute that occurs inside an XML element. */
|
||||
class XMLAttribute extends @xmlattribute, XMLLocatable {
|
||||
/** The name of this attribute. */
|
||||
/** Gets the name of this attribute. */
|
||||
string getName() { xmlAttrs(this,_,result,_,_,_) }
|
||||
|
||||
/** The XML element to which this attribute belongs. */
|
||||
/** Gets the XML element to which this attribute belongs. */
|
||||
XMLElement getElement() { xmlAttrs(this,result,_,_,_,_) }
|
||||
|
||||
/** Holds if this attribute has a namespace. */
|
||||
predicate hasNamespace() { xmlHasNs(this,_,_) }
|
||||
|
||||
/** The namespace of this attribute, if any. */
|
||||
/** Gets the namespace of this attribute, if any. */
|
||||
XMLNamespace getNamespace() { xmlHasNs(this,result,_) }
|
||||
|
||||
/** The value of this attribute. */
|
||||
/** Gets the value of this attribute. */
|
||||
string getValue() { xmlAttrs(this,_,_,result,_,_) }
|
||||
|
||||
/** A printable representation of this XML attribute. */
|
||||
/** Gets a printable representation of this XML attribute. */
|
||||
override string toString() { result = this.getName() + "=" + this.getValue() }
|
||||
}
|
||||
|
||||
/** A namespace used in an XML file */
|
||||
class XMLNamespace extends @xmlnamespace {
|
||||
/** The prefix of this namespace. */
|
||||
/** Gets the prefix of this namespace. */
|
||||
string getPrefix() { xmlNs(this,result,_,_) }
|
||||
|
||||
/** The URI of this namespace. */
|
||||
/** Gets the URI of this namespace. */
|
||||
string getURI() { xmlNs(this,_,result,_) }
|
||||
|
||||
/** Holds if this namespace has no prefix. */
|
||||
predicate isDefault() { this.getPrefix() = "" }
|
||||
|
||||
/** A printable representation of this XML namespace. */
|
||||
/** Gets a printable representation of this XML namespace. */
|
||||
string toString() {
|
||||
(this.isDefault() and result = this.getURI()) or
|
||||
(not this.isDefault() and result = this.getPrefix() + ":" + this.getURI())
|
||||
@@ -248,13 +248,13 @@ class XMLNamespace extends @xmlnamespace {
|
||||
|
||||
/** A comment of the form `<!-- ... -->` is an XML comment. */
|
||||
class XMLComment extends @xmlcomment, XMLLocatable {
|
||||
/** The text content of this XML comment. */
|
||||
/** Gets the text content of this XML comment. */
|
||||
string getText() { xmlComments(this,result,_,_) }
|
||||
|
||||
/** The parent of this XML comment. */
|
||||
/** Gets the parent of this XML comment. */
|
||||
XMLParent getParent() { xmlComments(this,_,result,_) }
|
||||
|
||||
/** A printable representation of this XML comment. */
|
||||
/** Gets a printable representation of this XML comment. */
|
||||
override string toString() { result = this.getText() }
|
||||
}
|
||||
|
||||
@@ -263,15 +263,15 @@ class XMLComment extends @xmlcomment, XMLLocatable {
|
||||
* closing tags of an XML element, excluding other elements.
|
||||
*/
|
||||
class XMLCharacters extends @xmlcharacters, XMLLocatable {
|
||||
/** The content of this character sequence. */
|
||||
/** Gets the content of this character sequence. */
|
||||
string getCharacters() { xmlChars(this,result,_,_,_,_) }
|
||||
|
||||
/** The parent of this character sequence. */
|
||||
/** Gets the parent of this character sequence. */
|
||||
XMLParent getParent() { xmlChars(this,_,result,_,_,_) }
|
||||
|
||||
/** Holds if this character sequence is CDATA. */
|
||||
predicate isCDATA() { xmlChars(this,_,_,_,1,_) }
|
||||
|
||||
/** A printable representation of this XML character sequence. */
|
||||
/** Gets a printable representation of this XML character sequence. */
|
||||
override string toString() { result = this.getCharacters() }
|
||||
}
|
||||
|
||||
@@ -614,6 +614,26 @@ module TaintTracking {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A check of the form `if(<isWhitelisted>(x))`, which sanitizes `x` in its "then" branch.
|
||||
*
|
||||
* `<isWhitelisted>` is a call with callee name 'safe', 'whitelist', 'allow', or similar.
|
||||
*
|
||||
* This sanitizer is not enabled by default.
|
||||
*/
|
||||
class AdHocWhitelistCheckSanitizer extends SanitizerGuardNode, DataFlow::CallNode {
|
||||
AdHocWhitelistCheckSanitizer() {
|
||||
getCalleeName().regexpMatch("(?i).*((?<!un)safe|whitelist|allow|(?<!un)auth(?!or\\b)).*") and
|
||||
getNumArgument() = 1
|
||||
}
|
||||
|
||||
override predicate sanitizes(boolean outcome, Expr e) {
|
||||
outcome = true and
|
||||
e = getArgument(0).asExpr()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** A check of the form `if(x in o)`, which sanitizes `x` in its "then" branch. */
|
||||
class InSanitizer extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {
|
||||
|
||||
|
||||
@@ -479,6 +479,17 @@ module Express {
|
||||
methodName = "header"
|
||||
)
|
||||
or
|
||||
exists (DataFlow::PropRead headers |
|
||||
// `req.headers.name`
|
||||
kind = "header" and
|
||||
headers.accesses(request, "headers") and
|
||||
this = headers.getAPropertyRead())
|
||||
or
|
||||
exists (string propName | propName = "host" or propName = "hostname" |
|
||||
// `req.host` and `req.hostname` are derived from headers
|
||||
kind = "header" and
|
||||
this.(DataFlow::PropRead).accesses(request, propName))
|
||||
or
|
||||
// `req.cookies`
|
||||
kind = "cookie" and
|
||||
this.(DataFlow::PropRef).accesses(request, "cookies")
|
||||
@@ -785,7 +796,8 @@ module Express {
|
||||
override MethodCallExpr astNode;
|
||||
|
||||
ResponseSendFileAsFileSystemAccess() {
|
||||
asExpr().(MethodCallExpr).calls(any(ResponseExpr res), "sendFile")
|
||||
exists (string name | name = "sendFile" or name = "sendfile" |
|
||||
asExpr().(MethodCallExpr).calls(any(ResponseExpr res), name))
|
||||
}
|
||||
|
||||
override DataFlow::Node getDataNode() {
|
||||
|
||||
@@ -49,6 +49,11 @@ module CorsMisconfigurationForCredentials {
|
||||
super.isSanitizer(node) or
|
||||
node instanceof Sanitizer
|
||||
}
|
||||
|
||||
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
|
||||
guard instanceof TaintTracking::AdHocWhitelistCheckSanitizer
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** A source of remote user input, considered as a flow source for CORS misconfiguration. */
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# This file intentionally contains a mix of different line endings
|
||||
tst1.js -text
|
||||
# This file intentionally contains a mix of different line endings
|
||||
tst1.js -text
|
||||
|
||||
@@ -23,4 +23,9 @@ class ExampleConfiguration extends TaintTracking::Configuration {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
|
||||
// add additional generic sanitizers
|
||||
guard instanceof TaintTracking::AdHocWhitelistCheckSanitizer
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,3 +36,5 @@
|
||||
| tst.js:214:9:214:24 | o.indexOf(v) < 0 | ExampleConfiguration | false | tst.js:214:19:214:19 | v |
|
||||
| tst.js:220:9:220:25 | o.indexOf(v) > -1 | ExampleConfiguration | true | tst.js:220:19:220:19 | v |
|
||||
| tst.js:226:9:226:26 | -1 >= o.indexOf(v) | ExampleConfiguration | false | tst.js:226:25:226:25 | v |
|
||||
| tst.js:236:9:236:24 | isWhitelisted(v) | ExampleConfiguration | true | tst.js:236:23:236:23 | v |
|
||||
| tst.js:240:9:240:28 | config.allowValue(v) | ExampleConfiguration | true | tst.js:240:27:240:27 | v |
|
||||
|
||||
@@ -34,3 +34,5 @@
|
||||
| tst.js:215:14:215:14 | v | tst.js:199:13:199:20 | SOURCE() |
|
||||
| tst.js:223:14:223:14 | v | tst.js:199:13:199:20 | SOURCE() |
|
||||
| tst.js:227:14:227:14 | v | tst.js:199:13:199:20 | SOURCE() |
|
||||
| tst.js:239:14:239:14 | v | tst.js:235:13:235:20 | SOURCE() |
|
||||
| tst.js:243:14:243:14 | v | tst.js:235:13:235:20 | SOURCE() |
|
||||
|
||||
@@ -29,3 +29,5 @@
|
||||
| tst.js:217:14:217:14 | v | ExampleConfiguration |
|
||||
| tst.js:221:14:221:14 | v | ExampleConfiguration |
|
||||
| tst.js:229:14:229:14 | v | ExampleConfiguration |
|
||||
| tst.js:237:14:237:14 | v | ExampleConfiguration |
|
||||
| tst.js:241:14:241:14 | v | ExampleConfiguration |
|
||||
|
||||
@@ -230,3 +230,16 @@ function RelationalIndexOfCheckSanitizer () {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function adhocWhitelisting() {
|
||||
var v = SOURCE();
|
||||
if (isWhitelisted(v))
|
||||
SINK(v);
|
||||
else
|
||||
SINK(v);
|
||||
if (config.allowValue(v))
|
||||
SINK(v);
|
||||
else
|
||||
SINK(v);
|
||||
|
||||
}
|
||||
|
||||
@@ -14,4 +14,8 @@
|
||||
| src/express.js:28:3:28:5 | req | src/express.js:22:30:32:1 | functio ... ar');\\n} |
|
||||
| src/express.js:29:3:29:5 | req | src/express.js:22:30:32:1 | functio ... ar');\\n} |
|
||||
| src/express.js:30:3:30:5 | req | src/express.js:22:30:32:1 | functio ... ar');\\n} |
|
||||
| src/express.js:47:3:47:5 | req | src/express.js:46:22:51:1 | functio ... ame];\\n} |
|
||||
| src/express.js:48:3:48:5 | req | src/express.js:46:22:51:1 | functio ... ame];\\n} |
|
||||
| src/express.js:49:3:49:5 | req | src/express.js:46:22:51:1 | functio ... ame];\\n} |
|
||||
| src/express.js:50:3:50:5 | req | src/express.js:46:22:51:1 | functio ... ame];\\n} |
|
||||
| src/responseExprs.js:17:5:17:7 | req | src/responseExprs.js:16:30:42:1 | functio ... }\\n} |
|
||||
|
||||
@@ -12,3 +12,7 @@
|
||||
| src/express.js:28:3:28:16 | req.get("foo") | header | src/express.js:22:30:32:1 | functio ... ar');\\n} |
|
||||
| src/express.js:29:3:29:19 | req.header("bar") | header | src/express.js:22:30:32:1 | functio ... ar');\\n} |
|
||||
| src/express.js:30:3:30:13 | req.cookies | cookie | src/express.js:22:30:32:1 | functio ... ar');\\n} |
|
||||
| src/express.js:47:3:47:17 | req.headers.baz | header | src/express.js:46:22:51:1 | functio ... ame];\\n} |
|
||||
| src/express.js:48:3:48:10 | req.host | header | src/express.js:46:22:51:1 | functio ... ame];\\n} |
|
||||
| src/express.js:49:3:49:14 | req.hostname | header | src/express.js:46:22:51:1 | functio ... ame];\\n} |
|
||||
| src/express.js:50:3:50:32 | req.hea ... erName] | header | src/express.js:46:22:51:1 | functio ... ame];\\n} |
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
| src/express.js:22:30:32:1 | functio ... ar');\\n} | src/express.js:22:39:22:41 | req | src/express.js:22:44:22:46 | res |
|
||||
| src/express.js:37:12:37:32 | functio ... res){} | src/express.js:37:22:37:24 | req | src/express.js:37:27:37:29 | res |
|
||||
| src/express.js:42:12:42:28 | (req, res) => f() | src/express.js:42:13:42:15 | req | src/express.js:42:18:42:20 | res |
|
||||
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:46:31:46:33 | req | src/express.js:46:36:46:38 | res |
|
||||
| src/responseExprs.js:4:23:6:1 | functio ... res1\\n} | src/responseExprs.js:4:32:4:34 | req | src/responseExprs.js:4:37:4:40 | res1 |
|
||||
| src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} | src/responseExprs.js:7:32:7:34 | req | src/responseExprs.js:7:37:7:40 | res2 |
|
||||
| src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} | src/responseExprs.js:10:39:10:41 | req | src/responseExprs.js:10:44:10:47 | res3 |
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
| src/express.js:34:14:34:52 | require ... handler | src/express.js:34:1:34:53 | app.get ... andler) | true |
|
||||
| src/express.js:39:9:39:20 | getHandler() | src/express.js:39:1:39:21 | app.use ... dler()) | false |
|
||||
| src/express.js:44:9:44:25 | getArrowHandler() | src/express.js:44:1:44:26 | app.use ... dler()) | false |
|
||||
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:46:1:51:2 | app.pos ... me];\\n}) | true |
|
||||
| src/responseExprs.js:4:23:6:1 | functio ... res1\\n} | src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | true |
|
||||
| src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} | src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | true |
|
||||
| src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} | src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | true |
|
||||
|
||||
@@ -16,3 +16,5 @@
|
||||
| src/express.js:16:19:18:3 | functio ... ");\\n } | src/express.js:39:9:39:20 | getHandler() |
|
||||
| src/express.js:16:19:18:3 | functio ... ");\\n } | src/express.js:44:9:44:25 | getArrowHandler() |
|
||||
| src/express.js:44:9:44:25 | getArrowHandler() | src/express.js:39:9:39:20 | getHandler() |
|
||||
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:39:9:39:20 | getHandler() |
|
||||
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:44:9:44:25 | getArrowHandler() |
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
| src/express.js:4:23:9:1 | functio ... res);\\n} | src/express.js:4:23:9:1 | functio ... res);\\n} |
|
||||
| src/express.js:16:19:18:3 | functio ... ");\\n } | src/express.js:16:19:18:3 | functio ... ");\\n } |
|
||||
| src/express.js:22:30:32:1 | functio ... ar');\\n} | src/express.js:22:30:32:1 | functio ... ar');\\n} |
|
||||
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:46:22:51:1 | functio ... ame];\\n} |
|
||||
| src/responseExprs.js:4:23:6:1 | functio ... res1\\n} | src/responseExprs.js:4:23:6:1 | functio ... res1\\n} |
|
||||
| src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} | src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} |
|
||||
| src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} | src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} |
|
||||
|
||||
@@ -7,4 +7,5 @@
|
||||
| src/csurf-example.js:18:9:18:30 | csrf({ ... true }) | src/csurf-example.js:40:27:40:48 | functio ... res) {} |
|
||||
| src/express.js:39:9:39:20 | getHandler() | src/express.js:44:9:44:25 | getArrowHandler() |
|
||||
| src/express.js:44:9:44:25 | getArrowHandler() | src/express.js:16:19:18:3 | functio ... ");\\n } |
|
||||
| src/express.js:44:9:44:25 | getArrowHandler() | src/express.js:46:22:51:1 | functio ... ame];\\n} |
|
||||
| src/subrouter.js:4:19:4:25 | protect | src/subrouter.js:5:14:5:28 | makeSubRouter() |
|
||||
|
||||
@@ -7,4 +7,5 @@
|
||||
| src/csurf-example.js:40:27:40:48 | functio ... res) {} | src/csurf-example.js:18:9:18:30 | csrf({ ... true }) |
|
||||
| src/express.js:16:19:18:3 | functio ... ");\\n } | src/express.js:44:9:44:25 | getArrowHandler() |
|
||||
| src/express.js:44:9:44:25 | getArrowHandler() | src/express.js:39:9:39:20 | getHandler() |
|
||||
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:44:9:44:25 | getArrowHandler() |
|
||||
| src/subrouter.js:5:14:5:28 | makeSubRouter() | src/subrouter.js:4:19:4:25 | protect |
|
||||
|
||||
@@ -14,4 +14,8 @@
|
||||
| src/express.js:22:30:32:1 | functio ... ar');\\n} | src/express.js:28:3:28:5 | req |
|
||||
| src/express.js:22:30:32:1 | functio ... ar');\\n} | src/express.js:29:3:29:5 | req |
|
||||
| src/express.js:22:30:32:1 | functio ... ar');\\n} | src/express.js:30:3:30:5 | req |
|
||||
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:47:3:47:5 | req |
|
||||
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:48:3:48:5 | req |
|
||||
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:49:3:49:5 | req |
|
||||
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:50:3:50:5 | req |
|
||||
| src/responseExprs.js:16:30:42:1 | functio ... }\\n} | src/responseExprs.js:17:5:17:7 | req |
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
| src/express.js:4:1:9:2 | app.get ... es);\\n}) | src/express.js:2:11:2:19 | express() | false |
|
||||
| src/express.js:16:3:18:4 | router. ... );\\n }) | src/express.js:2:11:2:19 | express() | false |
|
||||
| src/express.js:22:1:32:2 | app.pos ... r');\\n}) | src/express.js:2:11:2:19 | express() | false |
|
||||
| src/express.js:46:1:51:2 | app.pos ... me];\\n}) | src/express.js:2:11:2:19 | express() | false |
|
||||
| src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | src/responseExprs.js:2:11:2:19 | express() | false |
|
||||
| src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | src/responseExprs.js:2:11:2:19 | express() | false |
|
||||
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | src/responseExprs.js:2:11:2:19 | express() | false |
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
| src/express.js:39:1:39:21 | app.use ... dler()) | src/express.js:39:9:39:20 | getHandler() |
|
||||
| src/express.js:44:1:44:26 | app.use ... dler()) | src/express.js:42:12:42:28 | (req, res) => f() |
|
||||
| src/express.js:44:1:44:26 | app.use ... dler()) | src/express.js:44:9:44:25 | getArrowHandler() |
|
||||
| src/express.js:46:1:51:2 | app.pos ... me];\\n}) | src/express.js:46:22:51:1 | functio ... ame];\\n} |
|
||||
| src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | src/responseExprs.js:4:23:6:1 | functio ... res1\\n} |
|
||||
| src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} |
|
||||
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} |
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
| src/express.js:34:1:34:53 | app.get ... andler) | src/express.js:34:14:34:52 | require ... handler |
|
||||
| src/express.js:39:1:39:21 | app.use ... dler()) | src/express.js:39:9:39:20 | getHandler() |
|
||||
| src/express.js:44:1:44:26 | app.use ... dler()) | src/express.js:44:9:44:25 | getArrowHandler() |
|
||||
| src/express.js:46:1:51:2 | app.pos ... me];\\n}) | src/express.js:46:22:51:1 | functio ... ame];\\n} |
|
||||
| src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | src/responseExprs.js:4:23:6:1 | functio ... res1\\n} |
|
||||
| src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} |
|
||||
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} |
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
| src/express.js:34:1:34:53 | app.get ... andler) | src/express.js:34:14:34:52 | require ... handler |
|
||||
| src/express.js:39:1:39:21 | app.use ... dler()) | src/express.js:39:9:39:20 | getHandler() |
|
||||
| src/express.js:44:1:44:26 | app.use ... dler()) | src/express.js:44:9:44:25 | getArrowHandler() |
|
||||
| src/express.js:46:1:51:2 | app.pos ... me];\\n}) | src/express.js:46:22:51:1 | functio ... ame];\\n} |
|
||||
| src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | src/responseExprs.js:4:23:6:1 | functio ... res1\\n} |
|
||||
| src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} |
|
||||
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} |
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
| src/express.js:16:3:18:4 | router. ... );\\n }) | GET |
|
||||
| src/express.js:22:1:32:2 | app.pos ... r');\\n}) | POST |
|
||||
| src/express.js:34:1:34:53 | app.get ... andler) | GET |
|
||||
| src/express.js:46:1:51:2 | app.pos ... me];\\n}) | POST |
|
||||
| src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | GET |
|
||||
| src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | GET |
|
||||
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | GET |
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
| src/express.js:34:1:34:53 | app.get ... andler) | 0 | src/express.js:34:14:34:52 | require ... handler |
|
||||
| src/express.js:39:1:39:21 | app.use ... dler()) | 0 | src/express.js:39:9:39:20 | getHandler() |
|
||||
| src/express.js:44:1:44:26 | app.use ... dler()) | 0 | src/express.js:44:9:44:25 | getArrowHandler() |
|
||||
| src/express.js:46:1:51:2 | app.pos ... me];\\n}) | 0 | src/express.js:46:22:51:1 | functio ... ame];\\n} |
|
||||
| src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | 0 | src/responseExprs.js:4:23:6:1 | functio ... res1\\n} |
|
||||
| src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | 0 | src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} |
|
||||
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | 0 | src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} |
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
| src/express.js:34:1:34:53 | app.get ... andler) | src/express.js:2:11:2:19 | express() |
|
||||
| src/express.js:39:1:39:21 | app.use ... dler()) | src/express.js:2:11:2:19 | express() |
|
||||
| src/express.js:44:1:44:26 | app.use ... dler()) | src/express.js:2:11:2:19 | express() |
|
||||
| src/express.js:46:1:51:2 | app.pos ... me];\\n}) | src/express.js:2:11:2:19 | express() |
|
||||
| src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | src/responseExprs.js:2:11:2:19 | express() |
|
||||
| src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | src/responseExprs.js:2:11:2:19 | express() |
|
||||
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | src/responseExprs.js:2:11:2:19 | express() |
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
| src/express.js:4:1:9:2 | app.get ... es);\\n}) | src/express.js:2:11:2:19 | express() |
|
||||
| src/express.js:16:3:18:4 | router. ... );\\n }) | src/express.js:2:11:2:19 | express() |
|
||||
| src/express.js:22:1:32:2 | app.pos ... r');\\n}) | src/express.js:2:11:2:19 | express() |
|
||||
| src/express.js:46:1:51:2 | app.pos ... me];\\n}) | src/express.js:2:11:2:19 | express() |
|
||||
| src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | src/responseExprs.js:2:11:2:19 | express() |
|
||||
| src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | src/responseExprs.js:2:11:2:19 | express() |
|
||||
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | src/responseExprs.js:2:11:2:19 | express() |
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
| src/express.js:2:11:2:19 | express() | src/express.js:4:23:9:1 | functio ... res);\\n} |
|
||||
| src/express.js:2:11:2:19 | express() | src/express.js:16:19:18:3 | functio ... ");\\n } |
|
||||
| src/express.js:2:11:2:19 | express() | src/express.js:22:30:32:1 | functio ... ar');\\n} |
|
||||
| src/express.js:2:11:2:19 | express() | src/express.js:46:22:51:1 | functio ... ame];\\n} |
|
||||
| src/responseExprs.js:2:11:2:19 | express() | src/responseExprs.js:4:23:6:1 | functio ... res1\\n} |
|
||||
| src/responseExprs.js:2:11:2:19 | express() | src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} |
|
||||
| src/responseExprs.js:2:11:2:19 | express() | src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} |
|
||||
|
||||
@@ -75,7 +75,14 @@
|
||||
| src/express.js:2:11:2:19 | express() | src/express.js:44:5:44:7 | use | src/express.js:39:9:39:20 | getHandler() |
|
||||
| src/express.js:2:11:2:19 | express() | src/express.js:44:9:44:23 | getArrowHandler | src/express.js:39:9:39:20 | getHandler() |
|
||||
| src/express.js:2:11:2:19 | express() | src/express.js:44:9:44:25 | getArrowHandler() | src/express.js:39:9:39:20 | getHandler() |
|
||||
| src/express.js:2:11:2:19 | express() | src/express.js:45:1:45:0 | exit node of <toplevel> | src/express.js:44:9:44:25 | getArrowHandler() |
|
||||
| src/express.js:2:11:2:19 | express() | src/express.js:46:1:46:3 | app | src/express.js:44:9:44:25 | getArrowHandler() |
|
||||
| src/express.js:2:11:2:19 | express() | src/express.js:46:1:46:8 | app.post | src/express.js:44:9:44:25 | getArrowHandler() |
|
||||
| src/express.js:2:11:2:19 | express() | src/express.js:46:1:51:2 | app.pos ... me];\\n}) | src/express.js:44:9:44:25 | getArrowHandler() |
|
||||
| src/express.js:2:11:2:19 | express() | src/express.js:46:1:51:3 | app.pos ... e];\\n}); | src/express.js:44:9:44:25 | getArrowHandler() |
|
||||
| src/express.js:2:11:2:19 | express() | src/express.js:46:5:46:8 | post | src/express.js:44:9:44:25 | getArrowHandler() |
|
||||
| src/express.js:2:11:2:19 | express() | src/express.js:46:10:46:19 | '/headers' | src/express.js:44:9:44:25 | getArrowHandler() |
|
||||
| src/express.js:2:11:2:19 | express() | src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:44:9:44:25 | getArrowHandler() |
|
||||
| src/express.js:2:11:2:19 | express() | src/express.js:52:1:52:0 | exit node of <toplevel> | src/express.js:44:9:44:25 | getArrowHandler() |
|
||||
| src/subrouter.js:2:11:2:19 | express() | src/subrouter.js:4:1:4:26 | app.use ... rotect) | src/subrouter.js:4:19:4:25 | protect |
|
||||
| src/subrouter.js:2:11:2:19 | express() | src/subrouter.js:5:1:5:3 | app | src/subrouter.js:4:19:4:25 | protect |
|
||||
| src/subrouter.js:2:11:2:19 | express() | src/subrouter.js:5:1:5:7 | app.use | src/subrouter.js:4:19:4:25 | protect |
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
| src/express.js:4:23:9:1 | functio ... res);\\n} | src/express.js:2:11:2:19 | express() | src/express.js:4:32:4:34 | req | src/express.js:4:37:4:39 | res |
|
||||
| src/express.js:16:19:18:3 | functio ... ");\\n } | src/express.js:2:11:2:19 | express() | src/express.js:16:28:16:30 | req | src/express.js:16:33:16:35 | res |
|
||||
| src/express.js:22:30:32:1 | functio ... ar');\\n} | src/express.js:2:11:2:19 | express() | src/express.js:22:39:22:41 | req | src/express.js:22:44:22:46 | res |
|
||||
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:2:11:2:19 | express() | src/express.js:46:31:46:33 | req | src/express.js:46:36:46:38 | res |
|
||||
| src/responseExprs.js:4:23:6:1 | functio ... res1\\n} | src/responseExprs.js:2:11:2:19 | express() | src/responseExprs.js:4:32:4:34 | req | src/responseExprs.js:4:37:4:40 | res1 |
|
||||
| src/responseExprs.js:7:23:9:1 | functio ... res2;\\n} | src/responseExprs.js:2:11:2:19 | express() | src/responseExprs.js:7:32:7:34 | req | src/responseExprs.js:7:37:7:40 | res2 |
|
||||
| src/responseExprs.js:10:23:12:1 | functio ... res3;\\n} | src/responseExprs.js:2:11:2:19 | express() | src/responseExprs.js:10:39:10:41 | req | src/responseExprs.js:10:44:10:47 | res3 |
|
||||
|
||||
@@ -14,4 +14,8 @@
|
||||
| src/express.js:28:3:28:5 | req |
|
||||
| src/express.js:29:3:29:5 | req |
|
||||
| src/express.js:30:3:30:5 | req |
|
||||
| src/express.js:47:3:47:5 | req |
|
||||
| src/express.js:48:3:48:5 | req |
|
||||
| src/express.js:49:3:49:5 | req |
|
||||
| src/express.js:50:3:50:5 | req |
|
||||
| src/responseExprs.js:17:5:17:7 | req |
|
||||
|
||||
@@ -42,3 +42,10 @@ function getArrowHandler() {
|
||||
return (req, res) => f();
|
||||
}
|
||||
app.use(getArrowHandler());
|
||||
|
||||
app.post('/headers', function(req, res) {
|
||||
req.headers.baz;
|
||||
req.host;
|
||||
req.hostname;
|
||||
req.headers[config.headerName];
|
||||
});
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
| IdentityReplacement.js:1:27:1:30 | /"/g | This replaces '"' with itself. |
|
||||
| tst.js:1:13:1:16 | "\\\\" | This replaces '\\' with itself. |
|
||||
| tst.js:2:13:2:18 | /(\\\\)/ | This replaces '\\' with itself. |
|
||||
| tst.js:3:13:3:17 | /["]/ | This replaces '"' with itself. |
|
||||
| tst.js:6:13:6:18 | /foo/g | This replaces 'foo' with itself. |
|
||||
| tst.js:9:13:9:17 | /^\\\\/ | This replaces '\\' with itself. |
|
||||
| tst.js:10:13:10:17 | /\\\\$/ | This replaces '\\' with itself. |
|
||||
| tst.js:11:13:11:18 | /\\b\\\\/ | This replaces '\\' with itself. |
|
||||
| tst.js:12:13:12:18 | /\\B\\\\/ | This replaces '\\' with itself. |
|
||||
| tst.js:13:13:13:22 | /\\\\(?!\\\\)/ | This replaces '\\' with itself. |
|
||||
| tst.js:14:13:14:23 | /(?<!\\\\)\\\\/ | This replaces '\\' with itself. |
|
||||
| tst.js:16:13:16:15 | /^/ | This replaces the empty string with itself. |
|
||||
@@ -0,0 +1 @@
|
||||
var escaped = raw.replace(/"/g, '\"');
|
||||
@@ -0,0 +1 @@
|
||||
RegExp/IdentityReplacement.ql
|
||||
@@ -0,0 +1 @@
|
||||
var escaped = raw.replace(/"/g, '\\"');
|
||||
@@ -0,0 +1,16 @@
|
||||
raw.replace("\\", "\\"); // NOT OK
|
||||
raw.replace(/(\\)/, "\\"); // NOT OK
|
||||
raw.replace(/["]/, "\""); // NOT OK
|
||||
raw.replace("\\", "\\\\"); // OK
|
||||
|
||||
raw.replace(/foo/g, 'foo'); // NOT OK
|
||||
raw.replace(/foo/gi, 'foo'); // OK
|
||||
|
||||
raw.replace(/^\\/, "\\"); // NOT OK
|
||||
raw.replace(/\\$/, "\\"); // NOT OK
|
||||
raw.replace(/\b\\/, "\\"); // NOT OK
|
||||
raw.replace(/\B\\/, "\\"); // NOT OK
|
||||
raw.replace(/\\(?!\\)/, "\\"); // NOT OK
|
||||
raw.replace(/(?<!\\)\\/, "\\"); // NOT OK
|
||||
|
||||
raw.replace(/^/, ""); // NOT OK
|
||||
@@ -25,4 +25,5 @@
|
||||
| tainted-array-steps.js:15:29:15:43 | parts.join('/') | This path depends on $@. | tainted-array-steps.js:9:24:9:30 | req.url | a user-provided value |
|
||||
| tainted-require.js:7:19:7:37 | req.param("module") | This path depends on $@. | tainted-require.js:7:19:7:37 | req.param("module") | a user-provided value |
|
||||
| tainted-sendFile.js:7:16:7:33 | req.param("gimme") | This path depends on $@. | tainted-sendFile.js:7:16:7:33 | req.param("gimme") | a user-provided value |
|
||||
| tainted-sendFile.js:9:16:9:33 | req.param("gimme") | This path depends on $@. | tainted-sendFile.js:9:16:9:33 | req.param("gimme") | a user-provided value |
|
||||
| views.js:1:43:1:55 | req.params[0] | This path depends on $@. | views.js:1:43:1:55 | req.params[0] | a user-provided value |
|
||||
|
||||
@@ -5,4 +5,6 @@ var app = express();
|
||||
app.get('/some/path', function(req, res) {
|
||||
// BAD: sending a file based on un-sanitized query parameters
|
||||
res.sendFile(req.param("gimme"));
|
||||
// BAD: same as above
|
||||
res.sendfile(req.param("gimme"));
|
||||
});
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
| MissingCsrfMiddlewareBad.js:7:9:7:22 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | MissingCsrfMiddlewareBad.js:10:26:11:1 | functio ... es) {\\n} | here |
|
||||
| csurf_api_example.js:39:37:39:50 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | csurf_api_example.js:39:53:41:3 | functio ... e')\\n } | here |
|
||||
| csurf_example.js:18:9:18:22 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | csurf_example.js:29:40:31:1 | functio ... sed')\\n} | here |
|
||||
| lusca_example.js:9:9:9:22 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | lusca_example.js:23:42:25:1 | functio ... sed')\\n} | here |
|
||||
| lusca_example.js:9:9:9:22 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | lusca_example.js:27:40:29:1 | functio ... sed')\\n} | here |
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
var express = require('express')
|
||||
var cookieParser = require('cookie-parser')
|
||||
var bodyParser = require('body-parser')
|
||||
|
||||
var parseForm = bodyParser.urlencoded({ extended: false })
|
||||
var lusca = require('lusca');
|
||||
|
||||
var app = express()
|
||||
app.use(cookieParser())
|
||||
|
||||
app.post('/process', parseForm, lusca.csrf(), function (req, res) { // OK
|
||||
res.send('data is being processed')
|
||||
})
|
||||
|
||||
app.post('/process', parseForm, lusca({csrf:true}), function (req, res) { // OK
|
||||
res.send('data is being processed')
|
||||
})
|
||||
|
||||
app.post('/process', parseForm, lusca({csrf:{}}), function (req, res) { // OK
|
||||
res.send('data is being processed')
|
||||
})
|
||||
|
||||
app.post('/process', parseForm, lusca(), function (req, res) { // NOT OK - missing csrf option
|
||||
res.send('data is being processed')
|
||||
})
|
||||
|
||||
app.post('/process_unsafe', parseForm, function (req, res) { // NOT OK
|
||||
res.send('data is being processed')
|
||||
})
|
||||
Reference in New Issue
Block a user