Merge pull request #8783 from erik-krogh/jsAbstractBi

JS: don't initialize sanitizer-guards in the standard library
This commit is contained in:
Erik Krogh Kristensen
2022-04-29 11:12:16 +02:00
committed by GitHub
35 changed files with 826 additions and 672 deletions

View File

@@ -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 (

View File

@@ -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)
}
}

View File

@@ -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 }
}

View File

@@ -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) {

View File

@@ -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)
}
}
}

View File

@@ -1 +1,2 @@
**/*.testproj
**/*.testproj
**/*.actual

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View 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.

View File

@@ -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

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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

View File

@@ -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

View File

@@ -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()
}
}
}

View File

@@ -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 }
}

View File

@@ -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" }
}
}

View File

@@ -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

View File

@@ -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 {

View File

@@ -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 }
}

View File

@@ -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`.
*/

View File

@@ -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
}
}

View File

@@ -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 { }
}

View File

@@ -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 }
}

View File

@@ -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 }
}

View File

@@ -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

View File

@@ -4,7 +4,7 @@
*/
import javascript
import semmle.javascript.security.dataflow.Xss
import semmle.javascript.security.dataflow.DomBasedXssCustomizations
import UnsafeJQueryPluginCustomizations::UnsafeJQueryPlugin
/**

View File

@@ -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
}

View File

@@ -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") }

View File

@@ -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 }
}

View File

@@ -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() }

View File

@@ -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(

View File

@@ -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

View File

@@ -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