mirror of
https://github.com/github/codeql.git
synced 2026-05-02 04:05:14 +02:00
Merge pull request #6433 from asgerf/js/tainted-url-suffix
Approved by erik-krogh
This commit is contained in:
4
javascript/change-notes/2021-08-05-tainted-url-suffix.md
Normal file
4
javascript/change-notes/2021-08-05-tainted-url-suffix.md
Normal file
@@ -0,0 +1,4 @@
|
||||
lgtm,codescanning
|
||||
* The `js/xss` query now reports fewer false positives in cases where
|
||||
`location.hash` flows to a jQuery `$()` call in a way that preserves
|
||||
the `#` prefix.
|
||||
@@ -34,7 +34,7 @@ module StringConcatenation {
|
||||
or
|
||||
exists(DataFlow::ArrayCreationNode array, DataFlow::MethodCallNode call |
|
||||
call = array.getAMethodCall("join") and
|
||||
call.getArgument(0).mayHaveStringValue("") and
|
||||
(call.getArgument(0).mayHaveStringValue("") or call.getNumArgument() = 0) and
|
||||
(
|
||||
// step from array element to array
|
||||
result = array.getElement(n) and
|
||||
|
||||
@@ -802,4 +802,11 @@ module StringOps {
|
||||
override boolean getPolarity() { result = polarity }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of a string method which performs substring extraction.
|
||||
*
|
||||
* These are `substring`, `substr`, and `slice`.
|
||||
*/
|
||||
string substringMethodName() { result = ["substring", "substr", "slice"] }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* Provides a flow label for reasoning about URLs with a tainted query and fragment part,
|
||||
* which we collectively refer to as the "suffix" of the URL.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
/**
|
||||
* Provides a flow label for reasoning about URLs with a tainted query and fragment part,
|
||||
* which we collectively refer to as the "suffix" of the URL.
|
||||
*/
|
||||
module TaintedUrlSuffix {
|
||||
private import DataFlow
|
||||
|
||||
/**
|
||||
* The flow label representing a URL with a tainted query and fragment part.
|
||||
*
|
||||
* Can also be accessed using `TaintedUrlSuffix::label()`.
|
||||
*/
|
||||
class TaintedUrlSuffixLabel extends FlowLabel {
|
||||
TaintedUrlSuffixLabel() { this = "tainted-url-suffix" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the flow label representing a URL with a tainted query and fragment part.
|
||||
*/
|
||||
FlowLabel label() { result instanceof TaintedUrlSuffixLabel }
|
||||
|
||||
/** 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"
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a flow step `src -> dst` involving the URL suffix taint label.
|
||||
*
|
||||
* This handles steps through string operations, promises, URL parsers, and URL accessors.
|
||||
*/
|
||||
predicate step(Node src, Node dst, FlowLabel srclbl, FlowLabel dstlbl) {
|
||||
// Inherit all ordinary taint steps except `x -> x.p` steps
|
||||
srclbl = label() and
|
||||
dstlbl = label() and
|
||||
TaintTracking::sharedTaintStep(src, dst) and
|
||||
not isSafeLocationProp(dst)
|
||||
or
|
||||
// Transition from URL suffix to full taint when extracting the query/fragment part.
|
||||
srclbl = label() and
|
||||
dstlbl.isTaint() and
|
||||
(
|
||||
exists(MethodCallNode call, string name |
|
||||
src = call.getReceiver() and
|
||||
dst = call and
|
||||
name = call.getMethodName()
|
||||
|
|
||||
// Substring that is not a prefix
|
||||
name = StringOps::substringMethodName() and
|
||||
not call.getArgument(0).getIntValue() = 0
|
||||
or
|
||||
// Split around '#' or '?' and extract the suffix
|
||||
name = "split" and
|
||||
call.getArgument(0).getStringValue() = ["#", "?"] and
|
||||
not exists(call.getAPropertyRead("0")) // Avoid false flow to the prefix
|
||||
or
|
||||
// Replace '#' and '?' with nothing
|
||||
name = "replace" and
|
||||
call.getArgument(0).getStringValue() = ["#", "?"] and
|
||||
call.getArgument(1).getStringValue() = ""
|
||||
or
|
||||
// The `get` call in `url.searchParams.get(x)` and `url.hashParams.get(x)`
|
||||
// The step should be safe since nothing else reachable by this flow label supports a method named 'get'.
|
||||
name = "get"
|
||||
or
|
||||
// Methods on URL objects from the Closure library
|
||||
name = "getDecodedQuery"
|
||||
or
|
||||
name = "getFragment"
|
||||
or
|
||||
name = "getParameterValue"
|
||||
or
|
||||
name = "getParameterValues"
|
||||
or
|
||||
name = "getQueryData"
|
||||
)
|
||||
or
|
||||
exists(PropRead read |
|
||||
src = read.getBase() and
|
||||
dst = read and
|
||||
// Unlike the `search` property, the `query` property from `url.parse` does not include the `?`.
|
||||
read.getPropertyName() = "query"
|
||||
)
|
||||
or
|
||||
// Assume calls to regexp.exec always extract query/fragment parameters.
|
||||
exists(MethodCallNode call |
|
||||
call = any(RegExpLiteral re).flow().(DataFlow::SourceNode).getAMethodCall("exec") and
|
||||
src = call.getArgument(0) and
|
||||
dst = call
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ module ClientSideUrlRedirect {
|
||||
// exclude all splits where only the prefix is accessed, which is safe for url-redirects.
|
||||
not exists(PropAccess pacc | mce = pacc.getBase() | pacc.getPropertyName() = "0")
|
||||
or
|
||||
(methodName = "substring" or methodName = "substr" or methodName = "slice") and
|
||||
methodName = StringOps::substringMethodName() and
|
||||
// exclude `location.href.substring(0, ...)` and similar, which can
|
||||
// never refer to the query string
|
||||
not mce.getArgument(0).(NumberLiteral).getIntValue() = 0
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
import javascript
|
||||
private import semmle.javascript.security.TaintedUrlSuffix
|
||||
|
||||
module DomBasedXss {
|
||||
import DomBasedXssCustomizations::DomBasedXss
|
||||
@@ -61,26 +62,14 @@ module DomBasedXss {
|
||||
not source = [DOM::locationRef(), DOM::locationRef().getAPropertyRead()] and
|
||||
label.isTaint()
|
||||
or
|
||||
source = DOM::locationSource() and
|
||||
label.isData() // Require transformation before reaching sink
|
||||
or
|
||||
source = DOM::locationRef().getAPropertyRead(["hash", "search"]) and
|
||||
label.isData() // Require transformation before reaching sink
|
||||
source = [DOM::locationSource(), DOM::locationRef().getAPropertyRead(["hash", "search"])] and
|
||||
label = TaintedUrlSuffix::label()
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) {
|
||||
sink instanceof JQueryHtmlOrSelectorSink and label.isTaint()
|
||||
}
|
||||
|
||||
override predicate isAdditionalFlowStep(
|
||||
DataFlow::Node pred, DataFlow::Node succ, DataFlow::FlowLabel predlbl,
|
||||
DataFlow::FlowLabel succlbl
|
||||
) {
|
||||
TaintTracking::sharedTaintStep(pred, succ) and
|
||||
predlbl.isData() and
|
||||
succlbl.isTaint()
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
super.isSanitizer(node)
|
||||
or
|
||||
@@ -91,15 +80,16 @@ module DomBasedXss {
|
||||
guard instanceof SanitizerGuard
|
||||
}
|
||||
|
||||
override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
DomBasedXss::isOptionallySanitizedEdge(pred, succ)
|
||||
override predicate isAdditionalFlowStep(
|
||||
DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl
|
||||
) {
|
||||
TaintedUrlSuffix::step(src, trg, inlbl, outlbl)
|
||||
or
|
||||
// Avoid stepping from location -> location.hash, as the .hash is already treated as a source
|
||||
// (with a different flow label)
|
||||
exists(DataFlow::PropRead read |
|
||||
read = DOM::locationRef().getAPropertyRead(["hash", "search"]) and
|
||||
pred = read.getBase() and
|
||||
succ = read
|
||||
exists(DataFlow::Node operator |
|
||||
StringConcatenation::taintStep(src, trg, operator, _) and
|
||||
StringConcatenation::getOperand(operator, 0).getStringValue() = "<" + any(string s) and
|
||||
inlbl = TaintedUrlSuffix::label() and
|
||||
outlbl.isTaint()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -734,15 +734,9 @@ module TaintedPath {
|
||||
exists(DataFlow::MethodCallNode mcn, string name |
|
||||
srclabel = dstlabel and dst = mcn and mcn.calls(src, name)
|
||||
|
|
||||
exists(string substringMethodName |
|
||||
substringMethodName = "substr" or
|
||||
substringMethodName = "substring" or
|
||||
substringMethodName = "slice"
|
||||
|
|
||||
name = substringMethodName and
|
||||
// to avoid very dynamic transformations, require at least one fixed index
|
||||
exists(mcn.getAnArgument().asExpr().getIntValue())
|
||||
)
|
||||
name = StringOps::substringMethodName() and
|
||||
// to avoid very dynamic transformations, require at least one fixed index
|
||||
exists(mcn.getAnArgument().asExpr().getIntValue())
|
||||
or
|
||||
exists(string argumentlessMethodName |
|
||||
argumentlessMethodName = "toLocaleLowerCase" or
|
||||
|
||||
@@ -100,9 +100,7 @@ module PolynomialReDoS {
|
||||
root instanceof RegExpCharacterClassEscape
|
||||
)
|
||||
or
|
||||
exists(string name | name = "slice" or name = "substring" or name = "substr" |
|
||||
this.(DataFlow::MethodCallNode).getMethodName() = name
|
||||
)
|
||||
this.(DataFlow::MethodCallNode).getMethodName() = StringOps::substringMethodName()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,10 @@
|
||||
| tst.js:53:10:53:34 | `one ${ ... three` |
|
||||
| tst.js:53:19:53:23 | two |
|
||||
| tst.js:71:14:71:18 | "two" |
|
||||
| tst.js:77:15:77:37 | ["one", ... three"] |
|
||||
| tst.js:77:23:77:27 | "two" |
|
||||
| tst.js:79:12:79:16 | array |
|
||||
| tst.js:79:12:79:23 | array.join() |
|
||||
| tst.js:87:5:87:14 | x += 'two' |
|
||||
| tst.js:87:10:87:14 | 'two' |
|
||||
| tst.js:89:3:89:3 | x |
|
||||
|
||||
@@ -36,7 +36,10 @@
|
||||
| tst.js:53:10:53:34 | `one ${ ... three` |
|
||||
| tst.js:53:19:53:23 | two |
|
||||
| tst.js:71:14:71:18 | "two" |
|
||||
| tst.js:77:15:77:37 | ["one", ... three"] |
|
||||
| tst.js:77:23:77:27 | "two" |
|
||||
| tst.js:79:12:79:16 | array |
|
||||
| tst.js:79:12:79:23 | array.join() |
|
||||
| tst.js:87:5:87:14 | x += 'two' |
|
||||
| tst.js:87:10:87:14 | 'two' |
|
||||
| tst.js:89:3:89:3 | x |
|
||||
|
||||
@@ -41,6 +41,8 @@ concatenation
|
||||
| tst.js:49:10:49:20 | xs.join("") |
|
||||
| tst.js:53:10:53:34 | `one ${ ... three` |
|
||||
| tst.js:61:10:61:34 | `first ... } last` |
|
||||
| tst.js:77:15:77:37 | ["one", ... three"] |
|
||||
| tst.js:79:12:79:23 | array.join() |
|
||||
| tst.js:87:5:87:14 | x |
|
||||
| tst.js:87:5:87:14 | x += 'two' |
|
||||
| tst.js:89:3:89:14 | x |
|
||||
@@ -126,6 +128,10 @@ concatenationOperand
|
||||
| tst.js:61:23:61:23 | x |
|
||||
| tst.js:61:27:61:27 | x |
|
||||
| tst.js:61:29:61:33 | last |
|
||||
| tst.js:77:15:77:37 | ["one", ... three"] |
|
||||
| tst.js:77:16:77:20 | "one" |
|
||||
| tst.js:77:23:77:27 | "two" |
|
||||
| tst.js:77:30:77:36 | "three" |
|
||||
| tst.js:87:5:87:5 | x |
|
||||
| tst.js:87:10:87:14 | 'two' |
|
||||
| tst.js:89:3:89:3 | x |
|
||||
@@ -210,6 +216,9 @@ concatenationLeaf
|
||||
| tst.js:61:23:61:23 | x |
|
||||
| tst.js:61:27:61:27 | x |
|
||||
| tst.js:61:29:61:33 | last |
|
||||
| tst.js:77:16:77:20 | "one" |
|
||||
| tst.js:77:23:77:27 | "two" |
|
||||
| tst.js:77:30:77:36 | "three" |
|
||||
| tst.js:87:5:87:5 | x |
|
||||
| tst.js:87:10:87:14 | 'two' |
|
||||
| tst.js:89:3:89:3 | x |
|
||||
@@ -334,6 +343,11 @@ concatenationNode
|
||||
| tst.js:61:23:61:23 | x |
|
||||
| tst.js:61:27:61:27 | x |
|
||||
| tst.js:61:29:61:33 | last |
|
||||
| tst.js:77:15:77:37 | ["one", ... three"] |
|
||||
| tst.js:77:16:77:20 | "one" |
|
||||
| tst.js:77:23:77:27 | "two" |
|
||||
| tst.js:77:30:77:36 | "three" |
|
||||
| tst.js:79:12:79:23 | array.join() |
|
||||
| tst.js:87:5:87:5 | x |
|
||||
| tst.js:87:5:87:14 | x |
|
||||
| tst.js:87:5:87:14 | x += 'two' |
|
||||
@@ -454,6 +468,10 @@ operand
|
||||
| tst.js:61:10:61:34 | `first ... } last` | 2 | tst.js:61:23:61:23 | x |
|
||||
| tst.js:61:10:61:34 | `first ... } last` | 3 | tst.js:61:27:61:27 | x |
|
||||
| tst.js:61:10:61:34 | `first ... } last` | 4 | tst.js:61:29:61:33 | last |
|
||||
| tst.js:77:15:77:37 | ["one", ... three"] | 0 | tst.js:77:16:77:20 | "one" |
|
||||
| tst.js:77:15:77:37 | ["one", ... three"] | 1 | tst.js:77:23:77:27 | "two" |
|
||||
| tst.js:77:15:77:37 | ["one", ... three"] | 2 | tst.js:77:30:77:36 | "three" |
|
||||
| tst.js:79:12:79:23 | array.join() | 0 | tst.js:77:15:77:37 | ["one", ... three"] |
|
||||
| tst.js:87:5:87:14 | x | 0 | tst.js:87:5:87:5 | x |
|
||||
| tst.js:87:5:87:14 | x | 1 | tst.js:87:10:87:14 | 'two' |
|
||||
| tst.js:87:5:87:14 | x += 'two' | 0 | tst.js:87:5:87:5 | x |
|
||||
@@ -518,6 +536,8 @@ nextLeaf
|
||||
| tst.js:61:19:61:19 | x | tst.js:61:23:61:23 | x |
|
||||
| tst.js:61:23:61:23 | x | tst.js:61:27:61:27 | x |
|
||||
| tst.js:61:27:61:27 | x | tst.js:61:29:61:33 | last |
|
||||
| tst.js:77:16:77:20 | "one" | tst.js:77:23:77:27 | "two" |
|
||||
| tst.js:77:23:77:27 | "two" | tst.js:77:30:77:36 | "three" |
|
||||
| tst.js:87:5:87:5 | x | tst.js:87:10:87:14 | 'two' |
|
||||
| tst.js:89:3:89:3 | x | tst.js:89:8:89:14 | 'three' |
|
||||
| tst.js:95:7:95:7 | x | tst.js:95:16:95:20 | 'two' |
|
||||
|
||||
@@ -222,6 +222,31 @@ nodes
|
||||
| jquery.js:16:38:16:52 | window.location |
|
||||
| jquery.js:16:38:16:52 | window.location |
|
||||
| jquery.js:16:38:16:63 | window. ... tring() |
|
||||
| jquery.js:18:7:18:33 | hash |
|
||||
| jquery.js:18:14:18:33 | window.location.hash |
|
||||
| jquery.js:18:14:18:33 | window.location.hash |
|
||||
| jquery.js:21:5:21:8 | hash |
|
||||
| jquery.js:21:5:21:21 | hash.substring(1) |
|
||||
| jquery.js:21:5:21:21 | hash.substring(1) |
|
||||
| jquery.js:22:5:22:8 | hash |
|
||||
| jquery.js:22:5:22:25 | hash.su ... (1, 10) |
|
||||
| jquery.js:22:5:22:25 | hash.su ... (1, 10) |
|
||||
| jquery.js:23:5:23:8 | hash |
|
||||
| jquery.js:23:5:23:18 | hash.substr(1) |
|
||||
| jquery.js:23:5:23:18 | hash.substr(1) |
|
||||
| jquery.js:24:5:24:8 | hash |
|
||||
| jquery.js:24:5:24:17 | hash.slice(1) |
|
||||
| jquery.js:24:5:24:17 | hash.slice(1) |
|
||||
| jquery.js:27:5:27:8 | hash |
|
||||
| jquery.js:27:5:27:25 | hash.re ... #', '') |
|
||||
| jquery.js:27:5:27:25 | hash.re ... #', '') |
|
||||
| jquery.js:28:5:28:26 | window. ... .search |
|
||||
| jquery.js:28:5:28:26 | window. ... .search |
|
||||
| jquery.js:28:5:28:43 | window. ... ?', '') |
|
||||
| jquery.js:28:5:28:43 | window. ... ?', '') |
|
||||
| jquery.js:34:5:34:25 | '<b>' + ... '</b>' |
|
||||
| jquery.js:34:5:34:25 | '<b>' + ... '</b>' |
|
||||
| jquery.js:34:13:34:16 | hash |
|
||||
| jwt-server.js:7:9:7:35 | taint |
|
||||
| jwt-server.js:7:17:7:35 | req.param("wobble") |
|
||||
| jwt-server.js:7:17:7:35 | req.param("wobble") |
|
||||
@@ -959,6 +984,30 @@ edges
|
||||
| jquery.js:16:38:16:52 | window.location | jquery.js:16:38:16:63 | window. ... tring() |
|
||||
| jquery.js:16:38:16:63 | window. ... tring() | jquery.js:16:19:16:64 | decodeU ... ring()) |
|
||||
| jquery.js:16:38:16:63 | window. ... tring() | jquery.js:16:19:16:64 | decodeU ... ring()) |
|
||||
| jquery.js:18:7:18:33 | hash | jquery.js:21:5:21:8 | hash |
|
||||
| jquery.js:18:7:18:33 | hash | jquery.js:22:5:22:8 | hash |
|
||||
| jquery.js:18:7:18:33 | hash | jquery.js:23:5:23:8 | hash |
|
||||
| jquery.js:18:7:18:33 | hash | jquery.js:24:5:24:8 | hash |
|
||||
| jquery.js:18:7:18:33 | hash | jquery.js:27:5:27:8 | hash |
|
||||
| jquery.js:18:7:18:33 | hash | jquery.js:34:13:34:16 | hash |
|
||||
| jquery.js:18:14:18:33 | window.location.hash | jquery.js:18:7:18:33 | hash |
|
||||
| jquery.js:18:14:18:33 | window.location.hash | jquery.js:18:7:18:33 | hash |
|
||||
| jquery.js:21:5:21:8 | hash | jquery.js:21:5:21:21 | hash.substring(1) |
|
||||
| jquery.js:21:5:21:8 | hash | jquery.js:21:5:21:21 | hash.substring(1) |
|
||||
| jquery.js:22:5:22:8 | hash | jquery.js:22:5:22:25 | hash.su ... (1, 10) |
|
||||
| jquery.js:22:5:22:8 | hash | jquery.js:22:5:22:25 | hash.su ... (1, 10) |
|
||||
| jquery.js:23:5:23:8 | hash | jquery.js:23:5:23:18 | hash.substr(1) |
|
||||
| jquery.js:23:5:23:8 | hash | jquery.js:23:5:23:18 | hash.substr(1) |
|
||||
| jquery.js:24:5:24:8 | hash | jquery.js:24:5:24:17 | hash.slice(1) |
|
||||
| jquery.js:24:5:24:8 | hash | jquery.js:24:5:24:17 | hash.slice(1) |
|
||||
| jquery.js:27:5:27:8 | hash | jquery.js:27:5:27:25 | hash.re ... #', '') |
|
||||
| jquery.js:27:5:27:8 | hash | jquery.js:27:5:27:25 | hash.re ... #', '') |
|
||||
| jquery.js:28:5:28:26 | window. ... .search | jquery.js:28:5:28:43 | window. ... ?', '') |
|
||||
| jquery.js:28:5:28:26 | window. ... .search | jquery.js:28:5:28:43 | window. ... ?', '') |
|
||||
| jquery.js:28:5:28:26 | window. ... .search | jquery.js:28:5:28:43 | window. ... ?', '') |
|
||||
| jquery.js:28:5:28:26 | window. ... .search | jquery.js:28:5:28:43 | window. ... ?', '') |
|
||||
| jquery.js:34:13:34:16 | hash | jquery.js:34:5:34:25 | '<b>' + ... '</b>' |
|
||||
| jquery.js:34:13:34:16 | hash | jquery.js:34:5:34:25 | '<b>' + ... '</b>' |
|
||||
| jwt-server.js:7:9:7:35 | taint | jwt-server.js:9:16:9:20 | taint |
|
||||
| jwt-server.js:7:17:7:35 | req.param("wobble") | jwt-server.js:7:9:7:35 | taint |
|
||||
| jwt-server.js:7:17:7:35 | req.param("wobble") | jwt-server.js:7:9:7:35 | taint |
|
||||
@@ -1493,6 +1542,13 @@ edges
|
||||
| jquery.js:14:19:14:58 | decodeU ... n.hash) | jquery.js:14:38:14:57 | window.location.hash | jquery.js:14:19:14:58 | decodeU ... n.hash) | Cross-site scripting vulnerability due to $@. | jquery.js:14:38:14:57 | window.location.hash | user-provided value |
|
||||
| jquery.js:15:19:15:60 | decodeU ... search) | jquery.js:15:38:15:59 | window. ... .search | jquery.js:15:19:15:60 | decodeU ... search) | Cross-site scripting vulnerability due to $@. | jquery.js:15:38:15:59 | window. ... .search | user-provided value |
|
||||
| jquery.js:16:19:16:64 | decodeU ... ring()) | jquery.js:16:38:16:52 | window.location | jquery.js:16:19:16:64 | decodeU ... ring()) | Cross-site scripting vulnerability due to $@. | jquery.js:16:38:16:52 | window.location | user-provided value |
|
||||
| jquery.js:21:5:21:21 | hash.substring(1) | jquery.js:18:14:18:33 | window.location.hash | jquery.js:21:5:21:21 | hash.substring(1) | Cross-site scripting vulnerability due to $@. | jquery.js:18:14:18:33 | window.location.hash | user-provided value |
|
||||
| jquery.js:22:5:22:25 | hash.su ... (1, 10) | jquery.js:18:14:18:33 | window.location.hash | jquery.js:22:5:22:25 | hash.su ... (1, 10) | Cross-site scripting vulnerability due to $@. | jquery.js:18:14:18:33 | window.location.hash | user-provided value |
|
||||
| jquery.js:23:5:23:18 | hash.substr(1) | jquery.js:18:14:18:33 | window.location.hash | jquery.js:23:5:23:18 | hash.substr(1) | Cross-site scripting vulnerability due to $@. | jquery.js:18:14:18:33 | window.location.hash | user-provided value |
|
||||
| jquery.js:24:5:24:17 | hash.slice(1) | jquery.js:18:14:18:33 | window.location.hash | jquery.js:24:5:24:17 | hash.slice(1) | Cross-site scripting vulnerability due to $@. | jquery.js:18:14:18:33 | window.location.hash | user-provided value |
|
||||
| jquery.js:27:5:27:25 | hash.re ... #', '') | jquery.js:18:14:18:33 | window.location.hash | jquery.js:27:5:27:25 | hash.re ... #', '') | Cross-site scripting vulnerability due to $@. | jquery.js:18:14:18:33 | window.location.hash | user-provided value |
|
||||
| jquery.js:28:5:28:43 | window. ... ?', '') | jquery.js:28:5:28:26 | window. ... .search | jquery.js:28:5:28:43 | window. ... ?', '') | Cross-site scripting vulnerability due to $@. | jquery.js:28:5:28:26 | window. ... .search | user-provided value |
|
||||
| jquery.js:34:5:34:25 | '<b>' + ... '</b>' | jquery.js:18:14:18:33 | window.location.hash | jquery.js:34:5:34:25 | '<b>' + ... '</b>' | Cross-site scripting vulnerability due to $@. | jquery.js:18:14:18:33 | window.location.hash | user-provided value |
|
||||
| jwt-server.js:11:19:11:29 | decoded.foo | jwt-server.js:7:17:7:35 | req.param("wobble") | jwt-server.js:11:19:11:29 | decoded.foo | Cross-site scripting vulnerability due to $@. | jwt-server.js:7:17:7:35 | req.param("wobble") | user-provided value |
|
||||
| nodemailer.js:13:11:13:69 | `Hi, yo ... sage}.` | nodemailer.js:13:50:13:66 | req.query.message | nodemailer.js:13:11:13:69 | `Hi, yo ... sage}.` | HTML injection vulnerability due to $@. | nodemailer.js:13:50:13:66 | req.query.message | user-provided value |
|
||||
| optionalSanitizer.js:6:18:6:23 | target | optionalSanitizer.js:2:16:2:39 | documen ... .search | optionalSanitizer.js:6:18:6:23 | target | Cross-site scripting vulnerability due to $@. | optionalSanitizer.js:2:16:2:39 | documen ... .search | user-provided value |
|
||||
|
||||
@@ -222,6 +222,31 @@ nodes
|
||||
| jquery.js:16:38:16:52 | window.location |
|
||||
| jquery.js:16:38:16:52 | window.location |
|
||||
| jquery.js:16:38:16:63 | window. ... tring() |
|
||||
| jquery.js:18:7:18:33 | hash |
|
||||
| jquery.js:18:14:18:33 | window.location.hash |
|
||||
| jquery.js:18:14:18:33 | window.location.hash |
|
||||
| jquery.js:21:5:21:8 | hash |
|
||||
| jquery.js:21:5:21:21 | hash.substring(1) |
|
||||
| jquery.js:21:5:21:21 | hash.substring(1) |
|
||||
| jquery.js:22:5:22:8 | hash |
|
||||
| jquery.js:22:5:22:25 | hash.su ... (1, 10) |
|
||||
| jquery.js:22:5:22:25 | hash.su ... (1, 10) |
|
||||
| jquery.js:23:5:23:8 | hash |
|
||||
| jquery.js:23:5:23:18 | hash.substr(1) |
|
||||
| jquery.js:23:5:23:18 | hash.substr(1) |
|
||||
| jquery.js:24:5:24:8 | hash |
|
||||
| jquery.js:24:5:24:17 | hash.slice(1) |
|
||||
| jquery.js:24:5:24:17 | hash.slice(1) |
|
||||
| jquery.js:27:5:27:8 | hash |
|
||||
| jquery.js:27:5:27:25 | hash.re ... #', '') |
|
||||
| jquery.js:27:5:27:25 | hash.re ... #', '') |
|
||||
| jquery.js:28:5:28:26 | window. ... .search |
|
||||
| jquery.js:28:5:28:26 | window. ... .search |
|
||||
| jquery.js:28:5:28:43 | window. ... ?', '') |
|
||||
| jquery.js:28:5:28:43 | window. ... ?', '') |
|
||||
| jquery.js:34:5:34:25 | '<b>' + ... '</b>' |
|
||||
| jquery.js:34:5:34:25 | '<b>' + ... '</b>' |
|
||||
| jquery.js:34:13:34:16 | hash |
|
||||
| jwt-server.js:7:9:7:35 | taint |
|
||||
| jwt-server.js:7:17:7:35 | req.param("wobble") |
|
||||
| jwt-server.js:7:17:7:35 | req.param("wobble") |
|
||||
@@ -977,6 +1002,30 @@ edges
|
||||
| jquery.js:16:38:16:52 | window.location | jquery.js:16:38:16:63 | window. ... tring() |
|
||||
| jquery.js:16:38:16:63 | window. ... tring() | jquery.js:16:19:16:64 | decodeU ... ring()) |
|
||||
| jquery.js:16:38:16:63 | window. ... tring() | jquery.js:16:19:16:64 | decodeU ... ring()) |
|
||||
| jquery.js:18:7:18:33 | hash | jquery.js:21:5:21:8 | hash |
|
||||
| jquery.js:18:7:18:33 | hash | jquery.js:22:5:22:8 | hash |
|
||||
| jquery.js:18:7:18:33 | hash | jquery.js:23:5:23:8 | hash |
|
||||
| jquery.js:18:7:18:33 | hash | jquery.js:24:5:24:8 | hash |
|
||||
| jquery.js:18:7:18:33 | hash | jquery.js:27:5:27:8 | hash |
|
||||
| jquery.js:18:7:18:33 | hash | jquery.js:34:13:34:16 | hash |
|
||||
| jquery.js:18:14:18:33 | window.location.hash | jquery.js:18:7:18:33 | hash |
|
||||
| jquery.js:18:14:18:33 | window.location.hash | jquery.js:18:7:18:33 | hash |
|
||||
| jquery.js:21:5:21:8 | hash | jquery.js:21:5:21:21 | hash.substring(1) |
|
||||
| jquery.js:21:5:21:8 | hash | jquery.js:21:5:21:21 | hash.substring(1) |
|
||||
| jquery.js:22:5:22:8 | hash | jquery.js:22:5:22:25 | hash.su ... (1, 10) |
|
||||
| jquery.js:22:5:22:8 | hash | jquery.js:22:5:22:25 | hash.su ... (1, 10) |
|
||||
| jquery.js:23:5:23:8 | hash | jquery.js:23:5:23:18 | hash.substr(1) |
|
||||
| jquery.js:23:5:23:8 | hash | jquery.js:23:5:23:18 | hash.substr(1) |
|
||||
| jquery.js:24:5:24:8 | hash | jquery.js:24:5:24:17 | hash.slice(1) |
|
||||
| jquery.js:24:5:24:8 | hash | jquery.js:24:5:24:17 | hash.slice(1) |
|
||||
| jquery.js:27:5:27:8 | hash | jquery.js:27:5:27:25 | hash.re ... #', '') |
|
||||
| jquery.js:27:5:27:8 | hash | jquery.js:27:5:27:25 | hash.re ... #', '') |
|
||||
| jquery.js:28:5:28:26 | window. ... .search | jquery.js:28:5:28:43 | window. ... ?', '') |
|
||||
| jquery.js:28:5:28:26 | window. ... .search | jquery.js:28:5:28:43 | window. ... ?', '') |
|
||||
| jquery.js:28:5:28:26 | window. ... .search | jquery.js:28:5:28:43 | window. ... ?', '') |
|
||||
| jquery.js:28:5:28:26 | window. ... .search | jquery.js:28:5:28:43 | window. ... ?', '') |
|
||||
| jquery.js:34:13:34:16 | hash | jquery.js:34:5:34:25 | '<b>' + ... '</b>' |
|
||||
| jquery.js:34:13:34:16 | hash | jquery.js:34:5:34:25 | '<b>' + ... '</b>' |
|
||||
| jwt-server.js:7:9:7:35 | taint | jwt-server.js:9:16:9:20 | taint |
|
||||
| jwt-server.js:7:17:7:35 | req.param("wobble") | jwt-server.js:7:9:7:35 | taint |
|
||||
| jwt-server.js:7:17:7:35 | req.param("wobble") | jwt-server.js:7:9:7:35 | taint |
|
||||
|
||||
@@ -14,4 +14,22 @@ function test() {
|
||||
elm.innerHTML = decodeURIComponent(window.location.hash); // NOT OK
|
||||
elm.innerHTML = decodeURIComponent(window.location.search); // NOT OK
|
||||
elm.innerHTML = decodeURIComponent(window.location.toString()); // NOT OK
|
||||
|
||||
let hash = window.location.hash;
|
||||
$(hash); // OK - start with '#'
|
||||
|
||||
$(hash.substring(1)); // NOT OK
|
||||
$(hash.substring(1, 10)); // NOT OK
|
||||
$(hash.substr(1)); // NOT OK
|
||||
$(hash.slice(1)); // NOT OK
|
||||
$(hash.substring(0, 10)); // OK
|
||||
|
||||
$(hash.replace('#', '')); // NOT OK
|
||||
$(window.location.search.replace('?', '')); // NOT OK
|
||||
$(hash.replace('!', '')); // OK
|
||||
$(hash.replace('blah', '')); // OK
|
||||
|
||||
$(hash + 'blah'); // OK
|
||||
$('blah' + hash); // OK - does not start with '<'
|
||||
$('<b>' + hash + '</b>'); // NOT OK
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user