This commit is contained in:
aegilops
2025-01-23 17:00:56 +00:00
1407 changed files with 112486 additions and 49200 deletions

View File

@@ -44,12 +44,25 @@ class IndexOfCall extends DataFlow::MethodCallNode {
* Gets an `indexOf` call with the same receiver, argument, and method name, including this call itself.
*/
IndexOfCall getAnEquivalentIndexOfCall() {
result = this
or
exists(DataFlow::Node recv, string m |
this.receiverAndMethodName(recv, m) and result.receiverAndMethodName(recv, m)
|
// both directly reference the same value
result.getArgument(0).getALocalSource() = this.getArgument(0).getALocalSource()
or
// both use the same string literal
result.getArgument(0).getStringValue() = this.getArgument(0).getStringValue()
or
// both use the same concatenation of a string and a value
exists(Expr origin, StringLiteral str, AddExpr otherAdd |
this.getArgument(0).asExpr().(AddExpr).hasOperands(origin, str) and
otherAdd = result.getArgument(0).asExpr()
|
otherAdd.getAnOperand().(StringLiteral).getStringValue() = str.getStringValue() and
otherAdd.getAnOperand().flow().getALocalSource() = origin.flow().getALocalSource()
)
)
}

View File

@@ -11,10 +11,12 @@
import javascript
import semmle.javascript.security.dataflow.ExternalAPIUsedWithUntrustedDataQuery
import DataFlow::PathGraph
import ExternalAPIUsedWithUntrustedDataFlow::PathGraph
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
from
ExternalAPIUsedWithUntrustedDataFlow::PathNode source,
ExternalAPIUsedWithUntrustedDataFlow::PathNode sink
where ExternalAPIUsedWithUntrustedDataFlow::flowPath(source, sink)
select sink, source, sink,
"Call to " + sink.getNode().(Sink).getApiName() + " with untrusted data from $@.", source,
source.toString()

View File

@@ -17,9 +17,9 @@
import javascript
import semmle.javascript.security.dataflow.TaintedPathQuery
import DataFlow::PathGraph
import DataFlow::DeduplicatePathGraph<TaintedPathFlow::PathNode, TaintedPathFlow::PathGraph>
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from PathNode source, PathNode sink
where TaintedPathFlow::flowPath(source.getAnOriginalPathNode(), sink.getAnOriginalPathNode())
select sink.getNode(), source, sink, "This path depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -14,10 +14,10 @@
import javascript
import semmle.javascript.security.dataflow.ZipSlipQuery
import DataFlow::PathGraph
import DataFlow::DeduplicatePathGraph<ZipSlipFlow::PathNode, ZipSlipFlow::PathGraph>
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from PathNode source, PathNode sink
where ZipSlipFlow::flowPath(source.getAnOriginalPathNode(), sink.getAnOriginalPathNode())
select source.getNode(), source, sink,
"Unsanitized archive entry, which may contain '..', is used in a $@.", sink.getNode(),
"file system operation"

View File

@@ -12,10 +12,11 @@
*/
import javascript
import DataFlow::PathGraph
import semmle.javascript.security.dataflow.TemplateObjectInjectionQuery
import DataFlow::DeduplicatePathGraph<TemplateObjectInjectionFlow::PathNode, TemplateObjectInjectionFlow::PathGraph>
from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from PathNode source, PathNode sink
where
TemplateObjectInjectionFlow::flowPath(source.getAnOriginalPathNode(), sink.getAnOriginalPathNode())
select sink.getNode(), source, sink, "Template object depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -15,16 +15,16 @@
import javascript
import semmle.javascript.security.dataflow.CommandInjectionQuery
import DataFlow::PathGraph
import CommandInjectionFlow::PathGraph
from
Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node highlight,
Source sourceNode
CommandInjectionFlow::PathNode source, CommandInjectionFlow::PathNode sink,
DataFlow::Node highlight, Source sourceNode
where
cfg.hasFlowPath(source, sink) and
CommandInjectionFlow::flowPath(source, sink) and
(
if cfg.isSinkWithHighlight(sink.getNode(), _)
then cfg.isSinkWithHighlight(sink.getNode(), highlight)
if isSinkWithHighlight(sink.getNode(), _)
then isSinkWithHighlight(sink.getNode(), highlight)
else highlight = sink.getNode()
) and
sourceNode = source.getNode()

View File

@@ -15,14 +15,16 @@
*/
import javascript
import DataFlow::PathGraph
import semmle.javascript.security.dataflow.IndirectCommandInjectionQuery
import IndirectCommandInjectionFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node highlight
from
IndirectCommandInjectionFlow::PathNode source, IndirectCommandInjectionFlow::PathNode sink,
DataFlow::Node highlight
where
cfg.hasFlowPath(source, sink) and
if cfg.isSinkWithHighlight(sink.getNode(), _)
then cfg.isSinkWithHighlight(sink.getNode(), highlight)
IndirectCommandInjectionFlow::flowPath(source, sink) and
if IndirectCommandInjectionConfig::isSinkWithHighlight(sink.getNode(), _)
then IndirectCommandInjectionConfig::isSinkWithHighlight(sink.getNode(), highlight)
else highlight = sink.getNode()
select highlight, source, sink, "This command depends on an unsanitized $@.", source.getNode(),
source.getNode().(Source).describe()

View File

@@ -14,11 +14,14 @@
*/
import javascript
import DataFlow::PathGraph
import semmle.javascript.security.dataflow.SecondOrderCommandInjectionQuery
import DataFlow::DeduplicatePathGraph<SecondOrderCommandInjectionFlow::PathNode, SecondOrderCommandInjectionFlow::PathGraph>
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode
where cfg.hasFlowPath(source, sink) and sinkNode = sink.getNode()
from PathNode source, PathNode sink, Sink sinkNode
where
SecondOrderCommandInjectionFlow::flowPath(source.getAnOriginalPathNode(),
sink.getAnOriginalPathNode()) and
sinkNode = sink.getNode()
select sink.getNode(), source, sink,
"Command line argument that depends on $@ can execute an arbitrary command if " +
sinkNode.getVulnerableArgumentExample() + " is used with " + sinkNode.getCommand() + ".",

View File

@@ -14,17 +14,18 @@
*/
import javascript
import DataFlow::PathGraph
import semmle.javascript.security.dataflow.ShellCommandInjectionFromEnvironmentQuery
import ShellCommandInjectionFromEnvironmentFlow::PathGraph
from
Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node highlight,
ShellCommandInjectionFromEnvironmentFlow::PathNode source,
ShellCommandInjectionFromEnvironmentFlow::PathNode sink, DataFlow::Node highlight,
Source sourceNode
where
sourceNode = source.getNode() and
cfg.hasFlowPath(source, sink) and
if cfg.isSinkWithHighlight(sink.getNode(), _)
then cfg.isSinkWithHighlight(sink.getNode(), highlight)
ShellCommandInjectionFromEnvironmentFlow::flowPath(source, sink) and
if ShellCommandInjectionFromEnvironmentConfig::isSinkWithHighlight(sink.getNode(), _)
then ShellCommandInjectionFromEnvironmentConfig::isSinkWithHighlight(sink.getNode(), highlight)
else highlight = sink.getNode()
select highlight, source, sink, "This shell command depends on an uncontrolled $@.", sourceNode,
sourceNode.getSourceType()

View File

@@ -15,10 +15,12 @@
import javascript
import semmle.javascript.security.dataflow.UnsafeShellCommandConstructionQuery
import DataFlow::PathGraph
import UnsafeShellCommandConstructionFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode
where cfg.hasFlowPath(source, sink) and sinkNode = sink.getNode()
from
UnsafeShellCommandConstructionFlow::PathNode source,
UnsafeShellCommandConstructionFlow::PathNode sink, Sink sinkNode
where UnsafeShellCommandConstructionFlow::flowPath(source, sink) and sinkNode = sink.getNode()
select sinkNode.getAlertLocation(), source, sink,
"This " + sinkNode.getSinkType() + " which depends on $@ is later used in a $@.",
source.getNode(), "library input", sinkNode.getCommandExecution(), "shell command"

View File

@@ -0,0 +1,8 @@
nodes
| examples/ExceptionXssAjv.js:11:18:11:33 | ajv.errorsText() |
| examples/ExceptionXssAjv.js:11:18:11:33 | ajv.errorsText() |
| examples/ExceptionXssAjv.js:11:18:11:33 | ajv.errorsText() |
edges
| examples/ExceptionXssAjv.js:11:18:11:33 | ajv.errorsText() | examples/ExceptionXssAjv.js:11:18:11:33 | ajv.errorsText() |
#select
| examples/ExceptionXssAjv.js:11:18:11:33 | ajv.errorsText() | examples/ExceptionXssAjv.js:11:18:11:33 | ajv.errorsText() | examples/ExceptionXssAjv.js:11:18:11:33 | ajv.errorsText() | $@ is reinterpreted as HTML without escaping meta-characters. | examples/ExceptionXssAjv.js:11:18:11:33 | ajv.errorsText() | JSON schema validation error |

View File

@@ -14,10 +14,10 @@
import javascript
import semmle.javascript.security.dataflow.ExceptionXssQuery
import DataFlow::PathGraph
import DataFlow::DeduplicatePathGraph<ExceptionXssFlow::PathNode, ExceptionXssFlow::PathGraph>
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from PathNode source, PathNode sink
where ExceptionXssFlow::flowPath(source.getAnOriginalPathNode(), sink.getAnOriginalPathNode())
select sink.getNode(), source, sink,
"$@ is reinterpreted as HTML without escaping meta-characters.", source.getNode(),
source.getNode().(Source).getDescription()

View File

@@ -0,0 +1,12 @@
nodes
| examples/ReflectedXss.js:6:14:6:45 | "Unknow ... rams.id |
| examples/ReflectedXss.js:6:14:6:45 | "Unknow ... rams.id |
| examples/ReflectedXss.js:6:33:6:45 | req.params.id |
| examples/ReflectedXss.js:6:33:6:45 | req.params.id |
edges
| examples/ReflectedXss.js:6:33:6:45 | req.params.id | examples/ReflectedXss.js:6:14:6:45 | "Unknow ... rams.id |
| examples/ReflectedXss.js:6:33:6:45 | req.params.id | examples/ReflectedXss.js:6:14:6:45 | "Unknow ... rams.id |
| examples/ReflectedXss.js:6:33:6:45 | req.params.id | examples/ReflectedXss.js:6:14:6:45 | "Unknow ... rams.id |
| examples/ReflectedXss.js:6:33:6:45 | req.params.id | examples/ReflectedXss.js:6:14:6:45 | "Unknow ... rams.id |
#select
| examples/ReflectedXss.js:6:14:6:45 | "Unknow ... rams.id | examples/ReflectedXss.js:6:33:6:45 | req.params.id | examples/ReflectedXss.js:6:14:6:45 | "Unknow ... rams.id | Cross-site scripting vulnerability due to a $@. | examples/ReflectedXss.js:6:33:6:45 | req.params.id | user-provided value |

View File

@@ -14,9 +14,9 @@
import javascript
import semmle.javascript.security.dataflow.ReflectedXssQuery
import DataFlow::PathGraph
import ReflectedXssFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from ReflectedXssFlow::PathNode source, ReflectedXssFlow::PathNode sink
where ReflectedXssFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to a $@.",
source.getNode(), "user-provided value"

View File

@@ -0,0 +1,30 @@
nodes
| examples/StoredXss.js:5:44:5:52 | fileNames |
| examples/StoredXss.js:5:44:5:52 | fileNames |
| examples/StoredXss.js:7:9:7:17 | fileNames |
| examples/StoredXss.js:7:27:7:34 | fileName |
| examples/StoredXss.js:9:13:9:16 | list |
| examples/StoredXss.js:9:13:9:47 | list |
| examples/StoredXss.js:9:21:9:47 | '<li>' ... '</li>' |
| examples/StoredXss.js:9:30:9:37 | fileName |
| examples/StoredXss.js:11:9:11:12 | list |
| examples/StoredXss.js:11:9:11:23 | list |
| examples/StoredXss.js:12:18:12:21 | list |
| examples/StoredXss.js:12:18:12:21 | list |
edges
| examples/StoredXss.js:5:44:5:52 | fileNames | examples/StoredXss.js:7:9:7:17 | fileNames |
| examples/StoredXss.js:5:44:5:52 | fileNames | examples/StoredXss.js:7:9:7:17 | fileNames |
| examples/StoredXss.js:7:9:7:17 | fileNames | examples/StoredXss.js:7:27:7:34 | fileName |
| examples/StoredXss.js:7:27:7:34 | fileName | examples/StoredXss.js:9:30:9:37 | fileName |
| examples/StoredXss.js:9:13:9:16 | list | examples/StoredXss.js:9:13:9:47 | list |
| examples/StoredXss.js:9:13:9:47 | list | examples/StoredXss.js:9:13:9:16 | list |
| examples/StoredXss.js:9:13:9:47 | list | examples/StoredXss.js:11:9:11:12 | list |
| examples/StoredXss.js:9:21:9:47 | '<li>' ... '</li>' | examples/StoredXss.js:9:13:9:47 | list |
| examples/StoredXss.js:9:30:9:37 | fileName | examples/StoredXss.js:9:21:9:47 | '<li>' ... '</li>' |
| examples/StoredXss.js:11:9:11:12 | list | examples/StoredXss.js:11:9:11:23 | list |
| examples/StoredXss.js:11:9:11:23 | list | examples/StoredXss.js:9:13:9:16 | list |
| examples/StoredXss.js:11:9:11:23 | list | examples/StoredXss.js:11:9:11:12 | list |
| examples/StoredXss.js:11:9:11:23 | list | examples/StoredXss.js:12:18:12:21 | list |
| examples/StoredXss.js:11:9:11:23 | list | examples/StoredXss.js:12:18:12:21 | list |
#select
| examples/StoredXss.js:12:18:12:21 | list | examples/StoredXss.js:5:44:5:52 | fileNames | examples/StoredXss.js:12:18:12:21 | list | Stored cross-site scripting vulnerability due to $@. | examples/StoredXss.js:5:44:5:52 | fileNames | stored value |

View File

@@ -14,9 +14,9 @@
import javascript
import semmle.javascript.security.dataflow.StoredXssQuery
import DataFlow::PathGraph
import StoredXssFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from StoredXssFlow::PathNode source, StoredXssFlow::PathNode sink
where StoredXssFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Stored cross-site scripting vulnerability due to $@.",
source.getNode(), "stored value"

View File

@@ -0,0 +1,3 @@
nodes
edges
#select

View File

@@ -13,11 +13,13 @@
*/
import javascript
import DataFlow::PathGraph
import semmle.javascript.security.dataflow.UnsafeHtmlConstructionQuery
import DataFlow::DeduplicatePathGraph<UnsafeHtmlConstructionFlow::PathNode, UnsafeHtmlConstructionFlow::PathGraph>
from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode
where cfg.hasFlowPath(source, sink) and sink.getNode() = sinkNode
from PathNode source, PathNode sink, Sink sinkNode
where
UnsafeHtmlConstructionFlow::flowPath(source.getAnOriginalPathNode(), sink.getAnOriginalPathNode()) and
sink.getNode() = sinkNode
select sinkNode, source, sink,
"This " + sinkNode.describe() + " which depends on $@ might later allow $@.", source.getNode(),
"library input", sinkNode.getSink(), sinkNode.getVulnerabilityKind().toLowerCase()

View File

@@ -0,0 +1,13 @@
nodes
| examples/UnsafeJQueryPlugin.js:1:31:1:37 | options |
| examples/UnsafeJQueryPlugin.js:1:31:1:37 | options |
| examples/UnsafeJQueryPlugin.js:3:22:3:28 | options |
| examples/UnsafeJQueryPlugin.js:3:22:3:43 | options ... elector |
| examples/UnsafeJQueryPlugin.js:3:22:3:43 | options ... elector |
edges
| examples/UnsafeJQueryPlugin.js:1:31:1:37 | options | examples/UnsafeJQueryPlugin.js:3:22:3:28 | options |
| examples/UnsafeJQueryPlugin.js:1:31:1:37 | options | examples/UnsafeJQueryPlugin.js:3:22:3:28 | options |
| examples/UnsafeJQueryPlugin.js:3:22:3:28 | options | examples/UnsafeJQueryPlugin.js:3:22:3:43 | options ... elector |
| examples/UnsafeJQueryPlugin.js:3:22:3:28 | options | examples/UnsafeJQueryPlugin.js:3:22:3:43 | options ... elector |
#select
| examples/UnsafeJQueryPlugin.js:3:22:3:43 | options ... elector | examples/UnsafeJQueryPlugin.js:1:31:1:37 | options | examples/UnsafeJQueryPlugin.js:3:22:3:43 | options ... elector | Potential XSS vulnerability in the $@. | examples/UnsafeJQueryPlugin.js:1:22:6:1 | functio ... ext);\\n} | '$.fn.copyText' plugin |

View File

@@ -14,13 +14,13 @@
import javascript
import semmle.javascript.security.dataflow.UnsafeJQueryPluginQuery
import DataFlow::PathGraph
import UnsafeJQueryPluginFlow::PathGraph
from
Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink,
UnsafeJQueryPluginFlow::PathNode source, UnsafeJQueryPluginFlow::PathNode sink,
JQuery::JQueryPluginMethod plugin
where
cfg.hasFlowPath(source, sink) and
UnsafeJQueryPluginFlow::flowPath(source, sink) and
source.getNode().(Source).getPlugin() = plugin
select sink.getNode(), source, sink, "Potential XSS vulnerability in the $@.", plugin,
"'$.fn." + plugin.getPluginName() + "' plugin"

View File

@@ -0,0 +1,3 @@
nodes
edges
#select

View File

@@ -14,10 +14,10 @@
import javascript
import semmle.javascript.security.dataflow.DomBasedXssQuery
import DataFlow::PathGraph
import DataFlow::DeduplicatePathGraph<DomBasedXssFlow::PathNode, DomBasedXssFlow::PathGraph>
from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from PathNode source, PathNode sink
where DomBasedXssFlow::flowPath(source.getAnOriginalPathNode(), sink.getAnOriginalPathNode())
select sink.getNode(), source, sink,
sink.getNode().(Sink).getVulnerabilityKind() + " vulnerability due to $@.", source.getNode(),
"user-provided value"

View File

@@ -0,0 +1,13 @@
nodes
| examples/XssThroughDom.js:2:9:2:44 | target |
| examples/XssThroughDom.js:2:18:2:44 | $(this) ... arget") |
| examples/XssThroughDom.js:2:18:2:44 | $(this) ... arget") |
| examples/XssThroughDom.js:3:7:3:12 | target |
| examples/XssThroughDom.js:3:7:3:12 | target |
edges
| examples/XssThroughDom.js:2:9:2:44 | target | examples/XssThroughDom.js:3:7:3:12 | target |
| examples/XssThroughDom.js:2:9:2:44 | target | examples/XssThroughDom.js:3:7:3:12 | target |
| examples/XssThroughDom.js:2:18:2:44 | $(this) ... arget") | examples/XssThroughDom.js:2:9:2:44 | target |
| examples/XssThroughDom.js:2:18:2:44 | $(this) ... arget") | examples/XssThroughDom.js:2:9:2:44 | target |
#select
| examples/XssThroughDom.js:3:7:3:12 | target | examples/XssThroughDom.js:2:18:2:44 | $(this) ... arget") | examples/XssThroughDom.js:3:7:3:12 | target | $@ is reinterpreted as HTML without escaping meta-characters. | examples/XssThroughDom.js:2:18:2:44 | $(this) ... arget") | DOM text |

View File

@@ -14,9 +14,11 @@
import javascript
import semmle.javascript.security.dataflow.XssThroughDomQuery
import DataFlow::PathGraph
import XssThroughDomFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from XssThroughDomFlow::PathNode source, XssThroughDomFlow::PathNode sink
where
XssThroughDomFlow::flowPath(source, sink) and
not isIgnoredSourceSinkPair(source.getNode(), sink.getNode())
select sink.getNode(), source, sink,
"$@ is reinterpreted as HTML without escaping meta-characters.", source.getNode(), "DOM text"

View File

@@ -14,17 +14,23 @@
*/
import javascript
import semmle.javascript.security.dataflow.SqlInjectionQuery as SqlInjection
import semmle.javascript.security.dataflow.NosqlInjectionQuery as NosqlInjection
import DataFlow::PathGraph
import semmle.javascript.security.dataflow.SqlInjectionQuery as Sql
import semmle.javascript.security.dataflow.NosqlInjectionQuery as Nosql
from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, string type
module Merged =
DataFlow::MergePathGraph<Sql::SqlInjectionFlow::PathNode, Nosql::NosqlInjectionFlow::PathNode,
Sql::SqlInjectionFlow::PathGraph, Nosql::NosqlInjectionFlow::PathGraph>;
import DataFlow::DeduplicatePathGraph<Merged::PathNode, Merged::PathGraph>
from PathNode source, PathNode sink, string type
where
(
cfg instanceof SqlInjection::Configuration and type = "string"
or
cfg instanceof NosqlInjection::Configuration and type = "object"
) and
cfg.hasFlowPath(source, sink)
Sql::SqlInjectionFlow::flowPath(source.getAnOriginalPathNode().asPathNode1(),
sink.getAnOriginalPathNode().asPathNode1()) and
type = "string"
or
Nosql::NosqlInjectionFlow::flowPath(source.getAnOriginalPathNode().asPathNode2(),
sink.getAnOriginalPathNode().asPathNode2()) and
type = "object"
select sink.getNode(), source, sink, "This query " + type + " depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -16,9 +16,9 @@
import javascript
import semmle.javascript.security.dataflow.CodeInjectionQuery
import DataFlow::PathGraph
import CodeInjectionFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from CodeInjectionFlow::PathNode source, CodeInjectionFlow::PathNode sink
where CodeInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, sink.getNode().(Sink).getMessagePrefix() + " depends on a $@.",
source.getNode(), "user-provided value"

View File

@@ -14,9 +14,9 @@
import javascript
import semmle.javascript.security.dataflow.ImproperCodeSanitizationQuery
import DataFlow::PathGraph
private import semmle.javascript.heuristics.HeuristicSinks
private import semmle.javascript.security.dataflow.CodeInjectionCustomizations
import ImproperCodeSanitizationFlow::PathGraph
/**
* Gets a type-tracked instance of `RemoteFlowSource` using type-tracker `t`.
@@ -60,9 +60,9 @@ private DataFlow::Node endsInCodeInjectionSink() {
result = endsInCodeInjectionSink(DataFlow::TypeBackTracker::end())
}
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
from ImproperCodeSanitizationFlow::PathNode source, ImproperCodeSanitizationFlow::PathNode sink
where
cfg.hasFlowPath(source, sink) and
ImproperCodeSanitizationFlow::flowPath(source, sink) and
// Basic detection of duplicate results with `js/code-injection`.
not (
sink.getNode().(StringOps::ConcatenationLeaf).getRoot() = endsInCodeInjectionSink() and

View File

@@ -14,11 +14,13 @@
*/
import javascript
import DataFlow::PathGraph
import semmle.javascript.security.dataflow.UnsafeCodeConstruction::UnsafeCodeConstruction
import UnsafeCodeConstructionFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode
where cfg.hasFlowPath(source, sink) and sinkNode = sink.getNode()
from
UnsafeCodeConstructionFlow::PathNode source, UnsafeCodeConstructionFlow::PathNode sink,
Sink sinkNode
where UnsafeCodeConstructionFlow::flowPath(source, sink) and sinkNode = sink.getNode()
select sink.getNode(), source, sink,
"This " + sinkNode.getSinkType() + " which depends on $@ is later $@.", source.getNode(),
"library input", sinkNode.getCodeSink(), "interpreted as code"

View File

@@ -12,10 +12,10 @@
import javascript
import semmle.javascript.security.dataflow.UnsafeDynamicMethodAccessQuery
import DataFlow::PathGraph
import UnsafeDynamicMethodAccessFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from UnsafeDynamicMethodAccessFlow::PathNode source, UnsafeDynamicMethodAccessFlow::PathNode sink
where UnsafeDynamicMethodAccessFlow::flowPath(source, sink)
select sink, source, sink,
"This method is invoked using a $@, which may allow remote code execution.", source.getNode(),
"user-controlled value"

View File

@@ -15,9 +15,9 @@
*/
import javascript
import DataFlow::PathGraph
import semmle.javascript.security.dataflow.IncompleteHtmlAttributeSanitizationQuery
import semmle.javascript.security.IncompleteBlacklistSanitizer
import DataFlow::DeduplicatePathGraph<IncompleteHtmlAttributeSanitizationFlow::PathNode, IncompleteHtmlAttributeSanitizationFlow::PathGraph>
/**
* Gets a pretty string of the dangerous characters for `sink`.
@@ -31,8 +31,10 @@ string prettyPrintDangerousCharaters(Sink sink) {
).regexpReplaceAll(",(?=[^,]+$)", " or")
}
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from PathNode source, PathNode sink
where
IncompleteHtmlAttributeSanitizationFlow::flowPath(source.getAnOriginalPathNode(),
sink.getAnOriginalPathNode())
select sink.getNode(), source, sink,
// this message is slightly sub-optimal as we do not have an easy way
// to get the flow labels that reach the sink, so the message includes

View File

@@ -12,10 +12,10 @@
*/
import javascript
import DataFlow::PathGraph
import semmle.javascript.security.dataflow.LogInjectionQuery
import LogInjectionFlow::PathGraph
from LogInjectionConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
from LogInjectionFlow::PathNode source, LogInjectionFlow::PathNode sink
where LogInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Log entry depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -12,9 +12,9 @@
import javascript
import semmle.javascript.security.dataflow.TaintedFormatStringQuery
import DataFlow::PathGraph
import TaintedFormatStringFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from TaintedFormatStringFlow::PathNode source, TaintedFormatStringFlow::PathNode sink
where TaintedFormatStringFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Format string depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -12,9 +12,9 @@
import javascript
import semmle.javascript.security.dataflow.FileAccessToHttpQuery
import DataFlow::PathGraph
import FileAccessToHttpFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from FileAccessToHttpFlow::PathNode source, FileAccessToHttpFlow::PathNode sink
where FileAccessToHttpFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Outbound network request depends on $@.", source.getNode(),
"file data"

View File

@@ -15,9 +15,9 @@
import javascript
import semmle.javascript.security.dataflow.PostMessageStarQuery
import DataFlow::PathGraph
import PostMessageStarFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from PostMessageStarFlow::PathNode source, PostMessageStarFlow::PathNode sink
where PostMessageStarFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "$@ is sent to another window without origin restriction.",
source.getNode(), "Sensitive data"

View File

@@ -15,9 +15,9 @@
import javascript
import semmle.javascript.security.dataflow.StackTraceExposureQuery
import DataFlow::PathGraph
import StackTraceExposureFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from StackTraceExposureFlow::PathNode source, StackTraceExposureFlow::PathNode sink
where StackTraceExposureFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This information exposed to the user depends on $@.",
source.getNode(), "stack trace information"

View File

@@ -15,10 +15,10 @@
import javascript
import semmle.javascript.security.dataflow.BuildArtifactLeakQuery
import DataFlow::PathGraph
import BuildArtifactLeakFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from BuildArtifactLeakFlow::PathNode source, BuildArtifactLeakFlow::PathNode sink
where BuildArtifactLeakFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This creates a build artifact that depends on $@.",
source.getNode(),
"sensitive data returned by" + source.getNode().(CleartextLogging::Source).describe()

View File

@@ -15,7 +15,7 @@
import javascript
import semmle.javascript.security.dataflow.CleartextLoggingQuery
import DataFlow::PathGraph
import CleartextLoggingFlow::PathGraph
/**
* Holds if `tl` is used in a browser environment.
@@ -33,9 +33,9 @@ predicate inBrowserEnvironment(TopLevel tl) {
)
}
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
from CleartextLoggingFlow::PathNode source, CleartextLoggingFlow::PathNode sink
where
cfg.hasFlowPath(source, sink) and
CleartextLoggingFlow::flowPath(source, sink) and
// ignore logging to the browser console (even though it is not a good practice)
not inBrowserEnvironment(sink.getNode().asExpr().getTopLevel())
select sink.getNode(), source, sink, "This logs sensitive data returned by $@ as clear text.",

View File

@@ -15,9 +15,9 @@
import javascript
import semmle.javascript.security.dataflow.CleartextStorageQuery
import DataFlow::PathGraph
import ClearTextStorageFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from ClearTextStorageFlow::PathNode source, ClearTextStorageFlow::PathNode sink
where ClearTextStorageFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This stores sensitive data returned by $@ as clear text.",
source.getNode(), source.getNode().(Source).describe()

View File

@@ -14,13 +14,13 @@
import javascript
import semmle.javascript.security.dataflow.BrokenCryptoAlgorithmQuery
import semmle.javascript.security.SensitiveActions
import DataFlow::PathGraph
import BrokenCryptoAlgorithmFlow::PathGraph
from
Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Source sourceNode,
Sink sinkNode
BrokenCryptoAlgorithmFlow::PathNode source, BrokenCryptoAlgorithmFlow::PathNode sink,
Source sourceNode, Sink sinkNode
where
cfg.hasFlowPath(source, sink) and
BrokenCryptoAlgorithmFlow::flowPath(source, sink) and
sourceNode = source.getNode() and
sinkNode = sink.getNode() and
not sourceNode instanceof CleartextPasswordExpr // flagged by js/insufficient-password-hash

View File

@@ -14,10 +14,10 @@
import javascript
import semmle.javascript.security.dataflow.InsecureRandomnessQuery
import DataFlow::PathGraph
import InsecureRandomnessFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from InsecureRandomnessFlow::PathNode source, InsecureRandomnessFlow::PathNode sink
where InsecureRandomnessFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"This uses a cryptographically insecure random number generated at $@ in a security context.",
source.getNode(), source.getNode().toString()

View File

@@ -14,10 +14,10 @@
import javascript
import semmle.javascript.security.dataflow.CorsMisconfigurationForCredentialsQuery
import DataFlow::PathGraph
import CorsMisconfigurationFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from CorsMisconfigurationFlow::PathNode source, CorsMisconfigurationFlow::PathNode sink
where CorsMisconfigurationFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "$@ leak vulnerability due to a $@.",
sink.getNode().(Sink).getCredentialsHeader(), "Credential", source.getNode(),
"misconfigured CORS header value"

View File

@@ -13,10 +13,10 @@
*/
import javascript
import DataFlow::PathGraph
import semmle.javascript.security.dataflow.InsecureTemporaryFileQuery
import InsecureTemporaryFileFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from InsecureTemporaryFileFlow::PathNode source, InsecureTemporaryFileFlow::PathNode sink
where InsecureTemporaryFileFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Insecure creation of file in $@.", source.getNode(),
"the os temp dir"

View File

@@ -11,14 +11,13 @@
*/
import javascript
import DataFlow::PathGraph
import semmle.javascript.security.dataflow.DeepObjectResourceExhaustionQuery
import DataFlow::DeduplicatePathGraph<DeepObjectResourceExhaustionFlow::PathNode, DeepObjectResourceExhaustionFlow::PathGraph>
from
Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node link,
string reason
from PathNode source, PathNode sink, DataFlow::Node link, string reason
where
cfg.hasFlowPath(source, sink) and
DeepObjectResourceExhaustionFlow::flowPath(source.getAnOriginalPathNode(),
sink.getAnOriginalPathNode()) and
sink.getNode().(Sink).hasReason(link, reason)
select sink, source, sink, "Denial of service caused by processing $@ with $@.", source.getNode(),
"user input", link, reason

View File

@@ -14,9 +14,9 @@
import javascript
import semmle.javascript.security.dataflow.RemotePropertyInjectionQuery
import DataFlow::PathGraph
import RemotePropertyInjectionFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from RemotePropertyInjectionFlow::PathNode source, RemotePropertyInjectionFlow::PathNode sink
where RemotePropertyInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, sink.getNode().(Sink).getMessage() + " depends on a $@.",
source.getNode(), "user-provided value"

View File

@@ -13,9 +13,9 @@
import javascript
import semmle.javascript.security.dataflow.UnsafeDeserializationQuery
import DataFlow::PathGraph
import UnsafeDeserializationFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from UnsafeDeserializationFlow::PathNode source, UnsafeDeserializationFlow::PathNode sink
where UnsafeDeserializationFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Unsafe deserialization depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -14,10 +14,12 @@
import javascript
import semmle.javascript.security.dataflow.HardcodedDataInterpretedAsCodeQuery
import DataFlow::PathGraph
import DataFlow::DeduplicatePathGraph<HardcodedDataInterpretedAsCodeFlow::PathNode, HardcodedDataInterpretedAsCodeFlow::PathGraph>
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from PathNode source, PathNode sink
where
HardcodedDataInterpretedAsCodeFlow::flowPath(source.getAnOriginalPathNode(),
sink.getAnOriginalPathNode())
select sink.getNode(), source, sink,
"$@ is interpreted as " + sink.getNode().(Sink).getKind() + ".", source.getNode(),
"Hard-coded data"

View File

@@ -15,9 +15,10 @@
import javascript
import semmle.javascript.security.dataflow.ClientSideUrlRedirectQuery
import DataFlow::PathGraph
import DataFlow::DeduplicatePathGraph<ClientSideUrlRedirectFlow::PathNode, ClientSideUrlRedirectFlow::PathGraph>
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from PathNode source, PathNode sink
where
ClientSideUrlRedirectFlow::flowPath(source.getAnOriginalPathNode(), sink.getAnOriginalPathNode())
select sink.getNode(), source, sink, "Untrusted URL redirection depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -13,9 +13,9 @@
import javascript
import semmle.javascript.security.dataflow.ServerSideUrlRedirectQuery
import DataFlow::PathGraph
import ServerSideUrlRedirectFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from ServerSideUrlRedirectFlow::PathNode source, ServerSideUrlRedirectFlow::PathNode sink
where ServerSideUrlRedirectFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Untrusted URL redirection depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -14,10 +14,10 @@
import javascript
import semmle.javascript.security.dataflow.XxeQuery
import DataFlow::PathGraph
import XxeFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from XxeFlow::PathNode source, XxeFlow::PathNode sink
where XxeFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"XML parsing depends on a $@ without guarding against external entity expansion.",
source.getNode(), "user-provided value"

View File

@@ -13,9 +13,9 @@
import javascript
import semmle.javascript.security.dataflow.HostHeaderPoisoningInEmailGenerationQuery
import DataFlow::PathGraph
import HostHeaderPoisoningFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from HostHeaderPoisoningFlow::PathNode source, HostHeaderPoisoningFlow::PathNode sink
where HostHeaderPoisoningFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Links in this email can be hijacked by poisoning the $@.",
source.getNode(), "HTTP host header"

View File

@@ -13,9 +13,9 @@
import javascript
import semmle.javascript.security.dataflow.XpathInjectionQuery
import DataFlow::PathGraph
import XpathInjectionFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from XpathInjectionFlow::PathNode source, XpathInjectionFlow::PathNode sink
where XpathInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "XPath expression depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -15,9 +15,9 @@
import javascript
import semmle.javascript.security.dataflow.RegExpInjectionQuery
import DataFlow::PathGraph
import RegExpInjectionFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from RegExpInjectionFlow::PathNode source, RegExpInjectionFlow::PathNode sink
where RegExpInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This regular expression is constructed from a $@.",
source.getNode(), source.getNode().(Source).describe()

View File

@@ -13,10 +13,12 @@
import javascript
import semmle.javascript.security.dataflow.UnvalidatedDynamicMethodCallQuery
import DataFlow::PathGraph
import DataFlow::DeduplicatePathGraph<UnvalidatedDynamicMethodCallFlow::PathNode, UnvalidatedDynamicMethodCallFlow::PathGraph>
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from PathNode source, PathNode sink
where
UnvalidatedDynamicMethodCallFlow::flowPath(source.getAnOriginalPathNode(),
sink.getAnOriginalPathNode())
select sink.getNode(), source, sink,
"Invocation of method with $@ name may dispatch to unexpected target and cause an exception.",
source.getNode(), "user-controlled"

View File

@@ -13,10 +13,10 @@
*/
import javascript
import DataFlow::PathGraph
import semmle.javascript.security.dataflow.ResourceExhaustionQuery
import ResourceExhaustionFlow::PathGraph
from Configuration dataflow, DataFlow::PathNode source, DataFlow::PathNode sink
where dataflow.hasFlowPath(source, sink)
from ResourceExhaustionFlow::PathNode source, ResourceExhaustionFlow::PathNode sink
where ResourceExhaustionFlow::flowPath(source, sink)
select sink, source, sink, sink.getNode().(Sink).getProblemDescription() + " from a $@.", source,
"user-provided value"

View File

@@ -14,10 +14,10 @@
import javascript
import semmle.javascript.security.dataflow.XmlBombQuery
import DataFlow::PathGraph
import XmlBombFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from XmlBombFlow::PathNode source, XmlBombFlow::PathNode sink
where XmlBombFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"XML parsing depends on a $@ without guarding against uncontrolled entity expansion.",
source.getNode(), "user-provided value"

View File

@@ -15,14 +15,14 @@
import javascript
import semmle.javascript.security.dataflow.HardcodedCredentialsQuery
import DataFlow::PathGraph
import HardcodedCredentials::PathGraph
bindingset[s]
predicate looksLikeATemplate(string s) { s.regexpMatch(".*((\\{\\{.*\\}\\})|(<.*>)|(\\(.*\\))).*") }
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, string value
from HardcodedCredentials::PathNode source, HardcodedCredentials::PathNode sink, string value
where
cfg.hasFlowPath(source, sink) and
HardcodedCredentials::flowPath(source, sink) and
// use source value in message if it's available
if source.getNode().asExpr() instanceof ConstantString
then

View File

@@ -13,11 +13,13 @@
import javascript
import semmle.javascript.security.dataflow.ConditionalBypassQuery
import DataFlow::PathGraph
import ConditionalBypassFlow::PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, SensitiveAction action
from
ConditionalBypassFlow::PathNode source, ConditionalBypassFlow::PathNode sink,
SensitiveAction action
where
isTaintedGuardForSensitiveAction(sink, source, action) and
not isEarlyAbortGuard(sink, action)
isTaintedGuardNodeForSensitiveAction(sink, source, action) and
not isEarlyAbortGuardNode(sink, action)
select sink.getNode(), source, sink, "This condition guards a sensitive $@, but a $@ controls it.",
action, "action", source.getNode(), "user-provided value"

View File

@@ -13,9 +13,9 @@
import javascript
import semmle.javascript.security.dataflow.InsecureDownloadQuery
import DataFlow::PathGraph
import DataFlow::DeduplicatePathGraph<InsecureDownloadFlow::PathNode, InsecureDownloadFlow::PathGraph>
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from PathNode source, PathNode sink
where InsecureDownloadFlow::flowPath(source.getAnOriginalPathNode(), sink.getAnOriginalPathNode())
select sink.getNode(), source, sink, "$@ of sensitive file from $@.",
sink.getNode().(Sink).getDownloadCall(), "Download", source.getNode(), "HTTP source"

View File

@@ -14,10 +14,10 @@
import javascript
import semmle.javascript.security.dataflow.LoopBoundInjectionQuery
import DataFlow::PathGraph
import LoopBoundInjectionFlow::PathGraph
from Configuration dataflow, DataFlow::PathNode source, DataFlow::PathNode sink
where dataflow.hasFlowPath(source, sink)
from LoopBoundInjectionFlow::PathNode source, LoopBoundInjectionFlow::PathNode sink
where LoopBoundInjectionFlow::flowPath(source, sink)
select sink, source, sink,
"Iteration over a user-controlled object with a potentially unbounded .length property from a $@.",
source, "user-provided value"

View File

@@ -12,10 +12,10 @@
import javascript
import semmle.javascript.security.dataflow.TypeConfusionThroughParameterTamperingQuery
import DataFlow::PathGraph
import TypeConfusionFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from TypeConfusionFlow::PathNode source, TypeConfusionFlow::PathNode sink
where TypeConfusionFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"Potential type confusion as $@ may be either an array or a string.", source.getNode(),
"this HTTP request parameter"

View File

@@ -13,9 +13,9 @@
import javascript
import semmle.javascript.security.dataflow.HttpToFileAccessQuery
import DataFlow::PathGraph
import HttpToFileAccessFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from HttpToFileAccessFlow::PathNode source, HttpToFileAccessFlow::PathNode sink
where HttpToFileAccessFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Write to file system depends on $@.", source.getNode(),
"Untrusted data"

View File

@@ -19,10 +19,13 @@
import javascript
import semmle.javascript.security.dataflow.PrototypePollutingAssignmentQuery
import DataFlow::PathGraph
import PrototypePollutingAssignmentFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from
PrototypePollutingAssignmentFlow::PathNode source, PrototypePollutingAssignmentFlow::PathNode sink
where
PrototypePollutingAssignmentFlow::flowPath(source, sink) and
not isIgnoredLibraryFlow(source.getNode(), sink.getNode())
select sink, source, sink,
"This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@.",
source.getNode(), source.getNode().(Source).describe()

View File

@@ -17,11 +17,10 @@
*/
import javascript
import DataFlow
import PathGraph
import semmle.javascript.DynamicPropertyAccess
private import semmle.javascript.dataflow.InferredTypes
// WIN: gained TP in Lucifier/r.js:2757, though not sure why it wasn't flagged to start with.
/**
* A call of form `x.split(".")` where `x` is a parameter.
*
@@ -30,14 +29,14 @@ private import semmle.javascript.dataflow.InferredTypes
class SplitCall extends StringSplitCall {
SplitCall() {
this.getSeparator() = "." and
this.getBaseString().getALocalSource() instanceof ParameterNode
this.getBaseString().getALocalSource() instanceof DataFlow::ParameterNode
}
}
/**
* Holds if `pred -> succ` should preserve polluted property names.
*/
predicate copyArrayStep(SourceNode pred, SourceNode succ) {
predicate copyArrayStep(DataFlow::SourceNode pred, DataFlow::SourceNode succ) {
// x -> [...x]
exists(SpreadElement spread |
pred.flowsTo(spread.getOperand().flow()) and
@@ -45,7 +44,7 @@ predicate copyArrayStep(SourceNode pred, SourceNode succ) {
)
or
// `x -> y` in `y.push( x[i] )`
exists(MethodCallNode push |
exists(DataFlow::MethodCallNode push |
push = succ.getAMethodCall("push") and
(
getAnEnumeratedArrayElement(pred).flowsTo(push.getAnArgument())
@@ -55,7 +54,7 @@ predicate copyArrayStep(SourceNode pred, SourceNode succ) {
)
or
// x -> x.concat(...)
exists(MethodCallNode concat_ |
exists(DataFlow::MethodCallNode concat_ |
concat_.getMethodName() = "concat" and
(pred = concat_.getReceiver() or pred = concat_.getAnArgument()) and
succ = concat_
@@ -66,21 +65,21 @@ predicate copyArrayStep(SourceNode pred, SourceNode succ) {
* Holds if `node` may refer to a `SplitCall` or a copy thereof, possibly
* returned through a function call.
*/
predicate isSplitArray(SourceNode node) {
predicate isSplitArray(DataFlow::SourceNode node) {
node instanceof SplitCall
or
exists(SourceNode pred | isSplitArray(pred) |
exists(DataFlow::SourceNode pred | isSplitArray(pred) |
copyArrayStep(pred, node)
or
pred.flowsToExpr(node.(CallNode).getACallee().getAReturnedExpr())
pred.flowsToExpr(node.(DataFlow::CallNode).getACallee().getAReturnedExpr())
)
}
/**
* A property name originating from a `x.split(".")` call.
*/
class SplitPropName extends SourceNode {
SourceNode array;
class SplitPropName extends DataFlow::SourceNode {
DataFlow::SourceNode array;
SplitPropName() {
isSplitArray(array) and
@@ -90,7 +89,7 @@ class SplitPropName extends SourceNode {
/**
* Gets the array from which this property name was obtained (the result from `split`).
*/
SourceNode getArray() { result = array }
DataFlow::SourceNode getArray() { result = array }
/** Gets an element accessed on the same underlying array. */
SplitPropName getAnAlias() { result.getArray() = this.getArray() }
@@ -117,18 +116,18 @@ predicate isPollutedPropNameSource(DataFlow::Node node) {
* Holds if `node` may flow from a source of polluted propery names, possibly
* into function calls (but not returns).
*/
predicate isPollutedPropName(Node node) {
predicate isPollutedPropName(DataFlow::Node node) {
isPollutedPropNameSource(node)
or
exists(Node pred | isPollutedPropName(pred) |
exists(DataFlow::Node pred | isPollutedPropName(pred) |
node = pred.getASuccessor()
or
argumentPassingStep(_, pred, _, node)
DataFlow::argumentPassingStep(_, pred, _, node)
or
// Handle one level of callbacks
exists(FunctionNode function, ParameterNode callback, int i |
exists(DataFlow::FunctionNode function, DataFlow::ParameterNode callback, int i |
pred = callback.getAnInvocation().getArgument(i) and
argumentPassingStep(_, function, _, callback) and
DataFlow::argumentPassingStep(_, function, _, callback) and
node = function.getParameter(i)
)
)
@@ -138,8 +137,8 @@ predicate isPollutedPropName(Node node) {
* Holds if `node` may refer to `Object.prototype` obtained through dynamic property
* read of a property obtained through property enumeration.
*/
predicate isPotentiallyObjectPrototype(SourceNode node) {
exists(Node base, Node key |
predicate isPotentiallyObjectPrototype(DataFlow::SourceNode node) {
exists(DataFlow::Node base, DataFlow::Node key |
dynamicPropReadStep(base, key, node) and
isPollutedPropName(key) and
// Ignore cases where the properties of `base` are enumerated, to avoid FPs
@@ -149,8 +148,8 @@ predicate isPotentiallyObjectPrototype(SourceNode node) {
not arePropertiesEnumerated(base.getALocalSource())
)
or
exists(Node use | isPotentiallyObjectPrototype(use.getALocalSource()) |
argumentPassingStep(_, use, _, node)
exists(DataFlow::Node use | isPotentiallyObjectPrototype(use.getALocalSource()) |
DataFlow::argumentPassingStep(_, use, _, node)
)
}
@@ -193,14 +192,6 @@ string unsafePropName() {
result = "constructor"
}
/**
* A flow label representing an unsafe property name, or an object obtained
* by using such a property in a dynamic read.
*/
class UnsafePropLabel extends FlowLabel {
UnsafePropLabel() { this = unsafePropName() }
}
/**
* Tracks data from property enumerations to dynamic property writes.
*
@@ -233,11 +224,13 @@ class UnsafePropLabel extends FlowLabel {
* for coinciding paths afterwards. This means this configuration can't be used as
* a standalone configuration like in most path queries.
*/
class PropNameTracking extends DataFlow::Configuration {
PropNameTracking() { this = "PropNameTracking" }
module PropNameTrackingConfig implements DataFlow::StateConfigSig {
class FlowState extends string {
FlowState() { this = unsafePropName() }
}
override predicate isSource(DataFlow::Node node, FlowLabel label) {
label instanceof UnsafePropLabel and
predicate isSource(DataFlow::Node node, FlowState state) {
exists(state) and
(
isPollutedPropNameSource(node)
or
@@ -245,8 +238,8 @@ class PropNameTracking extends DataFlow::Configuration {
)
}
override predicate isSink(DataFlow::Node node, FlowLabel label) {
label instanceof UnsafePropLabel and
predicate isSink(DataFlow::Node node, FlowState state) {
exists(state) and
(
dynamicPropWrite(node, _, _) or
dynamicPropWrite(_, node, _) or
@@ -254,51 +247,71 @@ class PropNameTracking extends DataFlow::Configuration {
)
}
override predicate isAdditionalFlowStep(
DataFlow::Node pred, DataFlow::Node succ, FlowLabel predlbl, FlowLabel succlbl
predicate isBarrier(DataFlow::Node node, FlowState state) {
node = DataFlow::MakeStateBarrierGuard<FlowState, BarrierGuard>::getABarrierNode(state)
}
predicate isAdditionalFlowStep(
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
) {
predlbl instanceof UnsafePropLabel and
succlbl = predlbl and
exists(state1) and
state2 = state1 and
(
// Step through `p -> x[p]`
exists(PropRead read |
pred = read.getPropertyNameExpr().flow() and
exists(DataFlow::PropRead read |
node1 = read.getPropertyNameExpr().flow() and
not read.(DynamicPropRead).hasDominatingAssignment() and
succ = read
node2 = read
)
or
// Step through `x -> x[p]`
exists(DynamicPropRead read |
not read.hasDominatingAssignment() and
pred = read.getBase() and
succ = read
node1 = read.getBase() and
node2 = read
)
)
}
override predicate isBarrier(DataFlow::Node node) {
super.isBarrier(node)
or
node instanceof DataFlow::VarAccessBarrier
predicate isBarrier(DataFlow::Node node) {
node instanceof DataFlow::VarAccessBarrier or
node = DataFlow::MakeBarrierGuard<BarrierGuard>::getABarrierNode()
}
override predicate isBarrierGuard(DataFlow::BarrierGuardNode node) {
node instanceof DenyListEqualityGuard or
node instanceof AllowListEqualityGuard or
node instanceof HasOwnPropertyGuard or
node instanceof InExprGuard or
node instanceof InstanceOfGuard or
node instanceof TypeofGuard or
node instanceof DenyListInclusionGuard or
node instanceof AllowListInclusionGuard or
node instanceof IsPlainObjectGuard
int accessPathLimit() {
// Speed up the query. For the pattern we're looking for the value rarely
// flows through any contents, apart from a capture content.
result = 1
}
predicate observeDiffInformedIncrementalMode() {
none() // Disabled since the alert references some locations other than the source or sink
}
}
class FlowState = PropNameTrackingConfig::FlowState;
module PropNameTracking = DataFlow::GlobalWithState<PropNameTrackingConfig>;
/**
* A barrier guard for prototype pollution.
*/
abstract class BarrierGuard extends DataFlow::Node {
/**
* Holds if this node acts as a barrier for data flow, blocking further flow from `e` if `this` evaluates to `outcome`.
*/
predicate blocksExpr(boolean outcome, Expr e) { none() }
/**
* Holds if this node acts as a barrier for `state`, blocking further flow from `e` if `this` evaluates to `outcome`.
*/
predicate blocksExpr(boolean outcome, Expr e, FlowState state) { none() }
}
/**
* A sanitizer guard of form `x === "__proto__"` or `x === "constructor"`.
*/
class DenyListEqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNode {
class DenyListEqualityGuard extends BarrierGuard, DataFlow::ValueNode {
override EqualityTest astNode;
string propName;
@@ -307,17 +320,17 @@ class DenyListEqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNode
propName = unsafePropName()
}
override predicate blocks(boolean outcome, Expr e, FlowLabel label) {
override predicate blocksExpr(boolean outcome, Expr e, FlowState state) {
e = astNode.getAnOperand() and
outcome = astNode.getPolarity().booleanNot() and
label = propName
state = propName
}
}
/**
* An equality test with something other than `__proto__` or `constructor`.
*/
class AllowListEqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNode {
class AllowListEqualityGuard extends BarrierGuard, DataFlow::ValueNode {
override EqualityTest astNode;
AllowListEqualityGuard() {
@@ -325,10 +338,9 @@ class AllowListEqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNod
astNode.getAnOperand() instanceof Literal
}
override predicate blocks(boolean outcome, Expr e, FlowLabel label) {
override predicate blocksExpr(boolean outcome, Expr e) {
e = astNode.getAnOperand() and
outcome = astNode.getPolarity() and
label instanceof UnsafePropLabel
outcome = astNode.getPolarity()
}
}
@@ -339,7 +351,7 @@ class AllowListEqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNod
* but the destination object generally doesn't. It is therefore only a sanitizer when
* used on the destination object.
*/
class HasOwnPropertyGuard extends DataFlow::BarrierGuardNode instanceof HasOwnPropertyCall {
class HasOwnPropertyGuard extends BarrierGuard instanceof HasOwnPropertyCall {
HasOwnPropertyGuard() {
// Try to avoid `src.hasOwnProperty` by requiring that the receiver
// does not locally have its properties enumerated. Typically there is no
@@ -347,7 +359,7 @@ class HasOwnPropertyGuard extends DataFlow::BarrierGuardNode instanceof HasOwnPr
not arePropertiesEnumerated(super.getObject().getALocalSource())
}
override predicate blocks(boolean outcome, Expr e) {
override predicate blocksExpr(boolean outcome, Expr e) {
e = super.getProperty().asExpr() and outcome = true
}
}
@@ -358,7 +370,7 @@ class HasOwnPropertyGuard extends DataFlow::BarrierGuardNode instanceof HasOwnPr
* Since `"__proto__" in obj` and `"constructor" in obj` is true for most objects,
* this is seen as a sanitizer for `key` in the false outcome.
*/
class InExprGuard extends DataFlow::BarrierGuardNode, DataFlow::ValueNode {
class InExprGuard extends BarrierGuard, DataFlow::ValueNode {
override InExpr astNode;
InExprGuard() {
@@ -366,7 +378,7 @@ class InExprGuard extends DataFlow::BarrierGuardNode, DataFlow::ValueNode {
not arePropertiesEnumerated(astNode.getRightOperand().flow().getALocalSource())
}
override predicate blocks(boolean outcome, Expr e) {
override predicate blocksExpr(boolean outcome, Expr e) {
e = astNode.getLeftOperand() and outcome = false
}
}
@@ -374,41 +386,41 @@ class InExprGuard extends DataFlow::BarrierGuardNode, DataFlow::ValueNode {
/**
* A sanitizer guard for `instanceof` expressions.
*
* `Object.prototype instanceof X` is never true, so this blocks the `__proto__` label.
* `Object.prototype instanceof X` is never true, so this blocks the `__proto__` state.
*
* It is still possible to get to `Function.prototype` through `constructor.constructor.prototype`
* so we do not block the `constructor` label.
* so we do not block the `constructor` state.
*/
class InstanceOfGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::ValueNode {
class InstanceOfGuard extends BarrierGuard, DataFlow::ValueNode {
override InstanceOfExpr astNode;
override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel label) {
e = astNode.getLeftOperand() and outcome = true and label = "__proto__"
override predicate blocksExpr(boolean outcome, Expr e, FlowState state) {
e = astNode.getLeftOperand() and outcome = true and state = "__proto__"
}
}
/**
* Sanitizer guard of form `typeof x === "object"` or `typeof x === "function"`.
*
* The former blocks the `constructor` label as that payload must pass through a function,
* and the latter blocks the `__proto__` label as that only passes through objects.
* The former blocks the `constructor` state as that payload must pass through a function,
* and the latter blocks the `__proto__` state as that only passes through objects.
*/
class TypeofGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::ValueNode {
class TypeofGuard extends BarrierGuard, DataFlow::ValueNode {
override EqualityTest astNode;
Expr operand;
TypeofTag tag;
TypeofGuard() { TaintTracking::isTypeofGuard(astNode, operand, tag) }
override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel label) {
override predicate blocksExpr(boolean outcome, Expr e, FlowState state) {
e = operand and
outcome = astNode.getPolarity() and
(
tag = "object" and
label = "constructor"
state = "constructor"
or
tag = "function" and
label = "__proto__"
state = "__proto__"
)
or
e = operand and
@@ -417,10 +429,10 @@ class TypeofGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::ValueNode
// If something is not an object, sanitize object, as both must end
// in non-function prototype object.
tag = "object" and
label instanceof UnsafePropLabel
exists(state)
or
tag = "function" and
label = "constructor"
state = "constructor"
)
}
}
@@ -428,27 +440,27 @@ class TypeofGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::ValueNode
/**
* A check of form `["__proto__"].includes(x)` or similar.
*/
class DenyListInclusionGuard extends DataFlow::LabeledBarrierGuardNode, InclusionTest {
UnsafePropLabel label;
class DenyListInclusionGuard extends BarrierGuard, InclusionTest {
string blockedProp;
DenyListInclusionGuard() {
exists(DataFlow::ArrayCreationNode array |
array.getAnElement().getStringValue() = label and
array.getAnElement().getStringValue() = blockedProp and
array.flowsTo(this.getContainerNode())
)
}
override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel lbl) {
override predicate blocksExpr(boolean outcome, Expr e, FlowState state) {
outcome = this.getPolarity().booleanNot() and
e = this.getContainedNode().asExpr() and
label = lbl
blockedProp = state
}
}
/**
* A check of form `xs.includes(x)` or similar, which sanitizes `x` in the true case.
*/
class AllowListInclusionGuard extends DataFlow::LabeledBarrierGuardNode {
class AllowListInclusionGuard extends BarrierGuard {
AllowListInclusionGuard() {
this instanceof TaintTracking::PositiveIndexOfSanitizer
or
@@ -456,9 +468,8 @@ class AllowListInclusionGuard extends DataFlow::LabeledBarrierGuardNode {
not this = any(MembershipCandidate::ObjectPropertyNameMembershipCandidate c).getTest() // handled with more precision in `HasOwnPropertyGuard`
}
override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel lbl) {
this.(TaintTracking::AdditionalSanitizerGuardNode).sanitizes(outcome, e) and
lbl instanceof UnsafePropLabel
override predicate blocksExpr(boolean outcome, Expr e) {
this.(TaintTracking::AdditionalBarrierGuard).blocksExpr(outcome, e)
}
}
@@ -467,17 +478,17 @@ class AllowListInclusionGuard extends DataFlow::LabeledBarrierGuardNode {
* payload in the true case, since it rejects objects with a non-standard `constructor`
* property.
*/
class IsPlainObjectGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::CallNode {
class IsPlainObjectGuard extends BarrierGuard, DataFlow::CallNode {
IsPlainObjectGuard() {
exists(string name | name = "is-plain-object" or name = "is-extendable" |
this = moduleImport(name).getACall()
this = DataFlow::moduleImport(name).getACall()
)
}
override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel lbl) {
override predicate blocksExpr(boolean outcome, Expr e, FlowState state) {
e = this.getArgument(0).asExpr() and
outcome = true and
lbl = "constructor"
state = "constructor"
}
}
@@ -507,26 +518,26 @@ string deriveExprName(DataFlow::Node node) {
* In most cases this will result in an alert, the exception being the case where
* `base` does not have a prototype at all.
*/
predicate isPrototypePollutingAssignment(Node base, Node prop, Node rhs, Node propNameSource) {
predicate isPrototypePollutingAssignment(
DataFlow::Node base, DataFlow::Node prop, DataFlow::Node rhs, DataFlow::Node propNameSource
) {
dynamicPropWrite(base, prop, rhs) and
isPollutedPropNameSource(propNameSource) and
exists(PropNameTracking cfg |
cfg.hasFlow(propNameSource, base) and
if propNameSource instanceof EnumeratedPropName
then
cfg.hasFlow(propNameSource, prop) and
cfg.hasFlow([propNameSource, AccessPath::getAnAliasedSourceNode(propNameSource)]
.(EnumeratedPropName)
.getASourceProp(), rhs)
else (
cfg.hasFlow(propNameSource.(SplitPropName).getAnAlias(), prop) and
rhs.getALocalSource() instanceof ParameterNode
)
PropNameTracking::flow(propNameSource, base) and
if propNameSource instanceof EnumeratedPropName
then
PropNameTracking::flow(propNameSource, prop) and
PropNameTracking::flow([propNameSource, AccessPath::getAnAliasedSourceNode(propNameSource)]
.(EnumeratedPropName)
.getASourceProp(), rhs)
else (
PropNameTracking::flow(propNameSource.(SplitPropName).getAnAlias(), prop) and
rhs.getALocalSource() instanceof DataFlow::ParameterNode
)
}
/** Gets a data flow node leading to the base of a prototype-polluting assignment. */
private DataFlow::SourceNode getANodeLeadingToBase(DataFlow::TypeBackTracker t, Node base) {
private DataFlow::SourceNode getANodeLeadingToBase(DataFlow::TypeBackTracker t, DataFlow::Node base) {
t.start() and
isPrototypePollutingAssignment(base, _, _, _) and
result = base.getALocalSource()
@@ -542,7 +553,9 @@ private DataFlow::SourceNode getANodeLeadingToBase(DataFlow::TypeBackTracker t,
* This dynamic read is where the reference to a built-in prototype object is obtained,
* and we need this to ensure that this object actually has a prototype.
*/
private DataFlow::SourceNode getANodeLeadingToBaseBase(DataFlow::TypeBackTracker t, Node base) {
private DataFlow::SourceNode getANodeLeadingToBaseBase(
DataFlow::TypeBackTracker t, DataFlow::Node base
) {
exists(DynamicPropRead read |
read = getANodeLeadingToBase(t, base) and
result = read.getBase().getALocalSource()
@@ -553,29 +566,31 @@ private DataFlow::SourceNode getANodeLeadingToBaseBase(DataFlow::TypeBackTracker
)
}
DataFlow::SourceNode getANodeLeadingToBaseBase(Node base) {
DataFlow::SourceNode getANodeLeadingToBaseBase(DataFlow::Node base) {
result = getANodeLeadingToBaseBase(DataFlow::TypeBackTracker::end(), base)
}
/** A call to `Object.create(null)`. */
class ObjectCreateNullCall extends CallNode {
class ObjectCreateNullCall extends DataFlow::CallNode {
ObjectCreateNullCall() {
this = globalVarRef("Object").getAMemberCall("create") and
this = DataFlow::globalVarRef("Object").getAMemberCall("create") and
this.getArgument(0).asExpr() instanceof NullLiteral
}
}
import DataFlow::DeduplicatePathGraph<PropNameTracking::PathNode, PropNameTracking::PathGraph>
from
PropNameTracking cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Node propNameSource,
Node base, string msg, Node col1, Node col2
PathNode source, PathNode sink, DataFlow::Node propNameSource, DataFlow::Node base, string msg,
DataFlow::Node col1, DataFlow::Node col2
where
isPollutedPropName(propNameSource) and
cfg.hasFlowPath(source, sink) and
PropNameTracking::flowPath(source.getAnOriginalPathNode(), sink.getAnOriginalPathNode()) and
isPrototypePollutingAssignment(base, _, _, propNameSource) and
sink.getNode() = base and
source.getNode() = propNameSource and
(
getANodeLeadingToBaseBase(base) instanceof ObjectLiteralNode
getANodeLeadingToBaseBase(base) instanceof DataFlow::ObjectLiteralNode
or
not getANodeLeadingToBaseBase(base) instanceof ObjectCreateNullCall
) and

View File

@@ -19,13 +19,11 @@
import javascript
import semmle.javascript.security.dataflow.PrototypePollutionQuery
import DataFlow::PathGraph
import DataFlow::DeduplicatePathGraph<PrototypePollutionFlow::PathNode, PrototypePollutionFlow::PathGraph>
from
Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, string moduleName,
Locatable dependencyLoc
from PathNode source, PathNode sink, string moduleName, Locatable dependencyLoc
where
cfg.hasFlowPath(source, sink) and
PrototypePollutionFlow::flowPath(source.getAnOriginalPathNode(), sink.getAnOriginalPathNode()) and
sink.getNode().(Sink).dependencyInfo(moduleName, dependencyLoc)
select sink.getNode(), source, sink,
"Prototype pollution caused by merging a $@ using a vulnerable version of $@.", source,

View File

@@ -12,9 +12,9 @@
import javascript
import semmle.javascript.security.dataflow.InsufficientPasswordHashQuery
import DataFlow::PathGraph
import InsufficientPasswordHashFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from InsufficientPasswordHashFlow::PathNode source, InsufficientPasswordHashFlow::PathNode sink
where InsufficientPasswordHashFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Password from $@ is hashed insecurely.", source.getNode(),
source.getNode().(Source).describe()

View File

@@ -13,11 +13,13 @@
import javascript
import semmle.javascript.security.dataflow.ClientSideRequestForgeryQuery
import DataFlow::PathGraph
import ClientSideRequestForgeryFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node request
from
ClientSideRequestForgeryFlow::PathNode source, ClientSideRequestForgeryFlow::PathNode sink,
DataFlow::Node request
where
cfg.hasFlowPath(source, sink) and
ClientSideRequestForgeryFlow::flowPath(source, sink) and
request = sink.getNode().(Sink).getARequest()
select request, source, sink, "The $@ of this request depends on a $@.", sink.getNode(),
sink.getNode().(Sink).getKind(), source, "user-provided value"

View File

@@ -12,11 +12,11 @@
import javascript
import semmle.javascript.security.dataflow.RequestForgeryQuery
import DataFlow::PathGraph
import RequestForgeryFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node request
from RequestForgeryFlow::PathNode source, RequestForgeryFlow::PathNode sink, DataFlow::Node request
where
cfg.hasFlowPath(source, sink) and
RequestForgeryFlow::flowPath(source, sink) and
request = sink.getNode().(Sink).getARequest()
select request, source, sink, "The $@ of this request depends on a $@.", sink.getNode(),
sink.getNode().(Sink).getKind(), source, "user-provided value"