python: Rewrite path injection to use flow state

This removes the FP cause by chaining
This PR also removes `ChainedConfigs12.qll`,
as we hope to solve future problems via flow states.
This commit is contained in:
Rasmus Lerchedahl Petersen
2022-01-21 09:26:48 +01:00
parent c09b6691e1
commit a5bc5373d0
6 changed files with 85 additions and 257 deletions

View File

@@ -115,6 +115,8 @@ module Path {
PathNormalization::Range range;
PathNormalization() { this = range }
DataFlow::Node getPathArg() { result = range.getPathArg() }
}
/** Provides a class for modeling new path normalization APIs. */
@@ -123,7 +125,10 @@ module Path {
* A data-flow node that performs path normalization. This is often needed in order
* to safely access paths.
*/
abstract class Range extends DataFlow::Node { }
abstract class Range extends DataFlow::Node {
/** Gets an argument to this path normalization that is interpreted as a path. */
abstract DataFlow::Node getPathArg();
}
}
/** A data-flow node that checks that a path is safe to access. */

View File

@@ -970,7 +970,7 @@ private module StdlibPrivate {
private class OsPathNormpathCall extends Path::PathNormalization::Range, DataFlow::CallCfgNode {
OsPathNormpathCall() { this = os::path().getMember("normpath").getACall() }
DataFlow::Node getPathArg() { result in [this.getArg(0), this.getArgByName("path")] }
override DataFlow::Node getPathArg() { result in [this.getArg(0), this.getArgByName("path")] }
}
/**
@@ -980,7 +980,7 @@ private module StdlibPrivate {
private class OsPathAbspathCall extends Path::PathNormalization::Range, DataFlow::CallCfgNode {
OsPathAbspathCall() { this = os::path().getMember("abspath").getACall() }
DataFlow::Node getPathArg() { result in [this.getArg(0), this.getArgByName("path")] }
override DataFlow::Node getPathArg() { result in [this.getArg(0), this.getArgByName("path")] }
}
/**
@@ -990,7 +990,7 @@ private module StdlibPrivate {
private class OsPathRealpathCall extends Path::PathNormalization::Range, DataFlow::CallCfgNode {
OsPathRealpathCall() { this = os::path().getMember("realpath").getACall() }
DataFlow::Node getPathArg() { result in [this.getArg(0), this.getArgByName("path")] }
override DataFlow::Node getPathArg() { result in [this.getArg(0), this.getArgByName("path")] }
}
/**

View File

@@ -1,83 +0,0 @@
/**
* This defines a `PathGraph` where sinks from `TaintTracking::Configuration`s are identified with
* sources from `TaintTracking2::Configuration`s if they represent the same `ControlFlowNode`.
*
* Paths are then connected appropriately.
*/
import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.DataFlow2
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.TaintTracking2
/**
* A `DataFlow::Node` that appears as a sink in Config1 and a source in Config2.
*/
private predicate crossoverNode(DataFlow::Node n) {
any(TaintTracking::Configuration t1).isSink(n) and
any(TaintTracking2::Configuration t2).isSource(n)
}
/**
* A new type which represents the union of the two sets of nodes.
*/
private newtype TCustomPathNode =
Config1Node(DataFlow::PathNode node1) { not crossoverNode(node1.getNode()) } or
Config2Node(DataFlow2::PathNode node2) { not crossoverNode(node2.getNode()) } or
CrossoverNode(DataFlow::Node node) { crossoverNode(node) }
/**
* A class representing the set of all the path nodes in either config.
*/
class CustomPathNode extends TCustomPathNode {
/** Gets the PathNode if it is in Config1. */
DataFlow::PathNode asNode1() {
this = Config1Node(result) or this = CrossoverNode(result.getNode())
}
/** Gets the PathNode if it is in Config2. */
DataFlow2::PathNode asNode2() {
this = Config2Node(result) or this = CrossoverNode(result.getNode())
}
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
asNode1().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
or
asNode2().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets a textual representation of this element. */
string toString() {
result = asNode1().toString()
or
result = asNode2().toString()
}
}
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(CustomPathNode a, CustomPathNode b) {
// Edge is in Config1 graph
DataFlow::PathGraph::edges(a.asNode1(), b.asNode1())
or
// Edge is in Config2 graph
DataFlow2::PathGraph::edges(a.asNode2(), b.asNode2())
}
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(CustomPathNode n, string key, string val) {
// Node is in Config1 graph
DataFlow::PathGraph::nodes(n.asNode1(), key, val)
or
// Node is in Config2 graph
DataFlow2::PathGraph::nodes(n.asNode2(), key, val)
}

View File

@@ -2,107 +2,81 @@
* Provides taint-tracking configurations for detecting "path injection" vulnerabilities.
*
* Note, for performance reasons: only import this file if
* the Configurations or the `pathInjection` predicate are needed, otherwise
* `PathInjection::Configuration` is needed, otherwise
* `PathInjectionCustomizations` should be imported instead.
*/
private import python
private import semmle.python.Concepts
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.DataFlow2
private import semmle.python.dataflow.new.TaintTracking
private import semmle.python.dataflow.new.TaintTracking2
import ChainedConfigs12
import PathInjectionCustomizations::PathInjection
// ---------------------------------------------------------------------------
// Case 1. The path is never normalized.
// ---------------------------------------------------------------------------
/** Configuration to find paths from sources to sinks that contain no normalization. */
class PathNotNormalizedConfiguration extends TaintTracking::Configuration {
PathNotNormalizedConfiguration() { this = "PathNotNormalizedConfiguration" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
override predicate isSanitizer(DataFlow::Node node) {
node instanceof Sanitizer
or
node instanceof Path::PathNormalization
}
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof SanitizerGuard
}
}
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
/**
* Holds if there is a path injection from source to sink, where the (python) path is
* not normalized.
* Provides a taint-tracking configuration for detecting "path injection" vulnerabilities.
*/
predicate pathNotNormalized(CustomPathNode source, CustomPathNode sink) {
any(PathNotNormalizedConfiguration config).hasFlowPath(source.asNode1(), sink.asNode1())
}
module PathInjection {
import PathInjectionCustomizations::PathInjection
// ---------------------------------------------------------------------------
// Case 2. The path is normalized at least once, but never checked afterwards.
// ---------------------------------------------------------------------------
/** Configuration to find paths from sources to normalizations that contain no prior normalizations. */
class FirstNormalizationConfiguration extends TaintTracking::Configuration {
FirstNormalizationConfiguration() { this = "FirstNormalizationConfiguration" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
override predicate isSink(DataFlow::Node sink) { sink instanceof Path::PathNormalization }
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
override predicate isSanitizerOut(DataFlow::Node node) { node instanceof Path::PathNormalization }
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof SanitizerGuard
}
}
/** Configuration to find paths from normalizations to sinks that do not go through a check. */
class NormalizedPathNotCheckedConfiguration extends TaintTracking2::Configuration {
NormalizedPathNotCheckedConfiguration() { this = "NormalizedPathNotCheckedConfiguration" }
override predicate isSource(DataFlow::Node source) { source instanceof Path::PathNormalization }
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof Path::SafeAccessCheck
or
guard instanceof SanitizerGuard
}
}
/**
* Holds if there is a path injection from source to sink, where the (python) path is
* normalized at least once, but never checked afterwards.
/**
* A taint-tracking configuration for detecting "path injection" vulnerabilities.
*
* This configuration uses two flow states, `NotNormalized` and `NormalizedUnchecked`,
* to track the requirement that a file path must be first normalized and then checked
* before it is safe to use.
*
* At sources, paths are assumed not normalized. At normalization points, they change
* state to `NormalizedUnchecked` after which they can be made safe by an appropriate
* check of the prefix.
*
* Such checks are ineffective in the `NotNormalized` state.
*/
predicate pathNotCheckedAfterNormalization(CustomPathNode source, CustomPathNode sink) {
exists(
FirstNormalizationConfiguration config, DataFlow::PathNode mid1, DataFlow2::PathNode mid2,
NormalizedPathNotCheckedConfiguration config2
|
config.hasFlowPath(source.asNode1(), mid1) and
config2.hasFlowPath(mid2, sink.asNode2()) and
mid1.getNode().asCfgNode() = mid2.getNode().asCfgNode()
class Configuration extends TaintTracking::Configuration {
Configuration() { this = "PathInjection" }
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
source instanceof Source and state instanceof NotNormalized
}
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
sink instanceof Sink and
(
state instanceof NotNormalized or
state instanceof NormalizedUnchecked
)
}
}
// ---------------------------------------------------------------------------
// Query: Either case 1 or case 2.
// ---------------------------------------------------------------------------
/** Holds if there is a path injection from source to sink */
predicate pathInjection(CustomPathNode source, CustomPathNode sink) {
pathNotNormalized(source, sink)
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
override predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) {
// Block `NotNormalized` paths here, since they change state to `NormalizedUnchecked`
node instanceof Path::PathNormalization and
state instanceof NotNormalized
or
pathNotCheckedAfterNormalization(source, sink)
node = any(Path::SafeAccessCheck c).getAGuardedNode() and
state instanceof NormalizedUnchecked
}
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof SanitizerGuard
}
override predicate isAdditionalFlowStep(
DataFlow::Node nodeFrom, DataFlow::FlowState stateFrom, DataFlow::Node nodeTo,
DataFlow::FlowState stateTo
) {
nodeFrom = nodeTo.(Path::PathNormalization).getPathArg() and
stateFrom instanceof NotNormalized and
stateTo instanceof NormalizedUnchecked
}
}
/** A state signifying that the file path has not been normalized. */
class NotNormalized extends DataFlow::FlowState {
NotNormalized() { this = "NotNormalized" }
}
/** A state signifying that the file path has been normalized, but not checked. */
class NormalizedUnchecked extends DataFlow::FlowState {
NormalizedUnchecked() { this = "NormalizedUnchecked" }
}
}

View File

@@ -18,7 +18,9 @@
import python
import semmle.python.security.dataflow.PathInjection
import DataFlow::PathGraph
from CustomPathNode source, CustomPathNode sink
where pathInjection(source, sink)
select sink, source, sink, "This path depends on $@.", source, "a user-provided value"
from PathInjection::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "This path depends on $@.", source.getNode(),
"a user-provided value"

View File

@@ -4,26 +4,14 @@ edges
| path_injection.py:12:16:12:22 | ControlFlowNode for request | path_injection.py:12:16:12:27 | ControlFlowNode for Attribute |
| path_injection.py:12:16:12:27 | ControlFlowNode for Attribute | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() |
| path_injection.py:19:16:19:22 | ControlFlowNode for request | path_injection.py:19:16:19:27 | ControlFlowNode for Attribute |
| path_injection.py:19:16:19:27 | ControlFlowNode for Attribute | path_injection.py:20:13:20:64 | ControlFlowNode for Attribute() |
| path_injection.py:20:13:20:64 | ControlFlowNode for Attribute() | path_injection.py:21:14:21:18 | ControlFlowNode for npath |
| path_injection.py:19:16:19:27 | ControlFlowNode for Attribute | path_injection.py:21:14:21:18 | ControlFlowNode for npath |
| path_injection.py:27:16:27:22 | ControlFlowNode for request | path_injection.py:27:16:27:27 | ControlFlowNode for Attribute |
| path_injection.py:27:16:27:27 | ControlFlowNode for Attribute | path_injection.py:28:13:28:64 | ControlFlowNode for Attribute() |
| path_injection.py:28:13:28:64 | ControlFlowNode for Attribute() | path_injection.py:31:14:31:18 | ControlFlowNode for npath |
| path_injection.py:37:16:37:22 | ControlFlowNode for request | path_injection.py:37:16:37:27 | ControlFlowNode for Attribute |
| path_injection.py:37:16:37:27 | ControlFlowNode for Attribute | path_injection.py:38:13:38:64 | ControlFlowNode for Attribute() |
| path_injection.py:27:16:27:27 | ControlFlowNode for Attribute | path_injection.py:31:14:31:18 | ControlFlowNode for npath |
| path_injection.py:46:16:46:22 | ControlFlowNode for request | path_injection.py:46:16:46:27 | ControlFlowNode for Attribute |
| path_injection.py:46:16:46:27 | ControlFlowNode for Attribute | path_injection.py:47:13:47:64 | ControlFlowNode for Attribute() |
| path_injection.py:47:13:47:64 | ControlFlowNode for Attribute() | path_injection.py:48:14:48:18 | ControlFlowNode for npath |
| path_injection.py:54:16:54:22 | ControlFlowNode for request | path_injection.py:54:16:54:27 | ControlFlowNode for Attribute |
| path_injection.py:54:16:54:27 | ControlFlowNode for Attribute | path_injection.py:55:13:55:64 | ControlFlowNode for Attribute() |
| path_injection.py:46:16:46:27 | ControlFlowNode for Attribute | path_injection.py:48:14:48:18 | ControlFlowNode for npath |
| path_injection.py:63:16:63:22 | ControlFlowNode for request | path_injection.py:63:16:63:27 | ControlFlowNode for Attribute |
| path_injection.py:63:16:63:27 | ControlFlowNode for Attribute | path_injection.py:64:13:64:63 | ControlFlowNode for Attribute() |
| path_injection.py:64:13:64:63 | ControlFlowNode for Attribute() | path_injection.py:65:14:65:18 | ControlFlowNode for npath |
| path_injection.py:71:16:71:22 | ControlFlowNode for request | path_injection.py:71:16:71:27 | ControlFlowNode for Attribute |
| path_injection.py:71:16:71:27 | ControlFlowNode for Attribute | path_injection.py:72:13:72:63 | ControlFlowNode for Attribute() |
| path_injection.py:63:16:63:27 | ControlFlowNode for Attribute | path_injection.py:65:14:65:18 | ControlFlowNode for npath |
| path_injection.py:84:16:84:22 | ControlFlowNode for request | path_injection.py:84:16:84:27 | ControlFlowNode for Attribute |
| path_injection.py:84:16:84:22 | ControlFlowNode for request | path_injection.py:84:16:84:27 | ControlFlowNode for Attribute |
| path_injection.py:84:16:84:27 | ControlFlowNode for Attribute | path_injection.py:86:8:86:44 | ControlFlowNode for Attribute() |
| path_injection.py:84:16:84:27 | ControlFlowNode for Attribute | path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path |
| path_injection.py:91:20:91:25 | ControlFlowNode for foo_id | path_injection.py:94:14:94:17 | ControlFlowNode for path |
| path_injection.py:98:20:98:22 | ControlFlowNode for foo | path_injection.py:102:14:102:17 | ControlFlowNode for path |
@@ -34,47 +22,26 @@ edges
| path_injection.py:129:16:129:22 | ControlFlowNode for request | path_injection.py:129:16:129:27 | ControlFlowNode for Attribute |
| path_injection.py:129:16:129:27 | ControlFlowNode for Attribute | path_injection.py:132:14:132:22 | ControlFlowNode for sanitized |
| path_injection.py:138:16:138:22 | ControlFlowNode for request | path_injection.py:138:16:138:27 | ControlFlowNode for Attribute |
| path_injection.py:138:16:138:22 | ControlFlowNode for request | path_injection.py:138:16:138:27 | ControlFlowNode for Attribute |
| path_injection.py:138:16:138:27 | ControlFlowNode for Attribute | path_injection.py:140:30:140:51 | ControlFlowNode for Attribute() |
| path_injection.py:138:16:138:27 | ControlFlowNode for Attribute | path_injection.py:142:14:142:17 | ControlFlowNode for path |
| path_injection.py:149:16:149:22 | ControlFlowNode for request | path_injection.py:149:16:149:27 | ControlFlowNode for Attribute |
| path_injection.py:149:16:149:27 | ControlFlowNode for Attribute | path_injection.py:152:18:152:21 | ControlFlowNode for path |
| test.py:9:12:9:18 | ControlFlowNode for request | test.py:9:12:9:23 | ControlFlowNode for Attribute |
| test.py:9:12:9:18 | ControlFlowNode for request | test.py:9:12:9:23 | ControlFlowNode for Attribute |
| test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:9:12:9:39 | ControlFlowNode for Attribute() |
| test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:9:12:9:39 | ControlFlowNode for Attribute() |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | test.py:18:9:18:16 | ControlFlowNode for source() |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | test.py:24:9:24:16 | ControlFlowNode for source() |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | test.py:31:9:31:16 | ControlFlowNode for source() |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | test.py:38:9:38:16 | ControlFlowNode for source() |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | test.py:46:9:46:16 | ControlFlowNode for source() |
| test.py:12:15:12:15 | ControlFlowNode for x | test.py:13:12:13:30 | ControlFlowNode for Attribute() |
| test.py:13:12:13:30 | ControlFlowNode for Attribute() | test.py:25:9:25:20 | ControlFlowNode for normalize() |
| test.py:13:12:13:30 | ControlFlowNode for Attribute() | test.py:48:13:48:24 | ControlFlowNode for normalize() |
| test.py:18:9:18:16 | ControlFlowNode for source() | test.py:19:10:19:10 | ControlFlowNode for x |
| test.py:24:9:24:16 | ControlFlowNode for source() | test.py:25:19:25:19 | ControlFlowNode for x |
| test.py:25:9:25:20 | ControlFlowNode for normalize() | test.py:26:10:26:10 | ControlFlowNode for y |
| test.py:25:19:25:19 | ControlFlowNode for x | test.py:12:15:12:15 | ControlFlowNode for x |
| test.py:25:19:25:19 | ControlFlowNode for x | test.py:25:9:25:20 | ControlFlowNode for normalize() |
| test.py:31:9:31:16 | ControlFlowNode for source() | test.py:33:14:33:14 | ControlFlowNode for x |
| test.py:38:9:38:16 | ControlFlowNode for source() | test.py:39:19:39:19 | ControlFlowNode for x |
| test.py:39:19:39:19 | ControlFlowNode for x | test.py:12:15:12:15 | ControlFlowNode for x |
| test.py:46:9:46:16 | ControlFlowNode for source() | test.py:48:23:48:23 | ControlFlowNode for x |
| test.py:48:13:48:24 | ControlFlowNode for normalize() | test.py:49:14:49:14 | ControlFlowNode for y |
| test.py:48:23:48:23 | ControlFlowNode for x | test.py:12:15:12:15 | ControlFlowNode for x |
| test_chaining.py:9:12:9:18 | ControlFlowNode for request | test_chaining.py:9:12:9:23 | ControlFlowNode for Attribute |
| test_chaining.py:9:12:9:23 | ControlFlowNode for Attribute | test_chaining.py:9:12:9:39 | ControlFlowNode for Attribute() |
| test_chaining.py:9:12:9:39 | ControlFlowNode for Attribute() | test_chaining.py:20:9:20:16 | ControlFlowNode for source() |
| test_chaining.py:9:12:9:39 | ControlFlowNode for Attribute() | test_chaining.py:28:9:28:16 | ControlFlowNode for source() |
| test_chaining.py:9:12:9:39 | ControlFlowNode for Attribute() | test_chaining.py:41:9:41:16 | ControlFlowNode for source() |
| test_chaining.py:14:15:14:15 | ControlFlowNode for x | test_chaining.py:15:12:15:30 | ControlFlowNode for Attribute() |
| test_chaining.py:15:12:15:30 | ControlFlowNode for Attribute() | test_chaining.py:31:13:31:24 | ControlFlowNode for normalize() |
| test_chaining.py:20:9:20:16 | ControlFlowNode for source() | test_chaining.py:21:19:21:19 | ControlFlowNode for x |
| test_chaining.py:21:19:21:19 | ControlFlowNode for x | test_chaining.py:14:15:14:15 | ControlFlowNode for x |
| test_chaining.py:28:9:28:16 | ControlFlowNode for source() | test_chaining.py:29:19:29:19 | ControlFlowNode for x |
| test_chaining.py:29:19:29:19 | ControlFlowNode for x | test_chaining.py:14:15:14:15 | ControlFlowNode for x |
| test_chaining.py:31:13:31:24 | ControlFlowNode for normalize() | test_chaining.py:32:14:32:14 | ControlFlowNode for z |
| test_chaining.py:41:9:41:16 | ControlFlowNode for source() | test_chaining.py:42:9:42:19 | ControlFlowNode for normpath() |
| test_chaining.py:44:13:44:23 | ControlFlowNode for normpath() | test_chaining.py:45:14:45:14 | ControlFlowNode for z |
| test.py:48:23:48:23 | ControlFlowNode for x | test.py:48:13:48:24 | ControlFlowNode for normalize() |
nodes
| flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| flask_path_injection.py:19:15:19:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
@@ -84,34 +51,18 @@ nodes
| path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:19:16:19:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:19:16:19:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:20:13:20:64 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:21:14:21:18 | ControlFlowNode for npath | semmle.label | ControlFlowNode for npath |
| path_injection.py:27:16:27:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:27:16:27:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:28:13:28:64 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:31:14:31:18 | ControlFlowNode for npath | semmle.label | ControlFlowNode for npath |
| path_injection.py:37:16:37:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:37:16:37:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:38:13:38:64 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:46:16:46:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:46:16:46:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:47:13:47:64 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:48:14:48:18 | ControlFlowNode for npath | semmle.label | ControlFlowNode for npath |
| path_injection.py:54:16:54:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:54:16:54:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:55:13:55:64 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:63:16:63:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:63:16:63:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:64:13:64:63 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:65:14:65:18 | ControlFlowNode for npath | semmle.label | ControlFlowNode for npath |
| path_injection.py:71:16:71:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:71:16:71:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:72:13:72:63 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:84:16:84:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:84:16:84:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:84:16:84:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:84:16:84:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:86:8:86:44 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | semmle.label | ControlFlowNode for possibly_unsafe_path |
| path_injection.py:91:20:91:25 | ControlFlowNode for foo_id | semmle.label | ControlFlowNode for foo_id |
| path_injection.py:94:14:94:17 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
@@ -127,19 +78,13 @@ nodes
| path_injection.py:129:16:129:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | semmle.label | ControlFlowNode for sanitized |
| path_injection.py:138:16:138:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:138:16:138:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:138:16:138:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:138:16:138:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:140:30:140:51 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:142:14:142:17 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| path_injection.py:149:16:149:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:149:16:149:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:152:18:152:21 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| test.py:9:12:9:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test.py:9:12:9:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test.py:9:12:9:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:9:12:9:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:12:15:12:15 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:13:12:13:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
@@ -151,27 +96,13 @@ nodes
| test.py:26:10:26:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| test.py:31:9:31:16 | ControlFlowNode for source() | semmle.label | ControlFlowNode for source() |
| test.py:33:14:33:14 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:38:9:38:16 | ControlFlowNode for source() | semmle.label | ControlFlowNode for source() |
| test.py:39:19:39:19 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:46:9:46:16 | ControlFlowNode for source() | semmle.label | ControlFlowNode for source() |
| test.py:48:13:48:24 | ControlFlowNode for normalize() | semmle.label | ControlFlowNode for normalize() |
| test.py:48:23:48:23 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:49:14:49:14 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| test_chaining.py:9:12:9:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_chaining.py:9:12:9:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_chaining.py:9:12:9:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test_chaining.py:14:15:14:15 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test_chaining.py:15:12:15:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test_chaining.py:20:9:20:16 | ControlFlowNode for source() | semmle.label | ControlFlowNode for source() |
| test_chaining.py:21:19:21:19 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test_chaining.py:28:9:28:16 | ControlFlowNode for source() | semmle.label | ControlFlowNode for source() |
| test_chaining.py:29:19:29:19 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test_chaining.py:31:13:31:24 | ControlFlowNode for normalize() | semmle.label | ControlFlowNode for normalize() |
| test_chaining.py:32:14:32:14 | ControlFlowNode for z | semmle.label | ControlFlowNode for z |
| test_chaining.py:41:9:41:16 | ControlFlowNode for source() | semmle.label | ControlFlowNode for source() |
| test_chaining.py:42:9:42:19 | ControlFlowNode for normpath() | semmle.label | ControlFlowNode for normpath() |
| test_chaining.py:44:13:44:23 | ControlFlowNode for normpath() | semmle.label | ControlFlowNode for normpath() |
| test_chaining.py:45:14:45:14 | ControlFlowNode for z | semmle.label | ControlFlowNode for z |
subpaths
| test.py:25:19:25:19 | ControlFlowNode for x | test.py:12:15:12:15 | ControlFlowNode for x | test.py:13:12:13:30 | ControlFlowNode for Attribute() | test.py:25:9:25:20 | ControlFlowNode for normalize() |
| test.py:48:23:48:23 | ControlFlowNode for x | test.py:12:15:12:15 | ControlFlowNode for x | test.py:13:12:13:30 | ControlFlowNode for Attribute() | test.py:48:13:48:24 | ControlFlowNode for normalize() |
#select
| flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | This path depends on $@. | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | a user-provided value |
| path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | path_injection.py:12:16:12:22 | ControlFlowNode for request | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | This path depends on $@. | path_injection.py:12:16:12:22 | ControlFlowNode for request | a user-provided value |
@@ -191,4 +122,3 @@ nodes
| test.py:26:10:26:10 | ControlFlowNode for y | test.py:9:12:9:18 | ControlFlowNode for request | test.py:26:10:26:10 | ControlFlowNode for y | This path depends on $@. | test.py:9:12:9:18 | ControlFlowNode for request | a user-provided value |
| test.py:33:14:33:14 | ControlFlowNode for x | test.py:9:12:9:18 | ControlFlowNode for request | test.py:33:14:33:14 | ControlFlowNode for x | This path depends on $@. | test.py:9:12:9:18 | ControlFlowNode for request | a user-provided value |
| test.py:49:14:49:14 | ControlFlowNode for y | test.py:9:12:9:18 | ControlFlowNode for request | test.py:49:14:49:14 | ControlFlowNode for y | This path depends on $@. | test.py:9:12:9:18 | ControlFlowNode for request | a user-provided value |
| test_chaining.py:32:14:32:14 | ControlFlowNode for z | test_chaining.py:9:12:9:18 | ControlFlowNode for request | test_chaining.py:32:14:32:14 | ControlFlowNode for z | This path depends on $@. | test_chaining.py:9:12:9:18 | ControlFlowNode for request | a user-provided value |