mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #8783 from erik-krogh/jsAbstractBi
JS: don't initialize sanitizer-guards in the standard library
This commit is contained in:
@@ -118,6 +118,7 @@ class EndpointScoringResults extends ScoringResults {
|
||||
|
||||
pragma[inline]
|
||||
override predicate shouldResultBeIncluded(DataFlow::Node source, DataFlow::Node sink) {
|
||||
exists(source) and
|
||||
if getCfg().isKnownSink(sink)
|
||||
then any()
|
||||
else (
|
||||
|
||||
@@ -125,6 +125,6 @@ class BarrierGuardNodeAsSanitizerGuardNode extends TaintTracking::LabeledSanitiz
|
||||
}
|
||||
|
||||
override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) {
|
||||
sanitizes(outcome, e)
|
||||
sanitizes(outcome, e) and exists(label)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,10 +99,31 @@ class Configuration extends TaintTracking::Configuration {
|
||||
}
|
||||
|
||||
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
|
||||
guard instanceof DomBasedXss::SanitizerGuard
|
||||
guard instanceof PrefixStringSanitizerActivated or
|
||||
guard instanceof QuoteGuard or
|
||||
guard instanceof ContainsHtmlGuard
|
||||
}
|
||||
|
||||
override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
DomBasedXss::isOptionallySanitizedEdge(pred, succ)
|
||||
}
|
||||
}
|
||||
|
||||
private import semmle.javascript.security.dataflow.Xss::Shared as Shared
|
||||
|
||||
private class PrefixStringSanitizerActivated extends TaintTracking::SanitizerGuardNode,
|
||||
DomBasedXss::PrefixStringSanitizer {
|
||||
PrefixStringSanitizerActivated() { this = this }
|
||||
}
|
||||
|
||||
private class PrefixStringActivated extends DataFlow::FlowLabel, DomBasedXss::PrefixString {
|
||||
PrefixStringActivated() { this = this }
|
||||
}
|
||||
|
||||
private class QuoteGuard extends TaintTracking::SanitizerGuardNode, Shared::QuoteGuard {
|
||||
QuoteGuard() { this = this }
|
||||
}
|
||||
|
||||
private class ContainsHtmlGuard extends TaintTracking::SanitizerGuardNode, Shared::ContainsHtmlGuard {
|
||||
ContainsHtmlGuard() { this = this }
|
||||
}
|
||||
|
||||
@@ -9,12 +9,13 @@
|
||||
* each security vulnerability.
|
||||
*/
|
||||
|
||||
import semmle.javascript.security.dataflow.NosqlInjection
|
||||
import semmle.javascript.security.dataflow.SqlInjection
|
||||
import semmle.javascript.security.dataflow.TaintedPath
|
||||
import semmle.javascript.security.dataflow.DomBasedXss
|
||||
import semmle.javascript.security.dataflow.StoredXss
|
||||
import semmle.javascript.security.dataflow.XssThroughDom
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.NosqlInjectionQuery as NosqlInjection
|
||||
import semmle.javascript.security.dataflow.SqlInjectionQuery as SqlInjection
|
||||
import semmle.javascript.security.dataflow.TaintedPathQuery as TaintedPath
|
||||
import semmle.javascript.security.dataflow.DomBasedXssQuery as DomBasedXss
|
||||
import semmle.javascript.security.dataflow.StoredXssQuery as StoredXss
|
||||
import semmle.javascript.security.dataflow.XssThroughDomQuery as XssThroughDom
|
||||
import evaluation.EndToEndEvaluation
|
||||
|
||||
int numAlerts(DataFlow::Configuration cfg) {
|
||||
|
||||
@@ -193,7 +193,7 @@ module FlowFromSource {
|
||||
|
||||
/** The sinks are the endpoints we're extracting. */
|
||||
override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel lbl) {
|
||||
sink = getAnEndpoint(q)
|
||||
sink = getAnEndpoint(q) and exists(lbl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
**/*.testproj
|
||||
**/*.testproj
|
||||
**/*.actual
|
||||
@@ -4819,7 +4819,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/TaintedPath.js:17:23:17:35 | "/home/user/" | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:17:23:17:35 | "/home/user/" | Xss | notASinkReason | StringStartsWith | string |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:17:23:17:35 | "/home/user/" | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:18:33:18:36 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:18:33:18:36 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:18:33:18:36 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:18:33:18:36 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:18:33:18:36 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -5795,7 +5795,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:39:21:39:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:39:21:39:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:39:21:39:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:41:21:41:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:41:21:41:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:41:21:41:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:41:21:41:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:41:21:41:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -6007,7 +6007,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:76:21:76:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:76:21:76:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:76:21:76:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:78:22:78:25 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:78:22:78:25 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:78:22:78:25 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:78:22:78:25 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:78:22:78:25 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -6067,7 +6067,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:89:23:89:38 | '/home/user/www' | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:89:23:89:38 | '/home/user/www' | Xss | notASinkReason | StringStartsWith | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:89:23:89:38 | '/home/user/www' | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:90:31:90:34 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:90:31:90:34 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:90:31:90:34 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:90:31:90:34 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:90:31:90:34 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -6131,7 +6131,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:101:23:101:38 | '/home/user/www' | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:101:23:101:38 | '/home/user/www' | Xss | notASinkReason | StringStartsWith | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:101:23:101:38 | '/home/user/www' | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:102:31:102:34 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:102:31:102:34 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:102:31:102:34 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:102:31:102:34 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:102:31:102:34 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -6191,7 +6191,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:109:23:109:38 | "/home/user/www" | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:109:23:109:38 | "/home/user/www" | Xss | notASinkReason | StringStartsWith | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:109:23:109:38 | "/home/user/www" | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:110:21:110:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:110:21:110:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:110:21:110:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:110:21:110:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:110:21:110:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -6283,7 +6283,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:122:23:122:38 | "/home/user/www" | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:122:23:122:38 | "/home/user/www" | Xss | notASinkReason | StringStartsWith | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:122:23:122:38 | "/home/user/www" | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:123:21:123:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:123:21:123:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:123:21:123:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:123:21:123:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:123:21:123:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -6355,7 +6355,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:133:21:133:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:133:21:133:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:133:21:133:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:135:21:135:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:135:21:135:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:135:21:135:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:135:21:135:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:135:21:135:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -6415,7 +6415,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:141:23:141:38 | '/home/user/www' | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:141:23:141:38 | '/home/user/www' | Xss | notASinkReason | StringStartsWith | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:141:23:141:38 | '/home/user/www' | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:142:21:142:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:142:21:142:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:142:21:142:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:142:21:142:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:142:21:142:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -6483,7 +6483,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:151:21:151:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:151:21:151:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:151:21:151:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:153:21:153:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:153:21:153:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:153:21:153:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:153:21:153:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:153:21:153:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -6759,7 +6759,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:202:33:202:48 | '/home/user/www' | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:202:33:202:48 | '/home/user/www' | Xss | notASinkReason | StringStartsWith | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:202:33:202:48 | '/home/user/www' | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:203:21:203:34 | normalizedPath | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:203:21:203:34 | normalizedPath | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:203:21:203:34 | normalizedPath | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:203:21:203:34 | normalizedPath | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:203:21:203:34 | normalizedPath | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -7031,7 +7031,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:242:25:242:39 | self.dir.length | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:242:25:242:39 | self.dir.length | Xss | notASinkReason | BuiltinCallName | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:242:25:242:39 | self.dir.length | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:243:21:243:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:243:21:243:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:243:21:243:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:243:21:243:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:243:21:243:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -7079,7 +7079,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:247:21:247:35 | self.dir.length | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:247:21:247:35 | self.dir.length | Xss | notASinkReason | BuiltinCallName | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:247:21:247:35 | self.dir.length | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:248:21:248:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:248:21:248:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:248:21:248:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:248:21:248:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:248:21:248:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -7591,11 +7591,11 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:363:21:363:31 | requestPath | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:363:21:363:31 | requestPath | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:363:21:363:31 | requestPath | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:366:21:366:31 | requestPath | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:366:21:366:31 | requestPath | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:366:21:366:31 | requestPath | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:366:21:366:31 | requestPath | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:366:21:366:31 | requestPath | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:368:19:368:28 | targetPath | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:368:19:368:28 | targetPath | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:368:19:368:28 | targetPath | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:368:19:368:28 | targetPath | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:368:19:368:28 | targetPath | TaintedPath | sinkLabel | Sink | string |
|
||||
|
||||
@@ -4819,7 +4819,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/TaintedPath.js:17:23:17:35 | "/home/user/" | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:17:23:17:35 | "/home/user/" | Xss | notASinkReason | StringStartsWith | string |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:17:23:17:35 | "/home/user/" | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:18:33:18:36 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:18:33:18:36 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:18:33:18:36 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:18:33:18:36 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:18:33:18:36 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -5795,7 +5795,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:39:21:39:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:39:21:39:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:39:21:39:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:41:21:41:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:41:21:41:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:41:21:41:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:41:21:41:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:41:21:41:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -6007,7 +6007,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:76:21:76:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:76:21:76:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:76:21:76:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:78:22:78:25 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:78:22:78:25 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:78:22:78:25 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:78:22:78:25 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:78:22:78:25 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -6067,7 +6067,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:89:23:89:38 | '/home/user/www' | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:89:23:89:38 | '/home/user/www' | Xss | notASinkReason | StringStartsWith | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:89:23:89:38 | '/home/user/www' | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:90:31:90:34 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:90:31:90:34 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:90:31:90:34 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:90:31:90:34 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:90:31:90:34 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -6131,7 +6131,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:101:23:101:38 | '/home/user/www' | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:101:23:101:38 | '/home/user/www' | Xss | notASinkReason | StringStartsWith | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:101:23:101:38 | '/home/user/www' | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:102:31:102:34 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:102:31:102:34 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:102:31:102:34 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:102:31:102:34 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:102:31:102:34 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -6191,7 +6191,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:109:23:109:38 | "/home/user/www" | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:109:23:109:38 | "/home/user/www" | Xss | notASinkReason | StringStartsWith | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:109:23:109:38 | "/home/user/www" | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:110:21:110:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:110:21:110:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:110:21:110:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:110:21:110:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:110:21:110:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -6283,7 +6283,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:122:23:122:38 | "/home/user/www" | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:122:23:122:38 | "/home/user/www" | Xss | notASinkReason | StringStartsWith | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:122:23:122:38 | "/home/user/www" | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:123:21:123:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:123:21:123:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:123:21:123:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:123:21:123:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:123:21:123:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -6355,7 +6355,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:133:21:133:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:133:21:133:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:133:21:133:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:135:21:135:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:135:21:135:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:135:21:135:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:135:21:135:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:135:21:135:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -6415,7 +6415,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:141:23:141:38 | '/home/user/www' | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:141:23:141:38 | '/home/user/www' | Xss | notASinkReason | StringStartsWith | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:141:23:141:38 | '/home/user/www' | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:142:21:142:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:142:21:142:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:142:21:142:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:142:21:142:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:142:21:142:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -6483,7 +6483,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:151:21:151:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:151:21:151:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:151:21:151:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:153:21:153:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:153:21:153:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:153:21:153:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:153:21:153:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:153:21:153:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -6759,7 +6759,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:202:33:202:48 | '/home/user/www' | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:202:33:202:48 | '/home/user/www' | Xss | notASinkReason | StringStartsWith | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:202:33:202:48 | '/home/user/www' | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:203:21:203:34 | normalizedPath | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:203:21:203:34 | normalizedPath | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:203:21:203:34 | normalizedPath | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:203:21:203:34 | normalizedPath | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:203:21:203:34 | normalizedPath | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -7031,7 +7031,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:242:25:242:39 | self.dir.length | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:242:25:242:39 | self.dir.length | Xss | notASinkReason | BuiltinCallName | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:242:25:242:39 | self.dir.length | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:243:21:243:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:243:21:243:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:243:21:243:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:243:21:243:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:243:21:243:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -7079,7 +7079,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:247:21:247:35 | self.dir.length | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:247:21:247:35 | self.dir.length | Xss | notASinkReason | BuiltinCallName | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:247:21:247:35 | self.dir.length | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:248:21:248:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:248:21:248:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:248:21:248:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:248:21:248:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:248:21:248:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -7591,11 +7591,11 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:363:21:363:31 | requestPath | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:363:21:363:31 | requestPath | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:363:21:363:31 | requestPath | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:366:21:366:31 | requestPath | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:366:21:366:31 | requestPath | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:366:21:366:31 | requestPath | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:366:21:366:31 | requestPath | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:366:21:366:31 | requestPath | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:368:19:368:28 | targetPath | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:368:19:368:28 | targetPath | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:368:19:368:28 | targetPath | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:368:19:368:28 | targetPath | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:368:19:368:28 | targetPath | TaintedPath | sinkLabel | Sink | string |
|
||||
|
||||
@@ -1179,7 +1179,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/TaintedPath.js:15:29:15:48 | "/home/user/" + path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:15:29:15:48 | "/home/user/" + path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:15:29:15:48 | "/home/user/" + path | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:18:33:18:36 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:18:33:18:36 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:18:33:18:36 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:18:33:18:36 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/TaintedPath.js:18:33:18:36 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -1531,7 +1531,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:39:21:39:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:39:21:39:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:39:21:39:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:41:21:41:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:41:21:41:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:41:21:41:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:41:21:41:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:41:21:41:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -1591,7 +1591,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:76:21:76:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:76:21:76:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:76:21:76:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:78:22:78:25 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:78:22:78:25 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:78:22:78:25 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:78:22:78:25 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:78:22:78:25 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -1599,7 +1599,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:87:29:87:32 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:87:29:87:32 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:87:29:87:32 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:90:31:90:34 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:90:31:90:34 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:90:31:90:34 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:90:31:90:34 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:90:31:90:34 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -1607,11 +1607,11 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:99:29:99:32 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:99:29:99:32 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:99:29:99:32 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:102:31:102:34 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:102:31:102:34 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:102:31:102:34 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:102:31:102:34 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:102:31:102:34 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:110:21:110:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:110:21:110:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:110:21:110:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:110:21:110:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:110:21:110:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -1647,7 +1647,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:120:19:120:53 | pathMod ... .html') | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:120:19:120:53 | pathMod ... .html') | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:120:19:120:53 | pathMod ... .html') | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:123:21:123:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:123:21:123:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:123:21:123:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:123:21:123:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:123:21:123:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -1663,11 +1663,11 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:133:21:133:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:133:21:133:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:133:21:133:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:135:21:135:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:135:21:135:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:135:21:135:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:135:21:135:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:135:21:135:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:142:21:142:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:142:21:142:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:142:21:142:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:142:21:142:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:142:21:142:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -1679,7 +1679,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:151:21:151:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:151:21:151:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:151:21:151:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:153:21:153:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:153:21:153:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:153:21:153:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:153:21:153:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:153:21:153:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -1727,7 +1727,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:199:21:199:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:199:21:199:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:199:21:199:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:203:21:203:34 | normalizedPath | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:203:21:203:34 | normalizedPath | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:203:21:203:34 | normalizedPath | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:203:21:203:34 | normalizedPath | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:203:21:203:34 | normalizedPath | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -1783,7 +1783,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:242:25:242:39 | self.dir.length | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:242:25:242:39 | self.dir.length | Xss | notASinkReason | BuiltinCallName | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:242:25:242:39 | self.dir.length | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:243:21:243:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:243:21:243:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:243:21:243:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:243:21:243:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:243:21:243:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -1811,7 +1811,7 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:247:21:247:35 | self.dir.length | Xss | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:247:21:247:35 | self.dir.length | Xss | notASinkReason | BuiltinCallName | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:247:21:247:35 | self.dir.length | Xss | sinkLabel | NotASink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:248:21:248:24 | path | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:248:21:248:24 | path | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:248:21:248:24 | path | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:248:21:248:24 | path | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:248:21:248:24 | path | TaintedPath | sinkLabel | Sink | string |
|
||||
@@ -2019,11 +2019,11 @@ endpoints
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:363:21:363:31 | requestPath | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:363:21:363:31 | requestPath | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:363:21:363:31 | requestPath | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:366:21:366:31 | requestPath | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:366:21:366:31 | requestPath | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:366:21:366:31 | requestPath | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:366:21:366:31 | requestPath | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:366:21:366:31 | requestPath | TaintedPath | sinkLabel | Sink | string |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:368:19:368:28 | targetPath | TaintedPath | hasFlowFromSource | true | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:368:19:368:28 | targetPath | TaintedPath | hasFlowFromSource | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:368:19:368:28 | targetPath | TaintedPath | isConstantExpression | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:368:19:368:28 | targetPath | TaintedPath | isExcludedFromEndToEndEvaluation | false | boolean |
|
||||
| autogenerated/TaintedPath/normalizedPaths.js:368:19:368:28 | targetPath | TaintedPath | sinkLabel | Sink | string |
|
||||
|
||||
5
javascript/ql/lib/change-notes/2022-04-22-xss-library.md
Normal file
5
javascript/ql/lib/change-notes/2022-04-22-xss-library.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* The `ReflectedXss`, `StoredXss`, `XssThroughDom`, and `ExceptionXss` modules from `Xss.qll` have been deprecated.
|
||||
Use the `Customizations.qll` file belonging to the query instead.
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
private import semmle.javascript.security.dataflow.Xss
|
||||
private import semmle.javascript.security.dataflow.DomBasedXssCustomizations
|
||||
private import semmle.javascript.security.dataflow.CodeInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.ClientSideUrlRedirectCustomizations
|
||||
private import semmle.javascript.DynamicPropertyAccess
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import javascript
|
||||
private import semmle.javascript.security.dataflow.Xss as Xss
|
||||
private import semmle.javascript.security.dataflow.DomBasedXssCustomizations
|
||||
|
||||
module Cheerio {
|
||||
/** Gets a reference to the `cheerio` function, possibly with a loaded DOM. */
|
||||
@@ -95,7 +95,7 @@ module Cheerio {
|
||||
/**
|
||||
* An XSS sink through `cheerio`.
|
||||
*/
|
||||
class XssSink extends Xss::DomBasedXss::Sink {
|
||||
class XssSink extends DomBasedXss::Sink {
|
||||
XssSink() {
|
||||
exists(string name | this = cheerioObjectRef().getAMethodCall(name).getAnArgument() |
|
||||
JQuery::isMethodArgumentInterpretedAsHtml(name)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/** Provides classes and predicates modeling aspects of the `d3` library. */
|
||||
|
||||
private import javascript
|
||||
private import semmle.javascript.security.dataflow.Xss
|
||||
private import semmle.javascript.security.dataflow.DomBasedXssCustomizations
|
||||
|
||||
/** Provides classes and predicates modeling aspects of the `d3` library. */
|
||||
module D3 {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
private import semmle.javascript.security.dataflow.Xss
|
||||
private import semmle.javascript.security.dataflow.DomBasedXssCustomizations
|
||||
private import semmle.javascript.security.dataflow.ClientSideUrlRedirectCustomizations
|
||||
private import semmle.javascript.security.dataflow.CodeInjectionCustomizations
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import javascript
|
||||
private import SyntacticHeuristics
|
||||
private import semmle.javascript.security.dataflow.CodeInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.CommandInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.Xss as Xss
|
||||
private import semmle.javascript.security.dataflow.ReflectedXssCustomizations
|
||||
private import semmle.javascript.security.dataflow.SqlInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.NosqlInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.TaintedPathCustomizations
|
||||
@@ -16,6 +16,7 @@ private import semmle.javascript.security.dataflow.RegExpInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.ClientSideUrlRedirectCustomizations
|
||||
private import semmle.javascript.security.dataflow.ServerSideUrlRedirectCustomizations
|
||||
private import semmle.javascript.security.dataflow.InsecureRandomnessCustomizations
|
||||
private import semmle.javascript.security.dataflow.DomBasedXssCustomizations
|
||||
private import HeuristicSinks as Sinks
|
||||
|
||||
class HeuristicSink = Sinks::HeuristicSink;
|
||||
@@ -30,7 +31,7 @@ private class HeuristicCommandInjectionSink extends HeuristicSink, CommandInject
|
||||
}
|
||||
}
|
||||
|
||||
private class HeuristicDomBasedXssSink extends HeuristicSink, Xss::DomBasedXss::Sink {
|
||||
private class HeuristicDomBasedXssSink extends HeuristicSink, DomBasedXss::Sink {
|
||||
HeuristicDomBasedXssSink() {
|
||||
isAssignedToOrConcatenatedWith(this, "(?i)(html|innerhtml)") or
|
||||
isArgTo(this, "(?i)(html|render)") or
|
||||
@@ -39,7 +40,7 @@ private class HeuristicDomBasedXssSink extends HeuristicSink, Xss::DomBasedXss::
|
||||
}
|
||||
}
|
||||
|
||||
private class HeuristicReflectedXssSink extends HeuristicSink, Xss::ReflectedXss::Sink {
|
||||
private class HeuristicReflectedXssSink extends HeuristicSink, ReflectedXss::Sink {
|
||||
HeuristicReflectedXssSink() {
|
||||
isAssignedToOrConcatenatedWith(this, "(?i)(html|innerhtml)") or
|
||||
isArgTo(this, "(?i)(html|render)") or
|
||||
|
||||
@@ -4,9 +4,318 @@
|
||||
*/
|
||||
|
||||
import javascript
|
||||
private import semmle.javascript.dataflow.InferredTypes
|
||||
|
||||
module DomBasedXss {
|
||||
import Xss::DomBasedXss
|
||||
private import Xss::Shared as Shared
|
||||
|
||||
/** A data flow source for DOM-based XSS vulnerabilities. */
|
||||
abstract class Source extends Shared::Source { }
|
||||
|
||||
/** A data flow sink for DOM-based XSS vulnerabilities. */
|
||||
abstract class Sink extends Shared::Sink { }
|
||||
|
||||
/** A sanitizer for DOM-based XSS vulnerabilities. */
|
||||
abstract class Sanitizer extends Shared::Sanitizer { }
|
||||
|
||||
/**
|
||||
* An expression whose value is interpreted as HTML
|
||||
* and may be inserted into the DOM through a library.
|
||||
*/
|
||||
class LibrarySink extends Sink {
|
||||
LibrarySink() {
|
||||
// call to a jQuery method that interprets its argument as HTML
|
||||
exists(JQuery::MethodCall call |
|
||||
call.interpretsArgumentAsHtml(this) and
|
||||
not call.interpretsArgumentAsSelector(this) // Handled by `JQuerySelectorSink`
|
||||
)
|
||||
or
|
||||
// call to an Angular method that interprets its argument as HTML
|
||||
any(AngularJS::AngularJSCall call).interpretsArgumentAsHtml(this.asExpr())
|
||||
or
|
||||
// call to a WinJS function that interprets its argument as HTML
|
||||
exists(DataFlow::MethodCallNode mcn, string m |
|
||||
m = "setInnerHTMLUnsafe" or m = "setOuterHTMLUnsafe"
|
||||
|
|
||||
mcn.getMethodName() = m and
|
||||
this = mcn.getArgument(1)
|
||||
)
|
||||
or
|
||||
this = any(Typeahead::TypeaheadSuggestionFunction f).getAReturn()
|
||||
or
|
||||
this = any(Handlebars::SafeString s).getAnArgument()
|
||||
or
|
||||
this = any(JQuery::MethodCall call | call.getMethodName() = "jGrowl").getArgument(0)
|
||||
or
|
||||
// A construction of a JSDOM object (server side DOM), where scripts are allowed.
|
||||
exists(DataFlow::NewNode instance |
|
||||
instance = API::moduleImport("jsdom").getMember("JSDOM").getInstance().getAnImmediateUse() and
|
||||
this = instance.getArgument(0) and
|
||||
instance.getOptionArgument(1, "runScripts").mayHaveStringValue("dangerously")
|
||||
)
|
||||
or
|
||||
MooTools::interpretsNodeAsHtml(this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `prefix` is a prefix of `htmlString`, which may be intepreted as
|
||||
* HTML by a jQuery method.
|
||||
*/
|
||||
predicate isPrefixOfJQueryHtmlString(DataFlow::Node htmlString, DataFlow::Node prefix) {
|
||||
prefix = getAPrefixOfJQuerySelectorString(htmlString)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `prefix` is a prefix of `htmlString`, which may be intepreted as
|
||||
* HTML by a jQuery method.
|
||||
*/
|
||||
private DataFlow::Node getAPrefixOfJQuerySelectorString(DataFlow::Node htmlString) {
|
||||
any(JQuery::MethodCall call).interpretsArgumentAsSelector(htmlString) and
|
||||
result = htmlString
|
||||
or
|
||||
exists(DataFlow::Node pred | pred = getAPrefixOfJQuerySelectorString(htmlString) |
|
||||
result = StringConcatenation::getFirstOperand(pred)
|
||||
or
|
||||
result = pred.getAPredecessor()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An argument to the jQuery `$` function or similar, which is interpreted as either a selector
|
||||
* or as an HTML string depending on its first character.
|
||||
*/
|
||||
class JQueryHtmlOrSelectorArgument extends DataFlow::Node {
|
||||
JQueryHtmlOrSelectorArgument() {
|
||||
exists(JQuery::MethodCall call |
|
||||
call.interpretsArgumentAsHtml(this) and
|
||||
call.interpretsArgumentAsSelector(this) and
|
||||
pragma[only_bind_out](this.analyze()).getAType() = TTString()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a string that flows to the prefix of this argument. */
|
||||
string getAPrefix() { result = getAPrefixOfJQuerySelectorString(this).getStringValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An argument to the jQuery `$` function or similar, which may be interpreted as HTML.
|
||||
*
|
||||
* This is the same as `JQueryHtmlOrSelectorArgument`, excluding cases where the value
|
||||
* is prefixed by something other than `<`.
|
||||
*/
|
||||
class JQueryHtmlOrSelectorSink extends Sink, JQueryHtmlOrSelectorArgument {
|
||||
JQueryHtmlOrSelectorSink() {
|
||||
// If a prefix of the string is known, it must start with '<' or be an empty string
|
||||
forall(string strval | strval = this.getAPrefix() | strval.regexpMatch("(?s)\\s*<.*|"))
|
||||
}
|
||||
}
|
||||
|
||||
import ClientSideUrlRedirectCustomizations::ClientSideUrlRedirect as ClientSideUrlRedirect
|
||||
|
||||
/**
|
||||
* A write to a URL which may execute JavaScript code.
|
||||
*/
|
||||
class WriteUrlSink extends Sink instanceof ClientSideUrlRedirect::Sink {
|
||||
WriteUrlSink() { super.isXssSink() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `WriteUrlSink`. */
|
||||
deprecated class WriteURLSink = WriteUrlSink;
|
||||
|
||||
/**
|
||||
* An expression whose value is interpreted as HTML or CSS
|
||||
* and may be inserted into the DOM.
|
||||
*/
|
||||
class DomSink extends Sink {
|
||||
DomSink() {
|
||||
// Call to a DOM function that inserts its argument into the DOM
|
||||
any(DomMethodCallExpr call).interpretsArgumentsAsHtml(this.asExpr())
|
||||
or
|
||||
// Assignment to a dangerous DOM property
|
||||
exists(DomPropWriteNode pw |
|
||||
pw.interpretsValueAsHtml() and
|
||||
this = DataFlow::valueNode(pw.getRhs())
|
||||
)
|
||||
or
|
||||
// `html` or `source.html` properties of React Native `WebView`
|
||||
exists(ReactNative::WebViewElement webView, DataFlow::SourceNode source |
|
||||
source = webView or
|
||||
source = webView.getAPropertyWrite("source").getRhs().getALocalSource()
|
||||
|
|
||||
this = source.getAPropertyWrite("html").getRhs()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression whose value is interpreted as HTML.
|
||||
*/
|
||||
class HtmlParserSink extends Sink {
|
||||
HtmlParserSink() {
|
||||
exists(DataFlow::GlobalVarRefNode domParser |
|
||||
domParser.getName() = "DOMParser" and
|
||||
this = domParser.getAnInstantiation().getAMethodCall("parseFromString").getArgument(0)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::MethodCallNode ccf |
|
||||
isDomValue(ccf.getReceiver().asExpr()) and
|
||||
ccf.getMethodName() = "createContextualFragment" and
|
||||
this = ccf.getArgument(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A React `dangerouslySetInnerHTML` attribute, viewed as an XSS sink.
|
||||
*
|
||||
* Any write to the `__html` property of an object assigned to this attribute
|
||||
* is considered an XSS sink.
|
||||
*/
|
||||
class DangerouslySetInnerHtmlSink extends Sink, DataFlow::ValueNode {
|
||||
DangerouslySetInnerHtmlSink() {
|
||||
exists(DataFlow::Node danger, DataFlow::SourceNode valueSrc |
|
||||
exists(JsxAttribute attr |
|
||||
attr.getName() = "dangerouslySetInnerHTML" and
|
||||
attr.getValue() = danger.asExpr()
|
||||
)
|
||||
or
|
||||
exists(ReactElementDefinition def, DataFlow::ObjectLiteralNode props |
|
||||
props.flowsTo(def.getProps()) and
|
||||
props.hasPropertyWrite("dangerouslySetInnerHTML", danger)
|
||||
)
|
||||
|
|
||||
valueSrc.flowsTo(danger) and
|
||||
valueSrc.hasPropertyWrite("__html", this)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A React tooltip where the `data-html` attribute is set to `true`.
|
||||
*/
|
||||
class TooltipSink extends Sink {
|
||||
TooltipSink() {
|
||||
exists(JsxElement el |
|
||||
el.getAttributeByName("data-html").getStringValue() = "true" or
|
||||
el.getAttributeByName("data-html").getValue().mayHaveBooleanValue(true)
|
||||
|
|
||||
this = el.getAttributeByName("data-tip").getValue().flow()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The HTML body of an email, viewed as an XSS sink.
|
||||
*/
|
||||
class EmailHtmlBodySink extends Sink {
|
||||
EmailHtmlBodySink() { this = any(EmailSender sender).getHtmlBody() }
|
||||
|
||||
override string getVulnerabilityKind() { result = "HTML injection" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A write to the `template` option of a Vue instance, viewed as an XSS sink.
|
||||
*/
|
||||
class VueTemplateSink extends Sink {
|
||||
VueTemplateSink() {
|
||||
// Note: don't use Vue::Component#getTemplate as it includes an unwanted getALocalSource() step
|
||||
this = any(Vue::Component c).getOption("template")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The tag name argument to the `createElement` parameter of the
|
||||
* `render` method of a Vue instance, viewed as an XSS sink.
|
||||
*/
|
||||
class VueCreateElementSink extends Sink {
|
||||
VueCreateElementSink() {
|
||||
exists(Vue::Component c, DataFlow::FunctionNode f |
|
||||
f.flowsTo(c.getRender()) and
|
||||
this = f.getParameter(0).getACall().getArgument(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Vue `v-html` attribute, viewed as an XSS sink.
|
||||
*/
|
||||
class VHtmlSink extends Vue::VHtmlAttribute, Sink { }
|
||||
|
||||
/**
|
||||
* A raw interpolation tag in a template file, viewed as an XSS sink.
|
||||
*/
|
||||
class TemplateSink extends Sink {
|
||||
TemplateSink() {
|
||||
exists(Templating::TemplatePlaceholderTag tag |
|
||||
tag.isRawInterpolation() and
|
||||
this = tag.asDataFlowNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A value being piped into the `safe` pipe in a template file,
|
||||
* disabling subsequent HTML escaping.
|
||||
*/
|
||||
class SafePipe extends Sink {
|
||||
SafePipe() { this = Templating::getAPipeCall("safe").getArgument(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A property read from a safe property is considered a sanitizer.
|
||||
*/
|
||||
class SafePropertyReadSanitizer extends Sanitizer, DataFlow::Node {
|
||||
SafePropertyReadSanitizer() {
|
||||
exists(PropAccess pacc | pacc = this.asExpr() | pacc.getPropertyName() = "length")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A regexp replacement involving an HTML meta-character, viewed as a sanitizer for
|
||||
* XSS vulnerabilities.
|
||||
*
|
||||
* The XSS queries do not attempt to reason about correctness or completeness of sanitizers,
|
||||
* so any such replacement stops taint propagation.
|
||||
*/
|
||||
private class MetacharEscapeSanitizer extends Sanitizer, Shared::MetacharEscapeSanitizer { }
|
||||
|
||||
private class UriEncodingSanitizer extends Sanitizer, Shared::UriEncodingSanitizer { }
|
||||
|
||||
private class SerializeJavascriptSanitizer extends Sanitizer, Shared::SerializeJavascriptSanitizer {
|
||||
}
|
||||
|
||||
private class IsEscapedInSwitchSanitizer extends Sanitizer, Shared::IsEscapedInSwitchSanitizer { }
|
||||
|
||||
/**
|
||||
* Holds if there exists two dataflow edges to `succ`, where one edges is sanitized, and the other edge starts with `pred`.
|
||||
*/
|
||||
predicate isOptionallySanitizedEdge(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
exists(HtmlSanitizerCall sanitizer |
|
||||
// sanitized = sanitize ? sanitizer(source) : source;
|
||||
exists(ConditionalExpr branch, Variable var, VarAccess access |
|
||||
branch = succ.asExpr() and access = var.getAnAccess()
|
||||
|
|
||||
branch.getABranch() = access and
|
||||
pred.getEnclosingExpr() = access and
|
||||
sanitizer = branch.getABranch().flow() and
|
||||
sanitizer.getAnArgument().getEnclosingExpr() = var.getAnAccess()
|
||||
)
|
||||
or
|
||||
// sanitized = source; if (sanitize) {sanitized = sanitizer(source)};
|
||||
exists(SsaPhiNode phi, SsaExplicitDefinition a, SsaDefinition b |
|
||||
a = phi.getAnInput().getDefinition() and
|
||||
b = phi.getAnInput().getDefinition() and
|
||||
count(phi.getAnInput()) = 2 and
|
||||
not a = b and
|
||||
sanitizer = DataFlow::valueNode(a.getDef().getSource()) and
|
||||
sanitizer.getAnArgument().asExpr().(VarAccess).getVariable() = b.getSourceVariable()
|
||||
|
|
||||
pred = DataFlow::ssaDefinitionNode(b) and
|
||||
succ = DataFlow::ssaDefinitionNode(phi)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** A source of remote user input, considered as a flow source for DOM-based XSS. */
|
||||
class RemoteFlowSourceAsSource extends Source {
|
||||
@@ -16,10 +325,21 @@ module DomBasedXss {
|
||||
/**
|
||||
* A flow-label representing tainted values where the prefix is attacker controlled.
|
||||
*/
|
||||
class PrefixString extends DataFlow::FlowLabel {
|
||||
abstract class PrefixString extends DataFlow::FlowLabel {
|
||||
PrefixString() { this = "PrefixString" }
|
||||
}
|
||||
|
||||
/** Gets the flow-label representing tainted values where the prefix is attacker controlled. */
|
||||
PrefixString prefixLabel() { any() }
|
||||
|
||||
/**
|
||||
* A sanitizer that blocks the `PrefixString` label when the start of the string is being tested as being of a particular prefix.
|
||||
*/
|
||||
abstract class PrefixStringSanitizer extends TaintTracking::LabeledSanitizerGuardNode instanceof StringOps::StartsWith {
|
||||
override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) {
|
||||
e = super.getBaseString().asExpr() and
|
||||
label = prefixLabel() and
|
||||
outcome = super.getPolarity()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import javascript
|
||||
private import semmle.javascript.security.TaintedUrlSuffix
|
||||
import DomBasedXssCustomizations::DomBasedXss
|
||||
private import Xss::Shared as Shared
|
||||
|
||||
/**
|
||||
* DEPRECATED. Use `Vue::VHtmlSourceWrite` instead.
|
||||
@@ -24,7 +25,7 @@ deprecated class JQueryHtmlOrSelectorInjectionConfiguration = Configuration;
|
||||
*/
|
||||
class HTMLSink extends DataFlow::Node instanceof Sink {
|
||||
HTMLSink() {
|
||||
not this instanceof WriteURLSink and
|
||||
not this instanceof WriteUrlSink and
|
||||
not this instanceof JQueryHtmlOrSelectorSink
|
||||
}
|
||||
}
|
||||
@@ -60,7 +61,7 @@ class Configuration extends TaintTracking::Configuration {
|
||||
sink instanceof JQueryHtmlOrSelectorSink and
|
||||
label = [DataFlow::FlowLabel::taint(), prefixLabel()]
|
||||
or
|
||||
sink instanceof WriteURLSink and
|
||||
sink instanceof WriteUrlSink and
|
||||
label = prefixLabel()
|
||||
}
|
||||
|
||||
@@ -71,7 +72,9 @@ class Configuration extends TaintTracking::Configuration {
|
||||
}
|
||||
|
||||
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
|
||||
guard instanceof SanitizerGuard
|
||||
guard instanceof PrefixStringSanitizer or
|
||||
guard instanceof QuoteGuard or
|
||||
guard instanceof ContainsHtmlGuard
|
||||
}
|
||||
|
||||
override predicate isLabeledBarrier(DataFlow::Node node, DataFlow::FlowLabel lbl) {
|
||||
@@ -124,13 +127,19 @@ class Configuration extends TaintTracking::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A sanitizer that blocks the `PrefixString` label when the start of the string is being tested as being of a particular prefix.
|
||||
*/
|
||||
class PrefixStringSanitizer extends SanitizerGuard, TaintTracking::LabeledSanitizerGuardNode instanceof StringOps::StartsWith {
|
||||
override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) {
|
||||
e = super.getBaseString().asExpr() and
|
||||
label = prefixLabel() and
|
||||
outcome = super.getPolarity()
|
||||
}
|
||||
private class PrefixStringSanitizerActivated extends TaintTracking::SanitizerGuardNode,
|
||||
PrefixStringSanitizer {
|
||||
PrefixStringSanitizerActivated() { this = this }
|
||||
}
|
||||
|
||||
private class PrefixStringActivated extends DataFlow::FlowLabel, PrefixString {
|
||||
PrefixStringActivated() { this = this }
|
||||
}
|
||||
|
||||
private class QuoteGuard extends TaintTracking::SanitizerGuardNode, Shared::QuoteGuard {
|
||||
QuoteGuard() { this = this }
|
||||
}
|
||||
|
||||
private class ContainsHtmlGuard extends TaintTracking::SanitizerGuardNode, Shared::ContainsHtmlGuard {
|
||||
ContainsHtmlGuard() { this = this }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Provides default sources, sinks and sanitizers for reasoning about
|
||||
* cross-site scripting vulnerabilities where the taint-flow passes through a thrown
|
||||
* exception.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.RemoteFlowSources
|
||||
|
||||
/**
|
||||
* Provides sources, sinks, and sanitizers for reasoning about
|
||||
* cross-site scripting vulnerabilities where the taint-flow passes through a thrown
|
||||
* exception.
|
||||
*/
|
||||
module ExceptionXss {
|
||||
private import Xss::Shared as Shared
|
||||
|
||||
/** A data flow source for XSS caused by interpreting exception or error text as HTML. */
|
||||
abstract class Source extends DataFlow::Node {
|
||||
/**
|
||||
* Gets a flow label to associate with this source.
|
||||
*
|
||||
* For sources that should pass through a `throw/catch` before reaching the sink, use the
|
||||
* `NotYetThrown` labe. Otherwise use `taint` (the default).
|
||||
*/
|
||||
DataFlow::FlowLabel getAFlowLabel() { result.isTaint() }
|
||||
|
||||
/**
|
||||
* Gets a human-readable description of what type of error this refers to.
|
||||
*
|
||||
* The result should be capitalized and usable in the context of a noun.
|
||||
*/
|
||||
string getDescription() { result = "Error text" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A FlowLabel representing tainted data that has not been thrown in an exception.
|
||||
* In the js/xss-through-exception query data-flow can only reach a sink after
|
||||
* the data has been thrown as an exception, and data that has not been thrown
|
||||
* as an exception therefore has this flow label, and only this flow label, associated with it.
|
||||
*/
|
||||
abstract class NotYetThrown extends DataFlow::FlowLabel {
|
||||
NotYetThrown() { this = "NotYetThrown" }
|
||||
}
|
||||
|
||||
private class XssSourceAsSource extends Source {
|
||||
XssSourceAsSource() { this instanceof Shared::Source }
|
||||
|
||||
override DataFlow::FlowLabel getAFlowLabel() { result instanceof NotYetThrown }
|
||||
|
||||
override string getDescription() { result = "Exception text" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An error produced by validating using `ajv`.
|
||||
*
|
||||
* Such an error can contain property names from the input if the
|
||||
* underlying schema uses `additionalProperties` or `propertyPatterns`.
|
||||
*
|
||||
* For example, an input of form `{"<img src=x onerror=alert(1)>": 45}` might produce the error
|
||||
* `data/<img src=x onerror=alert(1)> should be string`.
|
||||
*/
|
||||
private class JsonSchemaValidationError extends Source {
|
||||
JsonSchemaValidationError() {
|
||||
this = any(JsonSchema::Ajv::Instance i).getAValidationError().getAnImmediateUse()
|
||||
or
|
||||
this = any(JsonSchema::Joi::JoiValidationErrorRead r).getAValidationResultAccess(_)
|
||||
}
|
||||
|
||||
override string getDescription() { result = "JSON schema validation error" }
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,9 @@
|
||||
import javascript
|
||||
import DomBasedXssCustomizations::DomBasedXss as DomBasedXssCustom
|
||||
import ReflectedXssCustomizations::ReflectedXss as ReflectedXssCustom
|
||||
import Xss as Xss
|
||||
import Xss::ExceptionXss
|
||||
import ExceptionXssCustomizations::ExceptionXss
|
||||
private import semmle.javascript.dataflow.InferredTypes
|
||||
import Xss::Shared as XssShared
|
||||
|
||||
/**
|
||||
* Gets the name of a method that does not leak taint from its arguments if an exception is thrown by the method.
|
||||
@@ -56,7 +56,7 @@ private predicate isNullOrUndefined(InferredType t) {
|
||||
*/
|
||||
predicate canThrowSensitiveInformation(DataFlow::Node node) {
|
||||
not isUnlikelyToThrowSensitiveInformation(node) and
|
||||
not node instanceof Xss::Shared::Sink and // removes duplicates from js/xss.
|
||||
not node instanceof XssShared::Sink and // removes duplicates from js/xss.
|
||||
(
|
||||
// in the case of reflective calls the below ensures that both InvokeNodes have no known callee.
|
||||
forex(DataFlow::InvokeNode call | call.getAnArgument() = node | not exists(call.getACallee()))
|
||||
@@ -71,7 +71,7 @@ predicate canThrowSensitiveInformation(DataFlow::Node node) {
|
||||
}
|
||||
|
||||
// Materialize flow labels
|
||||
private class ConcreteNotYetThrown extends Xss::ExceptionXss::NotYetThrown {
|
||||
private class ConcreteNotYetThrown extends NotYetThrown {
|
||||
ConcreteNotYetThrown() { this = this }
|
||||
}
|
||||
|
||||
@@ -133,14 +133,14 @@ class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "ExceptionXss" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) {
|
||||
source.(Xss::ExceptionXss::Source).getAFlowLabel() = label
|
||||
source.(Source).getAFlowLabel() = label
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) {
|
||||
sink instanceof Xss::Shared::Sink and not label instanceof NotYetThrown
|
||||
sink instanceof XssShared::Sink and not label instanceof NotYetThrown
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) { node instanceof Xss::Shared::Sanitizer }
|
||||
override predicate isSanitizer(DataFlow::Node node) { node instanceof XssShared::Sanitizer }
|
||||
|
||||
override predicate isAdditionalFlowStep(
|
||||
DataFlow::Node pred, DataFlow::Node succ, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl
|
||||
|
||||
@@ -6,7 +6,106 @@
|
||||
import javascript
|
||||
|
||||
module ReflectedXss {
|
||||
import Xss::ReflectedXss
|
||||
private import Xss::Shared as Shared
|
||||
|
||||
/** A data flow source for reflected XSS vulnerabilities. */
|
||||
abstract class Source extends Shared::Source { }
|
||||
|
||||
/** A data flow sink for reflected XSS vulnerabilities. */
|
||||
abstract class Sink extends Shared::Sink { }
|
||||
|
||||
/** A sanitizer for reflected XSS vulnerabilities. */
|
||||
abstract class Sanitizer extends Shared::Sanitizer { }
|
||||
|
||||
/**
|
||||
* An expression that is sent as part of an HTTP response, considered as an XSS sink.
|
||||
*
|
||||
* We exclude cases where the route handler sets either an unknown content type or
|
||||
* a content type that does not (case-insensitively) contain the string "html". This
|
||||
* is to prevent us from flagging plain-text or JSON responses as vulnerable.
|
||||
*/
|
||||
class HttpResponseSink extends Sink, DataFlow::ValueNode {
|
||||
override HTTP::ResponseSendArgument astNode;
|
||||
|
||||
HttpResponseSink() { not exists(getANonHtmlHeaderDefinition(astNode)) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a HeaderDefinition that defines a non-html content-type for `send`.
|
||||
*/
|
||||
HTTP::HeaderDefinition getANonHtmlHeaderDefinition(HTTP::ResponseSendArgument send) {
|
||||
exists(HTTP::RouteHandler h |
|
||||
send.getRouteHandler() = h and
|
||||
result = nonHtmlContentTypeHeader(h)
|
||||
|
|
||||
// The HeaderDefinition affects a response sent at `send`.
|
||||
headerAffects(result, send)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `h` may send a response with a content type other than HTML.
|
||||
*/
|
||||
HTTP::HeaderDefinition nonHtmlContentTypeHeader(HTTP::RouteHandler h) {
|
||||
result = h.getAResponseHeader("content-type") and
|
||||
not exists(string tp | result.defines("content-type", tp) | tp.regexpMatch("(?i).*html.*"))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a header set in `header` is likely to affect a response sent at `sender`.
|
||||
*/
|
||||
predicate headerAffects(HTTP::HeaderDefinition header, HTTP::ResponseSendArgument sender) {
|
||||
sender.getRouteHandler() = header.getRouteHandler() and
|
||||
(
|
||||
// `sender` is affected by a dominating `header`.
|
||||
header.getBasicBlock().(ReachableBasicBlock).dominates(sender.getBasicBlock())
|
||||
or
|
||||
// There is no dominating header, and `header` is non-local.
|
||||
not isLocalHeaderDefinition(header) and
|
||||
not exists(HTTP::HeaderDefinition dominatingHeader |
|
||||
dominatingHeader.getBasicBlock().(ReachableBasicBlock).dominates(sender.getBasicBlock())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the HeaderDefinition `header` seems to be local.
|
||||
* A HeaderDefinition is local if it dominates exactly one `ResponseSendArgument`.
|
||||
*
|
||||
* Recognizes variants of:
|
||||
* ```
|
||||
* response.writeHead(500, ...);
|
||||
* response.end('Some error');
|
||||
* return;
|
||||
* ```
|
||||
*/
|
||||
predicate isLocalHeaderDefinition(HTTP::HeaderDefinition header) {
|
||||
exists(ReachableBasicBlock headerBlock | headerBlock = header.getBasicBlock() |
|
||||
1 =
|
||||
strictcount(HTTP::ResponseSendArgument sender |
|
||||
sender.getRouteHandler() = header.getRouteHandler() and
|
||||
header.getBasicBlock().(ReachableBasicBlock).dominates(sender.getBasicBlock())
|
||||
) and
|
||||
// doesn't dominate something that looks like a callback.
|
||||
not exists(Expr e | e instanceof Function | headerBlock.dominates(e.getBasicBlock()))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A regexp replacement involving an HTML meta-character, viewed as a sanitizer for
|
||||
* XSS vulnerabilities.
|
||||
*
|
||||
* The XSS queries do not attempt to reason about correctness or completeness of sanitizers,
|
||||
* so any such replacement stops taint propagation.
|
||||
*/
|
||||
private class MetacharEscapeSanitizer extends Sanitizer, Shared::MetacharEscapeSanitizer { }
|
||||
|
||||
private class UriEncodingSanitizer extends Sanitizer, Shared::UriEncodingSanitizer { }
|
||||
|
||||
private class SerializeJavascriptSanitizer extends Sanitizer, Shared::SerializeJavascriptSanitizer {
|
||||
}
|
||||
|
||||
private class IsEscapedInSwitchSanitizer extends Sanitizer, Shared::IsEscapedInSwitchSanitizer { }
|
||||
|
||||
/** A third-party controllable request input, considered as a flow source for reflected XSS. */
|
||||
class ThirdPartyRequestInputAccessAsSource extends Source {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import javascript
|
||||
import ReflectedXssCustomizations::ReflectedXss
|
||||
private import Xss::Shared as Shared
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for reasoning about XSS.
|
||||
@@ -22,6 +23,15 @@ class Configuration extends TaintTracking::Configuration {
|
||||
}
|
||||
|
||||
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
|
||||
guard instanceof SanitizerGuard
|
||||
guard instanceof QuoteGuard or
|
||||
guard instanceof ContainsHtmlGuard
|
||||
}
|
||||
}
|
||||
|
||||
private class QuoteGuard extends TaintTracking::SanitizerGuardNode, Shared::QuoteGuard {
|
||||
QuoteGuard() { this = this }
|
||||
}
|
||||
|
||||
private class ContainsHtmlGuard extends TaintTracking::SanitizerGuardNode, Shared::ContainsHtmlGuard {
|
||||
ContainsHtmlGuard() { this = this }
|
||||
}
|
||||
|
||||
@@ -47,20 +47,6 @@ module ServerSideUrlRedirect {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to a function called `isLocalUrl` or similar, which is
|
||||
* considered to sanitize a variable for purposes of URL redirection.
|
||||
*/
|
||||
class LocalUrlSanitizingGuard extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode {
|
||||
LocalUrlSanitizingGuard() { this.getCalleeName().regexpMatch("(?i)(is_?)?local_?url") }
|
||||
|
||||
override predicate sanitizes(boolean outcome, Expr e) {
|
||||
// `isLocalUrl(e)` sanitizes `e` if it evaluates to `true`
|
||||
this.getAnArgument().asExpr() = e and
|
||||
outcome = true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A URL attribute for a React Native `WebView`.
|
||||
*/
|
||||
|
||||
@@ -36,3 +36,17 @@ class Configuration extends TaintTracking::Configuration {
|
||||
guard instanceof HostnameSanitizerGuard
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to a function called `isLocalUrl` or similar, which is
|
||||
* considered to sanitize a variable for purposes of URL redirection.
|
||||
*/
|
||||
class LocalUrlSanitizingGuard extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode {
|
||||
LocalUrlSanitizingGuard() { this.getCalleeName().regexpMatch("(?i)(is_?)?local_?url") }
|
||||
|
||||
override predicate sanitizes(boolean outcome, Expr e) {
|
||||
// `isLocalUrl(e)` sanitizes `e` if it evaluates to `true`
|
||||
this.getAnArgument().asExpr() = e and
|
||||
outcome = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Provides default sources, sinks and sanitizers for reasoning about
|
||||
* stored cross-site scripting vulnerabilities.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
/**
|
||||
* Provides default sources, sinks and sanitizers for reasoning about
|
||||
* stored cross-site scripting vulnerabilities.
|
||||
*/
|
||||
module StoredXss {
|
||||
private import Xss::Shared as Shared
|
||||
|
||||
/** A data flow source for stored XSS vulnerabilities. */
|
||||
abstract class Source extends Shared::Source { }
|
||||
|
||||
/** A data flow sink for stored XSS vulnerabilities. */
|
||||
abstract class Sink extends Shared::Sink { }
|
||||
|
||||
/** A sanitizer for stored XSS vulnerabilities. */
|
||||
abstract class Sanitizer extends Shared::Sanitizer { }
|
||||
|
||||
/** An arbitrary XSS sink, considered as a flow sink for stored XSS. */
|
||||
private class AnySink extends Sink {
|
||||
AnySink() { this instanceof Shared::Sink }
|
||||
}
|
||||
|
||||
/** A file name, considered as a flow source for stored XSS. */
|
||||
class FileNameSourceAsSource extends Source {
|
||||
FileNameSourceAsSource() { this instanceof FileNameSource }
|
||||
}
|
||||
|
||||
/** An instance of user-controlled torrent information, considered as a flow source for stored XSS. */
|
||||
class UserControlledTorrentInfoAsSource extends Source {
|
||||
UserControlledTorrentInfoAsSource() { this instanceof ParseTorrent::UserControlledTorrentInfo }
|
||||
}
|
||||
|
||||
/**
|
||||
* A regexp replacement involving an HTML meta-character, viewed as a sanitizer for
|
||||
* XSS vulnerabilities.
|
||||
*
|
||||
* The XSS queries do not attempt to reason about correctness or completeness of sanitizers,
|
||||
* so any such replacement stops taint propagation.
|
||||
*/
|
||||
private class MetacharEscapeSanitizer extends Sanitizer, Shared::MetacharEscapeSanitizer { }
|
||||
|
||||
private class UriEncodingSanitizer extends Sanitizer, Shared::UriEncodingSanitizer { }
|
||||
|
||||
private class SerializeJavascriptSanitizer extends Sanitizer, Shared::SerializeJavascriptSanitizer {
|
||||
}
|
||||
|
||||
private class IsEscapedInSwitchSanitizer extends Sanitizer, Shared::IsEscapedInSwitchSanitizer { }
|
||||
}
|
||||
@@ -4,7 +4,8 @@
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import Xss::StoredXss
|
||||
import StoredXssCustomizations::StoredXss
|
||||
private import Xss::Shared as Shared
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for reasoning about XSS.
|
||||
@@ -22,16 +23,15 @@ class Configuration extends TaintTracking::Configuration {
|
||||
}
|
||||
|
||||
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
|
||||
guard instanceof SanitizerGuard
|
||||
guard instanceof QuoteGuard or
|
||||
guard instanceof ContainsHtmlGuard
|
||||
}
|
||||
}
|
||||
|
||||
/** A file name, considered as a flow source for stored XSS. */
|
||||
class FileNameSourceAsSource extends Source {
|
||||
FileNameSourceAsSource() { this instanceof FileNameSource }
|
||||
private class QuoteGuard extends TaintTracking::SanitizerGuardNode, Shared::QuoteGuard {
|
||||
QuoteGuard() { this = this }
|
||||
}
|
||||
|
||||
/** An instance of user-controlled torrent information, considered as a flow source for stored XSS. */
|
||||
class UserControlledTorrentInfoAsSource extends Source {
|
||||
UserControlledTorrentInfoAsSource() { this instanceof ParseTorrent::UserControlledTorrentInfo }
|
||||
private class ContainsHtmlGuard extends TaintTracking::SanitizerGuardNode, Shared::ContainsHtmlGuard {
|
||||
ContainsHtmlGuard() { this = this }
|
||||
}
|
||||
|
||||
@@ -39,4 +39,29 @@ class Configration extends TaintTracking::Configuration {
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
DataFlow::localFieldStep(pred, succ)
|
||||
}
|
||||
|
||||
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
|
||||
guard instanceof PrefixStringSanitizer or
|
||||
guard instanceof QuoteGuard or
|
||||
guard instanceof ContainsHtmlGuard
|
||||
}
|
||||
}
|
||||
|
||||
private import semmle.javascript.security.dataflow.Xss::Shared as Shared
|
||||
|
||||
private class PrefixStringSanitizer extends TaintTracking::SanitizerGuardNode,
|
||||
DomBasedXss::PrefixStringSanitizer {
|
||||
PrefixStringSanitizer() { this = this }
|
||||
}
|
||||
|
||||
private class PrefixString extends DataFlow::FlowLabel, DomBasedXss::PrefixString {
|
||||
PrefixString() { this = this }
|
||||
}
|
||||
|
||||
private class QuoteGuard extends TaintTracking::SanitizerGuardNode, Shared::QuoteGuard {
|
||||
QuoteGuard() { this = this }
|
||||
}
|
||||
|
||||
private class ContainsHtmlGuard extends TaintTracking::SanitizerGuardNode, Shared::ContainsHtmlGuard {
|
||||
ContainsHtmlGuard() { this = this }
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import javascript
|
||||
private import semmle.javascript.dataflow.InferredTypes
|
||||
import semmle.javascript.security.dataflow.Xss
|
||||
import semmle.javascript.security.dataflow.DomBasedXssCustomizations
|
||||
|
||||
module UnsafeJQueryPlugin {
|
||||
private import DataFlow::FlowLabel
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.Xss
|
||||
import semmle.javascript.security.dataflow.DomBasedXssCustomizations
|
||||
import UnsafeJQueryPluginCustomizations::UnsafeJQueryPlugin
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
import javascript
|
||||
private import semmle.javascript.dataflow.InferredTypes
|
||||
|
||||
/** Provides classes and predicates shared between the XSS queries. */
|
||||
module Shared {
|
||||
@@ -24,9 +23,6 @@ module Shared {
|
||||
/** A sanitizer for XSS vulnerabilities. */
|
||||
abstract class Sanitizer extends DataFlow::Node { }
|
||||
|
||||
/** A sanitizer guard for XSS vulnerabilities. */
|
||||
abstract class SanitizerGuard extends TaintTracking::SanitizerGuardNode { }
|
||||
|
||||
/**
|
||||
* A global regexp replacement involving the `<`, `'`, or `"` meta-character, viewed as a sanitizer for
|
||||
* XSS vulnerabilities.
|
||||
@@ -71,7 +67,7 @@ module Shared {
|
||||
/**
|
||||
* A guard that checks if a string can contain quotes, which is a guard for strings that are inside a HTML attribute.
|
||||
*/
|
||||
class QuoteGuard extends SanitizerGuard, StringOps::Includes {
|
||||
abstract class QuoteGuard extends TaintTracking::SanitizerGuardNode, StringOps::Includes {
|
||||
QuoteGuard() {
|
||||
this.getSubstring().mayHaveStringValue("\"") and
|
||||
this.getBaseString()
|
||||
@@ -88,7 +84,7 @@ module Shared {
|
||||
* A sanitizer guard that checks for the existence of HTML chars in a string.
|
||||
* E.g. `/["'&<>]/.exec(str)`.
|
||||
*/
|
||||
class ContainsHtmlGuard extends SanitizerGuard, StringOps::RegExpTest {
|
||||
abstract class ContainsHtmlGuard extends TaintTracking::SanitizerGuardNode, StringOps::RegExpTest {
|
||||
ContainsHtmlGuard() {
|
||||
exists(RegExpCharacterClass regExp |
|
||||
regExp = this.getRegExp() and
|
||||
@@ -146,530 +142,42 @@ module Shared {
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides classes and predicates for the DOM-based XSS query. */
|
||||
module DomBasedXss {
|
||||
/** A data flow source for DOM-based XSS vulnerabilities. */
|
||||
abstract class Source extends Shared::Source { }
|
||||
|
||||
/** A data flow sink for DOM-based XSS vulnerabilities. */
|
||||
abstract class Sink extends Shared::Sink { }
|
||||
|
||||
/** A sanitizer for DOM-based XSS vulnerabilities. */
|
||||
abstract class Sanitizer extends Shared::Sanitizer { }
|
||||
|
||||
/** A sanitizer guard for DOM-based XSS vulnerabilities. */
|
||||
abstract class SanitizerGuard extends Shared::SanitizerGuard { }
|
||||
|
||||
/**
|
||||
* An expression whose value is interpreted as HTML
|
||||
* and may be inserted into the DOM through a library.
|
||||
*/
|
||||
class LibrarySink extends Sink {
|
||||
LibrarySink() {
|
||||
// call to a jQuery method that interprets its argument as HTML
|
||||
exists(JQuery::MethodCall call |
|
||||
call.interpretsArgumentAsHtml(this) and
|
||||
not call.interpretsArgumentAsSelector(this) // Handled by `JQuerySelectorSink`
|
||||
)
|
||||
or
|
||||
// call to an Angular method that interprets its argument as HTML
|
||||
any(AngularJS::AngularJSCall call).interpretsArgumentAsHtml(this.asExpr())
|
||||
or
|
||||
// call to a WinJS function that interprets its argument as HTML
|
||||
exists(DataFlow::MethodCallNode mcn, string m |
|
||||
m = "setInnerHTMLUnsafe" or m = "setOuterHTMLUnsafe"
|
||||
|
|
||||
mcn.getMethodName() = m and
|
||||
this = mcn.getArgument(1)
|
||||
)
|
||||
or
|
||||
this = any(Typeahead::TypeaheadSuggestionFunction f).getAReturn()
|
||||
or
|
||||
this = any(Handlebars::SafeString s).getAnArgument()
|
||||
or
|
||||
this = any(JQuery::MethodCall call | call.getMethodName() = "jGrowl").getArgument(0)
|
||||
or
|
||||
// A construction of a JSDOM object (server side DOM), where scripts are allowed.
|
||||
exists(DataFlow::NewNode instance |
|
||||
instance = API::moduleImport("jsdom").getMember("JSDOM").getInstance().getAnImmediateUse() and
|
||||
this = instance.getArgument(0) and
|
||||
instance.getOptionArgument(1, "runScripts").mayHaveStringValue("dangerously")
|
||||
)
|
||||
or
|
||||
MooTools::interpretsNodeAsHtml(this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `prefix` is a prefix of `htmlString`, which may be intepreted as
|
||||
* HTML by a jQuery method.
|
||||
*/
|
||||
predicate isPrefixOfJQueryHtmlString(DataFlow::Node htmlString, DataFlow::Node prefix) {
|
||||
prefix = getAPrefixOfJQuerySelectorString(htmlString)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `prefix` is a prefix of `htmlString`, which may be intepreted as
|
||||
* HTML by a jQuery method.
|
||||
*/
|
||||
private DataFlow::Node getAPrefixOfJQuerySelectorString(DataFlow::Node htmlString) {
|
||||
any(JQuery::MethodCall call).interpretsArgumentAsSelector(htmlString) and
|
||||
result = htmlString
|
||||
or
|
||||
exists(DataFlow::Node pred | pred = getAPrefixOfJQuerySelectorString(htmlString) |
|
||||
result = StringConcatenation::getFirstOperand(pred)
|
||||
or
|
||||
result = pred.getAPredecessor()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An argument to the jQuery `$` function or similar, which is interpreted as either a selector
|
||||
* or as an HTML string depending on its first character.
|
||||
*/
|
||||
class JQueryHtmlOrSelectorArgument extends DataFlow::Node {
|
||||
JQueryHtmlOrSelectorArgument() {
|
||||
exists(JQuery::MethodCall call |
|
||||
call.interpretsArgumentAsHtml(this) and
|
||||
call.interpretsArgumentAsSelector(this) and
|
||||
pragma[only_bind_out](this.analyze()).getAType() = TTString()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a string that flows to the prefix of this argument. */
|
||||
string getAPrefix() { result = getAPrefixOfJQuerySelectorString(this).getStringValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An argument to the jQuery `$` function or similar, which may be interpreted as HTML.
|
||||
*
|
||||
* This is the same as `JQueryHtmlOrSelectorArgument`, excluding cases where the value
|
||||
* is prefixed by something other than `<`.
|
||||
*/
|
||||
class JQueryHtmlOrSelectorSink extends Sink, JQueryHtmlOrSelectorArgument {
|
||||
JQueryHtmlOrSelectorSink() {
|
||||
// If a prefix of the string is known, it must start with '<' or be an empty string
|
||||
forall(string strval | strval = this.getAPrefix() | strval.regexpMatch("(?s)\\s*<.*|"))
|
||||
}
|
||||
}
|
||||
|
||||
import ClientSideUrlRedirectCustomizations::ClientSideUrlRedirect as ClientSideUrlRedirect
|
||||
|
||||
/**
|
||||
* A write to a URL which may execute JavaScript code.
|
||||
*/
|
||||
class WriteURLSink extends Sink instanceof ClientSideUrlRedirect::Sink {
|
||||
WriteURLSink() { super.isXssSink() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression whose value is interpreted as HTML or CSS
|
||||
* and may be inserted into the DOM.
|
||||
*/
|
||||
class DomSink extends Sink {
|
||||
DomSink() {
|
||||
// Call to a DOM function that inserts its argument into the DOM
|
||||
any(DomMethodCallExpr call).interpretsArgumentsAsHtml(this.asExpr())
|
||||
or
|
||||
// Assignment to a dangerous DOM property
|
||||
exists(DomPropWriteNode pw |
|
||||
pw.interpretsValueAsHtml() and
|
||||
this = DataFlow::valueNode(pw.getRhs())
|
||||
)
|
||||
or
|
||||
// `html` or `source.html` properties of React Native `WebView`
|
||||
exists(ReactNative::WebViewElement webView, DataFlow::SourceNode source |
|
||||
source = webView or
|
||||
source = webView.getAPropertyWrite("source").getRhs().getALocalSource()
|
||||
|
|
||||
this = source.getAPropertyWrite("html").getRhs()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression whose value is interpreted as HTML.
|
||||
*/
|
||||
class HtmlParserSink extends Sink {
|
||||
HtmlParserSink() {
|
||||
exists(DataFlow::GlobalVarRefNode domParser |
|
||||
domParser.getName() = "DOMParser" and
|
||||
this = domParser.getAnInstantiation().getAMethodCall("parseFromString").getArgument(0)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::MethodCallNode ccf |
|
||||
isDomValue(ccf.getReceiver().asExpr()) and
|
||||
ccf.getMethodName() = "createContextualFragment" and
|
||||
this = ccf.getArgument(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A React `dangerouslySetInnerHTML` attribute, viewed as an XSS sink.
|
||||
*
|
||||
* Any write to the `__html` property of an object assigned to this attribute
|
||||
* is considered an XSS sink.
|
||||
*/
|
||||
class DangerouslySetInnerHtmlSink extends Sink, DataFlow::ValueNode {
|
||||
DangerouslySetInnerHtmlSink() {
|
||||
exists(DataFlow::Node danger, DataFlow::SourceNode valueSrc |
|
||||
exists(JsxAttribute attr |
|
||||
attr.getName() = "dangerouslySetInnerHTML" and
|
||||
attr.getValue() = danger.asExpr()
|
||||
)
|
||||
or
|
||||
exists(ReactElementDefinition def, DataFlow::ObjectLiteralNode props |
|
||||
props.flowsTo(def.getProps()) and
|
||||
props.hasPropertyWrite("dangerouslySetInnerHTML", danger)
|
||||
)
|
||||
|
|
||||
valueSrc.flowsTo(danger) and
|
||||
valueSrc.hasPropertyWrite("__html", this)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A React tooltip where the `data-html` attribute is set to `true`.
|
||||
*/
|
||||
class TooltipSink extends Sink {
|
||||
TooltipSink() {
|
||||
exists(JsxElement el |
|
||||
el.getAttributeByName("data-html").getStringValue() = "true" or
|
||||
el.getAttributeByName("data-html").getValue().mayHaveBooleanValue(true)
|
||||
|
|
||||
this = el.getAttributeByName("data-tip").getValue().flow()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The HTML body of an email, viewed as an XSS sink.
|
||||
*/
|
||||
class EmailHtmlBodySink extends Sink {
|
||||
EmailHtmlBodySink() { this = any(EmailSender sender).getHtmlBody() }
|
||||
|
||||
override string getVulnerabilityKind() { result = "HTML injection" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A write to the `template` option of a Vue instance, viewed as an XSS sink.
|
||||
*/
|
||||
class VueTemplateSink extends Sink {
|
||||
VueTemplateSink() {
|
||||
// Note: don't use Vue::Component#getTemplate as it includes an unwanted getALocalSource() step
|
||||
this = any(Vue::Component c).getOption("template")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The tag name argument to the `createElement` parameter of the
|
||||
* `render` method of a Vue instance, viewed as an XSS sink.
|
||||
*/
|
||||
class VueCreateElementSink extends Sink {
|
||||
VueCreateElementSink() {
|
||||
exists(Vue::Component c, DataFlow::FunctionNode f |
|
||||
f.flowsTo(c.getRender()) and
|
||||
this = f.getParameter(0).getACall().getArgument(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Vue `v-html` attribute, viewed as an XSS sink.
|
||||
*/
|
||||
class VHtmlSink extends Vue::VHtmlAttribute, Sink { }
|
||||
|
||||
/**
|
||||
* A raw interpolation tag in a template file, viewed as an XSS sink.
|
||||
*/
|
||||
class TemplateSink extends Sink {
|
||||
TemplateSink() {
|
||||
exists(Templating::TemplatePlaceholderTag tag |
|
||||
tag.isRawInterpolation() and
|
||||
this = tag.asDataFlowNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A value being piped into the `safe` pipe in a template file,
|
||||
* disabling subsequent HTML escaping.
|
||||
*/
|
||||
class SafePipe extends Sink {
|
||||
SafePipe() { this = Templating::getAPipeCall("safe").getArgument(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A property read from a safe property is considered a sanitizer.
|
||||
*/
|
||||
class SafePropertyReadSanitizer extends Sanitizer, DataFlow::Node {
|
||||
SafePropertyReadSanitizer() {
|
||||
exists(PropAccess pacc | pacc = this.asExpr() | pacc.getPropertyName() = "length")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A regexp replacement involving an HTML meta-character, viewed as a sanitizer for
|
||||
* XSS vulnerabilities.
|
||||
*
|
||||
* The XSS queries do not attempt to reason about correctness or completeness of sanitizers,
|
||||
* so any such replacement stops taint propagation.
|
||||
*/
|
||||
private class MetacharEscapeSanitizer extends Sanitizer, Shared::MetacharEscapeSanitizer { }
|
||||
|
||||
private class UriEncodingSanitizer extends Sanitizer, Shared::UriEncodingSanitizer { }
|
||||
|
||||
private class SerializeJavascriptSanitizer extends Sanitizer, Shared::SerializeJavascriptSanitizer {
|
||||
}
|
||||
|
||||
private class IsEscapedInSwitchSanitizer extends Sanitizer, Shared::IsEscapedInSwitchSanitizer { }
|
||||
|
||||
private class QuoteGuard extends SanitizerGuard, Shared::QuoteGuard { }
|
||||
|
||||
/**
|
||||
* Holds if there exists two dataflow edges to `succ`, where one edges is sanitized, and the other edge starts with `pred`.
|
||||
*/
|
||||
predicate isOptionallySanitizedEdge(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
exists(HtmlSanitizerCall sanitizer |
|
||||
// sanitized = sanitize ? sanitizer(source) : source;
|
||||
exists(ConditionalExpr branch, Variable var, VarAccess access |
|
||||
branch = succ.asExpr() and access = var.getAnAccess()
|
||||
|
|
||||
branch.getABranch() = access and
|
||||
pred.getEnclosingExpr() = access and
|
||||
sanitizer = branch.getABranch().flow() and
|
||||
sanitizer.getAnArgument().getEnclosingExpr() = var.getAnAccess()
|
||||
)
|
||||
or
|
||||
// sanitized = source; if (sanitize) {sanitized = sanitizer(source)};
|
||||
exists(SsaPhiNode phi, SsaExplicitDefinition a, SsaDefinition b |
|
||||
a = phi.getAnInput().getDefinition() and
|
||||
b = phi.getAnInput().getDefinition() and
|
||||
count(phi.getAnInput()) = 2 and
|
||||
not a = b and
|
||||
sanitizer = DataFlow::valueNode(a.getDef().getSource()) and
|
||||
sanitizer.getAnArgument().asExpr().(VarAccess).getVariable() = b.getSourceVariable()
|
||||
|
|
||||
pred = DataFlow::ssaDefinitionNode(b) and
|
||||
succ = DataFlow::ssaDefinitionNode(phi)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private class ContainsHtmlGuard extends SanitizerGuard, Shared::ContainsHtmlGuard { }
|
||||
/**
|
||||
* DEPRECATED: Use the `DomBasedXssCustomizations.qll` file instead.
|
||||
* Provides classes and predicates for the DOM-based XSS query.
|
||||
*/
|
||||
deprecated module DomBasedXss {
|
||||
import DomBasedXssCustomizations::DomBasedXss
|
||||
}
|
||||
|
||||
/** Provides classes and predicates for the reflected XSS query. */
|
||||
module ReflectedXss {
|
||||
/** A data flow source for reflected XSS vulnerabilities. */
|
||||
abstract class Source extends Shared::Source { }
|
||||
|
||||
/** A data flow sink for reflected XSS vulnerabilities. */
|
||||
abstract class Sink extends Shared::Sink { }
|
||||
|
||||
/** A sanitizer for reflected XSS vulnerabilities. */
|
||||
abstract class Sanitizer extends Shared::Sanitizer { }
|
||||
|
||||
/** A sanitizer guard for reflected XSS vulnerabilities. */
|
||||
abstract class SanitizerGuard extends Shared::SanitizerGuard { }
|
||||
|
||||
/**
|
||||
* An expression that is sent as part of an HTTP response, considered as an XSS sink.
|
||||
*
|
||||
* We exclude cases where the route handler sets either an unknown content type or
|
||||
* a content type that does not (case-insensitively) contain the string "html". This
|
||||
* is to prevent us from flagging plain-text or JSON responses as vulnerable.
|
||||
*/
|
||||
class HttpResponseSink extends Sink, DataFlow::ValueNode {
|
||||
override HTTP::ResponseSendArgument astNode;
|
||||
|
||||
HttpResponseSink() { not exists(getANonHtmlHeaderDefinition(astNode)) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a HeaderDefinition that defines a non-html content-type for `send`.
|
||||
*/
|
||||
HTTP::HeaderDefinition getANonHtmlHeaderDefinition(HTTP::ResponseSendArgument send) {
|
||||
exists(HTTP::RouteHandler h |
|
||||
send.getRouteHandler() = h and
|
||||
result = nonHtmlContentTypeHeader(h)
|
||||
|
|
||||
// The HeaderDefinition affects a response sent at `send`.
|
||||
headerAffects(result, send)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `h` may send a response with a content type other than HTML.
|
||||
*/
|
||||
HTTP::HeaderDefinition nonHtmlContentTypeHeader(HTTP::RouteHandler h) {
|
||||
result = h.getAResponseHeader("content-type") and
|
||||
not exists(string tp | result.defines("content-type", tp) | tp.regexpMatch("(?i).*html.*"))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a header set in `header` is likely to affect a response sent at `sender`.
|
||||
*/
|
||||
predicate headerAffects(HTTP::HeaderDefinition header, HTTP::ResponseSendArgument sender) {
|
||||
sender.getRouteHandler() = header.getRouteHandler() and
|
||||
(
|
||||
// `sender` is affected by a dominating `header`.
|
||||
header.getBasicBlock().(ReachableBasicBlock).dominates(sender.getBasicBlock())
|
||||
or
|
||||
// There is no dominating header, and `header` is non-local.
|
||||
not isLocalHeaderDefinition(header) and
|
||||
not exists(HTTP::HeaderDefinition dominatingHeader |
|
||||
dominatingHeader.getBasicBlock().(ReachableBasicBlock).dominates(sender.getBasicBlock())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the HeaderDefinition `header` seems to be local.
|
||||
* A HeaderDefinition is local if it dominates exactly one `ResponseSendArgument`.
|
||||
*
|
||||
* Recognizes variants of:
|
||||
* ```
|
||||
* response.writeHead(500, ...);
|
||||
* response.end('Some error');
|
||||
* return;
|
||||
* ```
|
||||
*/
|
||||
predicate isLocalHeaderDefinition(HTTP::HeaderDefinition header) {
|
||||
exists(ReachableBasicBlock headerBlock | headerBlock = header.getBasicBlock() |
|
||||
1 =
|
||||
strictcount(HTTP::ResponseSendArgument sender |
|
||||
sender.getRouteHandler() = header.getRouteHandler() and
|
||||
header.getBasicBlock().(ReachableBasicBlock).dominates(sender.getBasicBlock())
|
||||
) and
|
||||
// doesn't dominate something that looks like a callback.
|
||||
not exists(Expr e | e instanceof Function | headerBlock.dominates(e.getBasicBlock()))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A regexp replacement involving an HTML meta-character, viewed as a sanitizer for
|
||||
* XSS vulnerabilities.
|
||||
*
|
||||
* The XSS queries do not attempt to reason about correctness or completeness of sanitizers,
|
||||
* so any such replacement stops taint propagation.
|
||||
*/
|
||||
private class MetacharEscapeSanitizer extends Sanitizer, Shared::MetacharEscapeSanitizer { }
|
||||
|
||||
private class UriEncodingSanitizer extends Sanitizer, Shared::UriEncodingSanitizer { }
|
||||
|
||||
private class SerializeJavascriptSanitizer extends Sanitizer, Shared::SerializeJavascriptSanitizer {
|
||||
}
|
||||
|
||||
private class IsEscapedInSwitchSanitizer extends Sanitizer, Shared::IsEscapedInSwitchSanitizer { }
|
||||
|
||||
private class QuoteGuard extends SanitizerGuard, Shared::QuoteGuard { }
|
||||
|
||||
private class ContainsHtmlGuard extends SanitizerGuard, Shared::ContainsHtmlGuard { }
|
||||
/**
|
||||
* DEPRECATED: Use the `DomBasedXssCustomizations.qll` file instead.
|
||||
* Provides classes and predicates for the reflected XSS query.
|
||||
*/
|
||||
deprecated module ReflectedXss {
|
||||
import ReflectedXssCustomizations::ReflectedXss
|
||||
}
|
||||
|
||||
/** Provides classes and predicates for the stored XSS query. */
|
||||
module StoredXss {
|
||||
/** A data flow source for stored XSS vulnerabilities. */
|
||||
abstract class Source extends Shared::Source { }
|
||||
|
||||
/** A data flow sink for stored XSS vulnerabilities. */
|
||||
abstract class Sink extends Shared::Sink { }
|
||||
|
||||
/** A sanitizer for stored XSS vulnerabilities. */
|
||||
abstract class Sanitizer extends Shared::Sanitizer { }
|
||||
|
||||
/** A sanitizer guard for stored XSS vulnerabilities. */
|
||||
abstract class SanitizerGuard extends Shared::SanitizerGuard { }
|
||||
|
||||
/** An arbitrary XSS sink, considered as a flow sink for stored XSS. */
|
||||
private class AnySink extends Sink {
|
||||
AnySink() { this instanceof Shared::Sink }
|
||||
}
|
||||
|
||||
/**
|
||||
* A regexp replacement involving an HTML meta-character, viewed as a sanitizer for
|
||||
* XSS vulnerabilities.
|
||||
*
|
||||
* The XSS queries do not attempt to reason about correctness or completeness of sanitizers,
|
||||
* so any such replacement stops taint propagation.
|
||||
*/
|
||||
private class MetacharEscapeSanitizer extends Sanitizer, Shared::MetacharEscapeSanitizer { }
|
||||
|
||||
private class UriEncodingSanitizer extends Sanitizer, Shared::UriEncodingSanitizer { }
|
||||
|
||||
private class SerializeJavascriptSanitizer extends Sanitizer, Shared::SerializeJavascriptSanitizer {
|
||||
}
|
||||
|
||||
private class IsEscapedInSwitchSanitizer extends Sanitizer, Shared::IsEscapedInSwitchSanitizer { }
|
||||
|
||||
private class QuoteGuard extends SanitizerGuard, Shared::QuoteGuard { }
|
||||
|
||||
private class ContainsHtmlGuard extends SanitizerGuard, Shared::ContainsHtmlGuard { }
|
||||
/**
|
||||
* DEPRECATED: Use the `StoredXssCustomizations.qll` file instead.
|
||||
* Provides classes and predicates for the stored XSS query.
|
||||
*/
|
||||
deprecated module StoredXss {
|
||||
import StoredXssCustomizations::StoredXss
|
||||
}
|
||||
|
||||
/** Provides classes and predicates for the XSS through DOM query. */
|
||||
module XssThroughDom {
|
||||
/** A data flow source for XSS through DOM vulnerabilities. */
|
||||
abstract class Source extends Shared::Source { }
|
||||
/**
|
||||
* DEPRECATED: Use the `XssThroughDomCustomizations.qll` file instead.
|
||||
* Provides classes and predicates for the XSS through DOM query.
|
||||
*/
|
||||
deprecated module XssThroughDom {
|
||||
import XssThroughDomCustomizations::XssThroughDom
|
||||
}
|
||||
|
||||
/** Provides classes for customizing the `ExceptionXss` query. */
|
||||
module ExceptionXss {
|
||||
/** A data flow source for XSS caused by interpreting exception or error text as HTML. */
|
||||
abstract class Source extends DataFlow::Node {
|
||||
/**
|
||||
* Gets a flow label to associate with this source.
|
||||
*
|
||||
* For sources that should pass through a `throw/catch` before reaching the sink, use the
|
||||
* `NotYetThrown` labe. Otherwise use `taint` (the default).
|
||||
*/
|
||||
DataFlow::FlowLabel getAFlowLabel() { result.isTaint() }
|
||||
|
||||
/**
|
||||
* Gets a human-readable description of what type of error this refers to.
|
||||
*
|
||||
* The result should be capitalized and usable in the context of a noun.
|
||||
*/
|
||||
string getDescription() { result = "Error text" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A FlowLabel representing tainted data that has not been thrown in an exception.
|
||||
* In the js/xss-through-exception query data-flow can only reach a sink after
|
||||
* the data has been thrown as an exception, and data that has not been thrown
|
||||
* as an exception therefore has this flow label, and only this flow label, associated with it.
|
||||
*/
|
||||
abstract class NotYetThrown extends DataFlow::FlowLabel {
|
||||
NotYetThrown() { this = "NotYetThrown" }
|
||||
}
|
||||
|
||||
private class XssSourceAsSource extends Source {
|
||||
XssSourceAsSource() { this instanceof Shared::Source }
|
||||
|
||||
override DataFlow::FlowLabel getAFlowLabel() { result instanceof NotYetThrown }
|
||||
|
||||
override string getDescription() { result = "Exception text" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An error produced by validating using `ajv`.
|
||||
*
|
||||
* Such an error can contain property names from the input if the
|
||||
* underlying schema uses `additionalProperties` or `propertyPatterns`.
|
||||
*
|
||||
* For example, an input of form `{"<img src=x onerror=alert(1)>": 45}` might produce the error
|
||||
* `data/<img src=x onerror=alert(1)> should be string`.
|
||||
*/
|
||||
private class JsonSchemaValidationError extends Source {
|
||||
JsonSchemaValidationError() {
|
||||
this = any(JsonSchema::Ajv::Instance i).getAValidationError().getAnImmediateUse()
|
||||
or
|
||||
this = any(JsonSchema::Joi::JoiValidationErrorRead r).getAValidationResultAccess(_)
|
||||
}
|
||||
|
||||
override string getDescription() { result = "JSON schema validation error" }
|
||||
}
|
||||
/**
|
||||
* DEPRECATED: Use the `ExceptionXssCustomizations.qll` file instead.
|
||||
* Provides classes for customizing the `ExceptionXss` query.
|
||||
*/
|
||||
deprecated module ExceptionXss {
|
||||
import ExceptionXssCustomizations::ExceptionXss
|
||||
}
|
||||
|
||||
@@ -9,9 +9,12 @@ import javascript
|
||||
* Sources for cross-site scripting vulnerabilities through the DOM.
|
||||
*/
|
||||
module XssThroughDom {
|
||||
import Xss::XssThroughDom
|
||||
private import Xss::Shared as Shared
|
||||
private import semmle.javascript.dataflow.InferredTypes
|
||||
private import semmle.javascript.security.dataflow.Xss::DomBasedXss as DomBasedXss
|
||||
private import semmle.javascript.security.dataflow.DomBasedXssCustomizations
|
||||
|
||||
/** A data flow source for XSS through DOM vulnerabilities. */
|
||||
abstract class Source extends Shared::Source { }
|
||||
|
||||
/**
|
||||
* Gets an attribute name that could store user-controlled data.
|
||||
@@ -134,34 +137,6 @@ module XssThroughDom {
|
||||
/** DEPRECATED: Alias for DomTextSource */
|
||||
deprecated class DOMTextSource = DomTextSource;
|
||||
|
||||
/**
|
||||
* A test of form `typeof x === "something"`, preventing `x` from being a string in some cases.
|
||||
*
|
||||
* This sanitizer helps prune infeasible paths in type-overloaded functions.
|
||||
*/
|
||||
class TypeTestGuard extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode {
|
||||
override EqualityTest astNode;
|
||||
Expr operand;
|
||||
boolean polarity;
|
||||
|
||||
TypeTestGuard() {
|
||||
exists(TypeofTag tag | TaintTracking::isTypeofGuard(astNode, operand, tag) |
|
||||
// typeof x === "string" sanitizes `x` when it evaluates to false
|
||||
tag = "string" and
|
||||
polarity = astNode.getPolarity().booleanNot()
|
||||
or
|
||||
// typeof x === "object" sanitizes `x` when it evaluates to true
|
||||
tag != "string" and
|
||||
polarity = astNode.getPolarity()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate sanitizes(boolean outcome, Expr e) {
|
||||
polarity = outcome and
|
||||
e = operand
|
||||
}
|
||||
}
|
||||
|
||||
/** The `files` property of an `<input />` element */
|
||||
class FilesSource extends Source {
|
||||
FilesSource() { this = DOM::domValueRef().getAPropertyRead("files") }
|
||||
|
||||
@@ -5,9 +5,8 @@
|
||||
|
||||
import javascript
|
||||
private import semmle.javascript.dataflow.InferredTypes
|
||||
import Xss::XssThroughDom
|
||||
private import XssThroughDomCustomizations::XssThroughDom
|
||||
private import semmle.javascript.security.dataflow.Xss::DomBasedXss as DomBasedXss
|
||||
private import semmle.javascript.security.dataflow.DomBasedXssCustomizations
|
||||
private import semmle.javascript.security.dataflow.UnsafeJQueryPluginCustomizations::UnsafeJQueryPlugin as UnsafeJQuery
|
||||
|
||||
/**
|
||||
@@ -29,7 +28,9 @@ class Configuration extends TaintTracking::Configuration {
|
||||
guard instanceof TypeTestGuard or
|
||||
guard instanceof UnsafeJQuery::PropertyPresenceSanitizer or
|
||||
guard instanceof UnsafeJQuery::NumberGuard or
|
||||
guard instanceof DomBasedXss::SanitizerGuard
|
||||
guard instanceof PrefixStringSanitizer or
|
||||
guard instanceof QuoteGuard or
|
||||
guard instanceof ContainsHtmlGuard
|
||||
}
|
||||
|
||||
override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
@@ -45,8 +46,55 @@ class Configuration extends TaintTracking::Configuration {
|
||||
super.hasFlowPath(src, sink) and
|
||||
// filtering away readings of `src` that end in a URL sink.
|
||||
not (
|
||||
sink.getNode() instanceof DomBasedXss::WriteURLSink and
|
||||
sink.getNode() instanceof DomBasedXss::WriteUrlSink and
|
||||
src.getNode().(DomPropertySource).getPropertyName() = "src"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A test of form `typeof x === "something"`, preventing `x` from being a string in some cases.
|
||||
*
|
||||
* This sanitizer helps prune infeasible paths in type-overloaded functions.
|
||||
*/
|
||||
class TypeTestGuard extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode {
|
||||
override EqualityTest astNode;
|
||||
Expr operand;
|
||||
boolean polarity;
|
||||
|
||||
TypeTestGuard() {
|
||||
exists(TypeofTag tag | TaintTracking::isTypeofGuard(astNode, operand, tag) |
|
||||
// typeof x === "string" sanitizes `x` when it evaluates to false
|
||||
tag = "string" and
|
||||
polarity = astNode.getPolarity().booleanNot()
|
||||
or
|
||||
// typeof x === "object" sanitizes `x` when it evaluates to true
|
||||
tag != "string" and
|
||||
polarity = astNode.getPolarity()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate sanitizes(boolean outcome, Expr e) {
|
||||
polarity = outcome and
|
||||
e = operand
|
||||
}
|
||||
}
|
||||
|
||||
private import semmle.javascript.security.dataflow.Xss::Shared as Shared
|
||||
|
||||
private class PrefixStringSanitizer extends TaintTracking::SanitizerGuardNode,
|
||||
DomBasedXss::PrefixStringSanitizer {
|
||||
PrefixStringSanitizer() { this = this }
|
||||
}
|
||||
|
||||
private class PrefixString extends DataFlow::FlowLabel, DomBasedXss::PrefixString {
|
||||
PrefixString() { this = this }
|
||||
}
|
||||
|
||||
private class QuoteGuard extends TaintTracking::SanitizerGuardNode, Shared::QuoteGuard {
|
||||
QuoteGuard() { this = this }
|
||||
}
|
||||
|
||||
private class ContainsHtmlGuard extends TaintTracking::SanitizerGuardNode, Shared::ContainsHtmlGuard {
|
||||
ContainsHtmlGuard() { this = this }
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import javascript
|
||||
private import semmle.javascript.security.dataflow.Xss
|
||||
private import semmle.javascript.security.dataflow.DomBasedXssCustomizations
|
||||
|
||||
query Angular2::PipeRefExpr pipeRef() { any() }
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.Xss
|
||||
import semmle.javascript.security.dataflow.DomBasedXssCustomizations
|
||||
import semmle.javascript.security.dataflow.CodeInjectionCustomizations
|
||||
|
||||
query Templating::TemplateSyntax getTemplateInstantiationSyntax(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import javascript
|
||||
import semmle.javascript.security.dataflow.Xss
|
||||
import semmle.javascript.security.dataflow.DomBasedXssCustomizations
|
||||
|
||||
query predicate component_getAPropertyValue(Vue::Component c, string name, DataFlow::Node prop) {
|
||||
c.getAPropertyValue(name) = prop
|
||||
|
||||
@@ -97,7 +97,11 @@ predicate alert(Class ab, string msg, Class sub, Class sub2) {
|
||||
)
|
||||
) and
|
||||
// exclude results in experimental
|
||||
not experimentalFile(sub.getLocation().getFile())
|
||||
not experimentalFile(sub.getLocation().getFile()) and
|
||||
// exclude trivially empty classes
|
||||
not sub.getCharPred().getBody() instanceof NoneCall and
|
||||
// exclude test/example queries
|
||||
not sub.getLocation().getFile().getRelativePath().matches("%/" + ["examples", "test"] + "/%.ql")
|
||||
}
|
||||
|
||||
from Class ab, string msg, Class sub, Class sub2
|
||||
|
||||
Reference in New Issue
Block a user