Compare commits

..

10 Commits

Author SHA1 Message Date
Ian Wright
a716d39370 repatch 2021-12-17 16:59:31 +00:00
Ian Wright
335b2466a9 patch again 2021-12-17 16:49:40 +00:00
Ian Wright
96ae9617ec post cherry-pick patch 2021-12-17 16:43:07 +00:00
Henry Mercer
82029663b2 JS: Push FeaturizationConfig context into more predicates 2021-12-17 16:03:15 +00:00
Henry Mercer
4cd15ba654 JS: Only featurize endpoints that are part of a flow path 2021-12-17 15:58:46 +00:00
Ian Wright
c17c10e450 Revert "JS: Push FeaturizationConfig context into more predicates"
This reverts commit a0f479d503.
2021-12-17 15:54:03 +00:00
Henry Mercer
a0f479d503 JS: Push FeaturizationConfig context into more predicates 2021-12-17 13:54:25 +00:00
Ian Wright
24a5e8a8e1 bump the release number 2021-12-17 13:12:05 +00:00
Henry Mercer
427cdf480a JS: Update featurization for absent features optimization
Absent features are now represented implicitly by the absence of a row
in the `tokenFeatures` relation, rather than explicitly by an empty
string. This leads to improved runtime performance. To enable this
implicit representation, we pass the set of supported token features to
the `scoreEndpoints` HOP. Requires CodeQL CLI v2.7.4.
2021-12-17 13:10:10 +00:00
Ian Wright
8e1f2645cb bump the release number 2021-12-17 13:10:10 +00:00
103 changed files with 24211 additions and 24114 deletions

3
.github/labeler.yml vendored
View File

@@ -26,6 +26,3 @@ documentation:
- "**/*.qhelp"
- "**/*.md"
- docs/**/*
"QL-for-QL":
- ql/**/*

View File

@@ -7,7 +7,6 @@ on:
- "*/ql/src/**/*.ql"
- "*/ql/src/**/*.qll"
- "!**/experimental/**"
- "!ql/**"
jobs:
check-change-note:

View File

@@ -16,7 +16,7 @@ jobs:
- uses: actions/checkout@v2
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@erik-krogh/ql
uses: github/codeql-action/init@esbena/ql
with:
languages: javascript # does not matter
- name: Get CodeQL version
@@ -56,46 +56,27 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Cache entire extractor
id: cache-extractor
uses: actions/cache@v2
with:
path: |
ql/target/release/ql-autobuilder
ql/target/release/ql-autobuilder.exe
ql/target/release/ql-extractor
ql/target/release/ql-extractor.exe
key: ${{ runner.os }}-extractor-${{ hashFiles('ql/**/Cargo.lock') }}-${{ hashFiles('ql/**/*.rs') }}
- name: Cache cargo
if: steps.cache-extractor.outputs.cache-hit != 'true'
uses: actions/cache@v2
- uses: actions/cache@v2
with:
path: |
~/.cargo/registry
~/.cargo/git
ql/target
key: ${{ runner.os }}-rust-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
key: ${{ runner.os }}-rust-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Check formatting
if: steps.cache-extractor.outputs.cache-hit != 'true'
run: cd ql; cargo fmt --all -- --check
- name: Build
if: steps.cache-extractor.outputs.cache-hit != 'true'
run: cd ql; cargo build --verbose
- name: Run tests
if: steps.cache-extractor.outputs.cache-hit != 'true'
run: cd ql; cargo test --verbose
- name: Release build
if: steps.cache-extractor.outputs.cache-hit != 'true'
run: cd ql; cargo build --release
- name: Generate dbscheme
if: steps.cache-extractor.outputs.cache-hit != 'true'
run: ql/target/release/ql-generator --dbscheme ql/ql/src/ql.dbscheme --library ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll
- uses: actions/upload-artifact@v2
with:
name: extractor-ubuntu-latest
path: |
ql/target/release/ql-autobuilder
ql/target/release/ql-autobuilder.exe
ql/target/release/ql-extractor
ql/target/release/ql-extractor.exe
retention-days: 1
@@ -120,10 +101,6 @@ jobs:
unzip query-pack-zip/*.zip -d pack
cp -r ql/codeql-extractor.yml ql/tools ql/ql/src/ql.dbscheme.stats pack/
mkdir -p pack/tools/linux64
if [[ -f linux64/ql-autobuilder ]]; then
cp linux64/ql-autobuilder pack/tools/linux64/autobuilder
chmod +x pack/tools/linux64/autobuilder
fi
if [[ -f linux64/ql-extractor ]]; then
cp linux64/ql-extractor pack/tools/linux64/extractor
chmod +x pack/tools/linux64/extractor
@@ -135,16 +112,13 @@ jobs:
name: codeql-ql-pack
path: codeql-ql.zip
retention-days: 1
analyze:
analyze:
runs-on: ubuntu-latest
strategy:
matrix:
folder: [cpp, csharp, java, javascript, python, ql, ruby]
needs:
needs:
- package
steps:
steps:
- name: Download pack
uses: actions/download-artifact@v2
with:
@@ -166,27 +140,13 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v2
- name: Create CodeQL config file
run: |
echo "paths:" > ${CONF}
echo " - ${FOLDER}" >> ${CONF}
echo "paths-ignore:" >> ${CONF}
echo " - ql/ql/test" >> ${CONF}
echo "Config file: "
cat ${CONF}
env:
CONF: ./ql-for-ql-config.yml
FOLDER: ${{ matrix.folder }}
- name: Initialize CodeQL
uses: github/codeql-action/init@erik-krogh/ql
uses: github/codeql-action/init@esbena/ql
with:
languages: ql
db-location: ${{ runner.temp }}/db
config-file: ./ql-for-ql-config.yml
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@erik-krogh/ql
with:
category: "ql-for-ql-${{ matrix.folder }}"
uses: github/codeql-action/analyze@esbena/ql

View File

@@ -26,7 +26,7 @@ jobs:
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@erik-krogh/ql
uses: github/codeql-action/init@esbena/ql
with:
languages: javascript # does not matter
- uses: actions/cache@v2

View File

@@ -4,11 +4,11 @@ on:
push:
branches: [main]
paths:
- "ql/**"
- ql/*
pull_request:
branches: [main]
paths:
- "ql/**"
- ql/*
env:
CARGO_TERM_COLOR: always
@@ -20,7 +20,7 @@ jobs:
- uses: actions/checkout@v2
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@erik-krogh/ql
uses: github/codeql-action/init@esbena/ql
with:
languages: javascript # does not matter
- uses: actions/cache@v2

View File

@@ -1,2 +0,0 @@
lgtm,codescanning
* The "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) query has been improved, reducing the number of false positive results when encryption is present.

View File

@@ -73,7 +73,7 @@ class Options extends string {
* __assume(0);
* ```
* (note that in this case if the hint is wrong and the expression is reached at
* runtime, the program's behavior is undefined)
* runtime, the program's behaviour is undefined)
*/
predicate exprExits(Expr e) {
e.(AssumeExpr).getChild(0).(CompileTimeConstantInt).getIntValue() = 0 or

View File

@@ -50,7 +50,7 @@ class CustomOptions extends Options {
* __assume(0);
* ```
* (note that in this case if the hint is wrong and the expression is reached at
* runtime, the program's behavior is undefined)
* runtime, the program's behaviour is undefined)
*/
override predicate exprExits(Expr e) { Options.super.exprExits(e) }

View File

@@ -5,7 +5,7 @@
* `Instruction` level), and then using the array length analysis and the range
* analysis together to prove that some of these pointer dereferences are safe.
*
* The analysis is soundy, i.e. it is sound if no undefined behavior is present
* The analysis is soundy, i.e. it is sound if no undefined behaviour is present
* in the program.
* Furthermore, it crucially depends on the soundiness of the range analysis and
* the array length analysis.

View File

@@ -153,11 +153,9 @@ library class SSAHelper extends int {
* Modern Compiler Implementation by Andrew Appel.
*/
private predicate frontier_phi_node(StackVariable v, BasicBlock b) {
exists(BasicBlock x |
dominanceFrontier(x, b) and ssa_defn_rec(pragma[only_bind_into](v), pragma[only_bind_into](x))
) and
exists(BasicBlock x | dominanceFrontier(x, b) and ssa_defn_rec(v, x)) and
/* We can also eliminate those nodes where the variable is not live on any incoming edge */
live_at_start_of_bb(pragma[only_bind_into](v), b)
live_at_start_of_bb(v, b)
}
private predicate ssa_defn_rec(StackVariable v, BasicBlock b) {

View File

@@ -15,23 +15,11 @@ module Consistency {
class ConsistencyConfiguration extends TConsistencyConfiguration {
string toString() { none() }
/** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */
predicate uniqueEnclosingCallableExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */
predicate uniqueNodeLocationExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `missingLocation`. */
predicate missingLocationExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `postWithInFlow`. */
predicate postWithInFlowExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `argHasPostUpdate`. */
predicate argHasPostUpdateExclude(ArgumentNode n) { none() }
/** Holds if `n` should be excluded from the consistency test `reverseRead`. */
predicate reverseReadExclude(Node n) { none() }
}
private class RelevantNode extends Node {
@@ -58,7 +46,6 @@ module Consistency {
n instanceof RelevantNode and
c = count(nodeGetEnclosingCallable(n)) and
c != 1 and
not any(ConsistencyConfiguration conf).uniqueEnclosingCallableExclude(n) and
msg = "Node should have one enclosing callable but has " + c + "."
)
}
@@ -79,7 +66,6 @@ module Consistency {
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
) and
c != 1 and
not any(ConsistencyConfiguration conf).uniqueNodeLocationExclude(n) and
msg = "Node should have one location but has " + c + "."
)
}
@@ -90,8 +76,7 @@ module Consistency {
strictcount(Node n |
not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
) and
not any(ConsistencyConfiguration conf).missingLocationExclude(n)
)
) and
msg = "Nodes without location: " + c
)
@@ -187,7 +172,6 @@ module Consistency {
query predicate reverseRead(Node n, string msg) {
exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and
not any(ConsistencyConfiguration conf).reverseReadExclude(n) and
msg = "Origin of readStep is missing a PostUpdateNode."
}

View File

@@ -118,7 +118,7 @@ class LambdaCapture extends Locatable, @lambdacapture {
* An identifier is captured by reference if:
* - It is explicitly captured by reference.
* - It is implicitly captured, and the lambda's default capture mode is by-reference.
* - The identifier is "this". [Said behavior is dictated by the C++11 standard, but it
* - The identifier is "this". [Said behaviour is dictated by the C++11 standard, but it
* is actually "*this" being captured rather than "this".]
*/
predicate isCapturedByReference() { lambda_capture(this, _, _, _, true, _, _) }

View File

@@ -15,23 +15,11 @@ module Consistency {
class ConsistencyConfiguration extends TConsistencyConfiguration {
string toString() { none() }
/** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */
predicate uniqueEnclosingCallableExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */
predicate uniqueNodeLocationExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `missingLocation`. */
predicate missingLocationExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `postWithInFlow`. */
predicate postWithInFlowExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `argHasPostUpdate`. */
predicate argHasPostUpdateExclude(ArgumentNode n) { none() }
/** Holds if `n` should be excluded from the consistency test `reverseRead`. */
predicate reverseReadExclude(Node n) { none() }
}
private class RelevantNode extends Node {
@@ -58,7 +46,6 @@ module Consistency {
n instanceof RelevantNode and
c = count(nodeGetEnclosingCallable(n)) and
c != 1 and
not any(ConsistencyConfiguration conf).uniqueEnclosingCallableExclude(n) and
msg = "Node should have one enclosing callable but has " + c + "."
)
}
@@ -79,7 +66,6 @@ module Consistency {
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
) and
c != 1 and
not any(ConsistencyConfiguration conf).uniqueNodeLocationExclude(n) and
msg = "Node should have one location but has " + c + "."
)
}
@@ -90,8 +76,7 @@ module Consistency {
strictcount(Node n |
not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
) and
not any(ConsistencyConfiguration conf).missingLocationExclude(n)
)
) and
msg = "Nodes without location: " + c
)
@@ -187,7 +172,6 @@ module Consistency {
query predicate reverseRead(Node n, string msg) {
exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and
not any(ConsistencyConfiguration conf).reverseReadExclude(n) and
msg = "Origin of readStep is missing a PostUpdateNode."
}

View File

@@ -3,7 +3,7 @@
"qhelp.dtd">
<qhelp>
<overview>
<p>The return value of a call to <code>snprintf</code> is the number of characters that <i>would have</i> been written to the buffer assuming there was sufficient space. In the event that the operation reaches the end of the buffer and more than one character is discarded, the return value will be greater than the buffer size. This can cause incorrect behavior, for example:
<p>The return value of a call to <code>snprintf</code> is the number of characters that <i>would have</i> been written to the buffer assuming there was sufficient space. In the event that the operation reaches the end of the buffer and more than one character is discarded, the return value will be greater than the buffer size. This can cause incorrect behaviour, for example:
</p>
</overview>

View File

@@ -14,188 +14,105 @@
import cpp
import semmle.code.cpp.security.SensitiveExprs
import semmle.code.cpp.dataflow.TaintTracking
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import semmle.code.cpp.models.interfaces.FlowSource
import DataFlow::PathGraph
/**
* A DataFlow node corresponding to a variable or function call that
* might contain or return a password or other sensitive information.
*/
class SensitiveNode extends DataFlow::Node {
SensitiveNode() {
this.asExpr() = any(SensitiveVariable sv).getInitializer().getExpr() or
this.asExpr().(VariableAccess).getTarget() =
any(SensitiveVariable sv).(GlobalOrNamespaceVariable) or
this.asUninitialized() instanceof SensitiveVariable or
this.asParameter() instanceof SensitiveVariable or
this.asExpr().(FunctionCall).getTarget() instanceof SensitiveFunction
}
}
/**
* A function that sends or receives data over a network.
*/
abstract class SendRecv extends Function {
/**
* Gets the expression for the socket or similar object used for sending or
* receiving data through the function call `call` (if any).
*/
abstract Expr getSocketExpr(Call call);
/**
* Gets the expression for the buffer to be sent from / received into through
* the function call `call`.
*/
abstract Expr getDataExpr(Call call);
}
/**
* A function that sends data over a network.
*/
class Send extends SendRecv instanceof RemoteFlowSinkFunction {
override Expr getSocketExpr(Call call) {
call.getTarget() = this and
exists(FunctionInput input, int arg |
super.hasSocketInput(input) and
input.isParameter(arg) and
result = call.getArgument(arg)
)
}
override Expr getDataExpr(Call call) {
call.getTarget() = this and
exists(FunctionInput input, int arg |
super.hasRemoteFlowSink(input, _) and
input.isParameterDeref(arg) and
result = call.getArgument(arg)
)
}
}
/**
* A function that receives data over a network.
*/
class Recv extends SendRecv instanceof RemoteFlowSourceFunction {
override Expr getSocketExpr(Call call) {
call.getTarget() = this and
exists(FunctionInput input, int arg |
super.hasSocketInput(input) and
input.isParameter(arg) and
result = call.getArgument(arg)
)
}
override Expr getDataExpr(Call call) {
call.getTarget() = this and
exists(FunctionOutput output, int arg |
super.hasRemoteFlowSource(output, _) and
output.isParameterDeref(arg) and
result = call.getArgument(arg)
)
}
}
/**
* A function call that sends or receives data over a network.
*
* note: function calls such as `write` may be writing to a network source
* or a file. We could attempt to determine which, and sort results into
* `cpp/cleartext-transmission` and perhaps `cpp/cleartext-storage-file`. In
* practice it usually isn't very important which query reports a result as
* long as its reported exactly once.
*
* We do exclude function calls that specify a constant socket, which is
* likely to mean standard input, standard output or a similar channel.
*/
abstract class NetworkSendRecv extends FunctionCall {
SendRecv target;
/**
* Gets the expression for the socket or similar object used for sending or
* receiving data (if any).
*/
abstract Expr getSocketExpr();
NetworkSendRecv() {
this.getTarget() = target and
// exclude calls based on the socket...
not exists(GVN g |
g = globalValueNumber(target.getSocketExpr(this)) and
(
// literal constant
globalValueNumber(any(Literal l)) = g
or
// variable (such as a global) initialized to a literal constant
exists(Variable v |
v.getInitializer().getExpr() instanceof Literal and
g = globalValueNumber(v.getAnAccess())
)
)
)
}
final Expr getDataExpr() { result = target.getDataExpr(this) }
/**
* Gets the expression for the buffer to be sent from / received into.
*/
abstract Expr getDataExpr();
}
/**
* A function call that sends data over a network.
*
* note: functions such as `write` may be writing to a network source or a file. We could attempt to determine which, and sort results into `cpp/cleartext-transmission` and perhaps `cpp/cleartext-storage-file`. In practice it usually isn't very important which query reports a result as long as its reported exactly once.
*/
class NetworkSend extends NetworkSendRecv {
override Send target;
RemoteFlowSinkFunction target;
NetworkSend() { target = this.getTarget() }
override Expr getSocketExpr() {
exists(FunctionInput input, int arg |
target.hasSocketInput(input) and
input.isParameter(arg) and
result = this.getArgument(arg)
)
}
override Expr getDataExpr() {
exists(FunctionInput input, int arg |
target.hasRemoteFlowSink(input, _) and
input.isParameterDeref(arg) and
result = this.getArgument(arg)
)
}
}
/**
* A function call that receives data over a network.
*/
class NetworkRecv extends NetworkSendRecv {
override Recv target;
}
RemoteFlowSourceFunction target;
/**
* An expression that is an argument or return value from an encryption or
* decryption call.
*/
class Encrypted extends Expr {
Encrypted() {
exists(FunctionCall fc |
fc.getTarget().getName().toLowerCase().regexpMatch(".*(crypt|encode|decode).*") and
(
this = fc or
this = fc.getAnArgument()
)
NetworkRecv() { target = this.getTarget() }
override Expr getSocketExpr() {
exists(FunctionInput input, int arg |
target.hasSocketInput(input) and
input.isParameter(arg) and
result = this.getArgument(arg)
)
}
override Expr getDataExpr() {
exists(FunctionOutput output, int arg |
target.hasRemoteFlowSource(output, _) and
output.isParameterDeref(arg) and
result = this.getArgument(arg)
)
}
}
/**
* Taint flow from a sensitive expression.
* Taint flow from a sensitive expression to a network operation with data
* tainted by that expression.
*/
class FromSensitiveConfiguration extends TaintTracking::Configuration {
FromSensitiveConfiguration() { this = "FromSensitiveConfiguration" }
class SensitiveSendRecvConfiguration extends TaintTracking::Configuration {
SensitiveSendRecvConfiguration() { this = "SensitiveSendRecvConfiguration" }
override predicate isSource(DataFlow::Node source) { source instanceof SensitiveNode }
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveExpr }
override predicate isSink(DataFlow::Node sink) {
sink.asExpr() = any(NetworkSendRecv nsr).getDataExpr()
or
sink.asExpr() instanceof Encrypted
}
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
// flow through encryption functions to the return value (in case we can reach other sinks)
node2.asExpr().(Encrypted).(FunctionCall).getAnArgument() = node1.asExpr()
exists(NetworkSendRecv transmission |
sink.asExpr() = transmission.getDataExpr() and
// a zero socket descriptor is standard input, which is not interesting for this query.
not exists(Zero zero |
DataFlow::localFlow(DataFlow::exprNode(zero),
DataFlow::exprNode(transmission.getSocketExpr()))
)
)
}
}
from
FromSensitiveConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink,
NetworkSendRecv networkSendRecv, string msg
SensitiveSendRecvConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink,
NetworkSendRecv transmission, string msg
where
// flow from sensitive -> network data
config.hasFlowPath(source, sink) and
sink.getNode().asExpr() = networkSendRecv.getDataExpr() and
// no flow from sensitive -> evidence of encryption
not exists(DataFlow::Node encrypted |
config.hasFlow(source.getNode(), encrypted) and
encrypted.asExpr() instanceof Encrypted
) and
// construct result
if networkSendRecv instanceof NetworkSend
sink.getNode().asExpr() = transmission.getDataExpr() and
if transmission instanceof NetworkSend
then
msg =
"This operation transmits '" + sink.toString() +
@@ -204,4 +121,4 @@ where
msg =
"This operation receives into '" + sink.toString() +
"', which may put unencrypted sensitive data into $@"
select networkSendRecv, source, sink, msg, source, source.getNode().toString()
select transmission, source, sink, msg, source, source.getNode().asExpr().toString()

View File

@@ -1,228 +1,49 @@
edges
| test3.cpp:17:28:17:36 | password1 | test3.cpp:22:15:22:23 | password1 |
| test3.cpp:17:51:17:59 | password2 | test3.cpp:26:15:26:23 | password2 |
| test3.cpp:45:8:45:15 | password | test3.cpp:47:15:47:22 | password |
| test3.cpp:53:8:53:15 | password | test3.cpp:55:15:55:22 | password |
| test3.cpp:71:32:71:40 | password1 | test3.cpp:76:15:76:17 | ptr |
| test3.cpp:80:8:80:15 | password | test3.cpp:83:15:83:17 | ptr |
| test3.cpp:98:8:98:15 | password | test3.cpp:101:12:101:19 | password |
| test3.cpp:112:20:112:25 | buffer | test3.cpp:114:14:114:19 | buffer |
| test3.cpp:117:28:117:33 | buffer | test3.cpp:119:9:119:14 | buffer |
| test3.cpp:126:9:126:23 | global_password | test3.cpp:144:16:144:29 | call to get_global_str |
| test3.cpp:129:39:129:47 | password1 | test3.cpp:138:24:138:32 | password1 |
| test3.cpp:132:8:132:15 | password | test3.cpp:134:11:134:18 | password |
| test3.cpp:134:11:134:18 | password | test3.cpp:112:20:112:25 | buffer |
| test3.cpp:138:21:138:22 | call to id | test3.cpp:140:15:140:17 | ptr |
| test3.cpp:138:24:138:32 | password1 | test3.cpp:117:28:117:33 | buffer |
| test3.cpp:138:24:138:32 | password1 | test3.cpp:138:21:138:22 | call to id |
| test3.cpp:144:16:144:29 | call to get_global_str | test3.cpp:146:15:146:18 | data |
| test3.cpp:152:29:152:36 | password | test3.cpp:159:15:159:20 | buffer |
| test3.cpp:171:8:171:15 | password | test3.cpp:173:15:173:22 | password |
| test3.cpp:171:8:171:15 | password | test3.cpp:175:3:175:17 | call to decrypt_inplace |
| test3.cpp:171:8:171:15 | password | test3.cpp:175:19:175:26 | password |
| test3.cpp:179:8:179:15 | password | test3.cpp:181:15:181:22 | password |
| test3.cpp:179:8:179:15 | password | test3.cpp:184:3:184:17 | call to decrypt_inplace |
| test3.cpp:179:8:179:15 | password | test3.cpp:184:19:184:26 | password |
| test3.cpp:188:8:188:15 | password | test3.cpp:191:15:191:22 | password |
| test3.cpp:188:8:188:15 | password | test3.cpp:193:18:193:28 | call to rtn_decrypt |
| test3.cpp:188:8:188:15 | password | test3.cpp:193:30:193:37 | password |
| test3.cpp:197:8:197:15 | password | test3.cpp:199:3:199:17 | call to encrypt_inplace |
| test3.cpp:197:8:197:15 | password | test3.cpp:199:19:199:26 | password |
| test3.cpp:197:8:197:15 | password | test3.cpp:201:15:201:22 | password |
| test3.cpp:205:8:205:15 | password | test3.cpp:207:3:207:17 | call to encrypt_inplace |
| test3.cpp:205:8:205:15 | password | test3.cpp:207:19:207:26 | password |
| test3.cpp:205:8:205:15 | password | test3.cpp:210:15:210:22 | password |
| test3.cpp:214:8:214:15 | password | test3.cpp:217:18:217:28 | call to rtn_encrypt |
| test3.cpp:214:8:214:15 | password | test3.cpp:217:18:217:28 | call to rtn_encrypt |
| test3.cpp:214:8:214:15 | password | test3.cpp:217:30:217:37 | password |
| test3.cpp:214:8:214:15 | password | test3.cpp:219:15:219:26 | password_ptr |
| test3.cpp:217:18:217:28 | call to rtn_encrypt | test3.cpp:219:15:219:26 | password_ptr |
| test3.cpp:225:34:225:41 | password | test3.cpp:227:22:227:29 | password |
| test3.cpp:225:34:225:41 | password | test3.cpp:228:26:228:33 | password |
| test3.cpp:239:7:239:14 | password | test3.cpp:241:8:241:15 | password |
| test3.cpp:239:7:239:14 | password | test3.cpp:242:8:242:15 | password |
| test3.cpp:252:8:252:16 | password1 | test3.cpp:254:15:254:23 | password1 |
| test3.cpp:252:8:252:16 | password1 | test3.cpp:256:3:256:19 | call to decrypt_to_buffer |
| test3.cpp:252:8:252:16 | password1 | test3.cpp:256:21:256:29 | password1 |
| test3.cpp:252:24:252:32 | password2 | test3.cpp:256:3:256:19 | call to decrypt_to_buffer |
| test3.cpp:252:24:252:32 | password2 | test3.cpp:256:32:256:40 | password2 |
| test3.cpp:260:8:260:16 | password1 | test3.cpp:262:3:262:19 | call to encrypt_to_buffer |
| test3.cpp:260:8:260:16 | password1 | test3.cpp:262:21:262:29 | password1 |
| test3.cpp:260:24:260:32 | password2 | test3.cpp:262:3:262:19 | call to encrypt_to_buffer |
| test3.cpp:260:24:260:32 | password2 | test3.cpp:262:32:262:40 | password2 |
| test3.cpp:260:24:260:32 | password2 | test3.cpp:264:15:264:23 | password2 |
| test3.cpp:268:19:268:26 | password | test3.cpp:272:15:272:18 | data |
| test3.cpp:278:20:278:23 | data | test3.cpp:278:20:278:23 | data |
| test3.cpp:278:20:278:23 | data | test3.cpp:280:14:280:17 | data |
| test3.cpp:283:20:283:23 | data | test3.cpp:283:20:283:23 | data |
| test3.cpp:283:20:283:23 | data | test3.cpp:285:14:285:17 | data |
| test3.cpp:288:20:288:23 | data | test3.cpp:290:14:290:17 | data |
| test3.cpp:293:20:293:23 | data | test3.cpp:293:20:293:23 | data |
| test3.cpp:293:20:293:23 | data | test3.cpp:295:14:295:17 | data |
| test3.cpp:298:20:298:23 | data | test3.cpp:300:14:300:17 | data |
| test3.cpp:308:41:308:49 | password1 | test3.cpp:312:3:312:17 | call to encrypt_inplace |
| test3.cpp:308:41:308:49 | password1 | test3.cpp:312:19:312:27 | password1 |
| test3.cpp:308:41:308:49 | password1 | test3.cpp:313:11:313:19 | password1 |
| test3.cpp:308:41:308:49 | password1 | test3.cpp:314:11:314:19 | password1 |
| test3.cpp:308:41:308:49 | password1 | test3.cpp:316:11:316:19 | password1 |
| test3.cpp:308:41:308:49 | password1 | test3.cpp:317:11:317:19 | password1 |
| test3.cpp:308:58:308:66 | password2 | test3.cpp:324:11:324:14 | data |
| test3.cpp:308:58:308:66 | password2 | test3.cpp:325:11:325:14 | data |
| test3.cpp:313:11:313:19 | password1 | test3.cpp:278:20:278:23 | data |
| test3.cpp:313:11:313:19 | password1 | test3.cpp:313:11:313:19 | ref arg password1 |
| test3.cpp:313:11:313:19 | ref arg password1 | test3.cpp:314:11:314:19 | password1 |
| test3.cpp:314:11:314:19 | password1 | test3.cpp:283:20:283:23 | data |
| test3.cpp:316:11:316:19 | password1 | test3.cpp:283:20:283:23 | data |
| test3.cpp:316:11:316:19 | password1 | test3.cpp:316:11:316:19 | ref arg password1 |
| test3.cpp:316:11:316:19 | ref arg password1 | test3.cpp:317:11:317:19 | password1 |
| test3.cpp:317:11:317:19 | password1 | test3.cpp:288:20:288:23 | data |
| test3.cpp:324:11:324:14 | data | test3.cpp:293:20:293:23 | data |
| test3.cpp:324:11:324:14 | data | test3.cpp:324:11:324:14 | ref arg data |
| test3.cpp:324:11:324:14 | ref arg data | test3.cpp:325:11:325:14 | data |
| test3.cpp:325:11:325:14 | data | test3.cpp:298:20:298:23 | data |
| test3.cpp:339:9:339:16 | password | test3.cpp:341:16:341:23 | password |
| test3.cpp:350:9:350:16 | password | test3.cpp:352:16:352:23 | password |
| test3.cpp:350:9:350:16 | password | test3.cpp:353:4:353:18 | call to decrypt_inplace |
| test3.cpp:350:9:350:16 | password | test3.cpp:353:20:353:27 | password |
| test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:21:48:27 | call to encrypt |
| test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:29:48:39 | thePassword |
| test.cpp:66:23:66:43 | cleartext password! | test.cpp:76:21:76:27 | call to encrypt |
| test.cpp:66:23:66:43 | cleartext password! | test.cpp:76:29:76:39 | thePassword |
| test3.cpp:68:21:68:29 | password1 | test3.cpp:70:15:70:17 | ptr |
| test3.cpp:75:15:75:22 | password | test3.cpp:77:15:77:17 | ptr |
| test3.cpp:106:20:106:25 | buffer | test3.cpp:108:14:108:19 | buffer |
| test3.cpp:111:28:111:33 | buffer | test3.cpp:113:9:113:14 | buffer |
| test3.cpp:120:9:120:23 | global_password | test3.cpp:138:16:138:29 | call to get_global_str |
| test3.cpp:128:11:128:18 | password | test3.cpp:106:20:106:25 | buffer |
| test3.cpp:132:21:132:22 | call to id | test3.cpp:134:15:134:17 | ptr |
| test3.cpp:132:24:132:32 | password1 | test3.cpp:111:28:111:33 | buffer |
| test3.cpp:132:24:132:32 | password1 | test3.cpp:132:21:132:22 | call to id |
| test3.cpp:138:16:138:29 | call to get_global_str | test3.cpp:140:15:140:18 | data |
| test3.cpp:151:19:151:26 | password | test3.cpp:153:15:153:20 | buffer |
nodes
| test3.cpp:17:28:17:36 | password1 | semmle.label | password1 |
| test3.cpp:17:51:17:59 | password2 | semmle.label | password2 |
| test3.cpp:22:15:22:23 | password1 | semmle.label | password1 |
| test3.cpp:26:15:26:23 | password2 | semmle.label | password2 |
| test3.cpp:45:8:45:15 | password | semmle.label | password |
| test3.cpp:47:15:47:22 | password | semmle.label | password |
| test3.cpp:53:8:53:15 | password | semmle.label | password |
| test3.cpp:55:15:55:22 | password | semmle.label | password |
| test3.cpp:71:32:71:40 | password1 | semmle.label | password1 |
| test3.cpp:76:15:76:17 | ptr | semmle.label | ptr |
| test3.cpp:80:8:80:15 | password | semmle.label | password |
| test3.cpp:83:15:83:17 | ptr | semmle.label | ptr |
| test3.cpp:98:8:98:15 | password | semmle.label | password |
| test3.cpp:101:12:101:19 | password | semmle.label | password |
| test3.cpp:112:20:112:25 | buffer | semmle.label | buffer |
| test3.cpp:114:14:114:19 | buffer | semmle.label | buffer |
| test3.cpp:117:28:117:33 | buffer | semmle.label | buffer |
| test3.cpp:119:9:119:14 | buffer | semmle.label | buffer |
| test3.cpp:126:9:126:23 | global_password | semmle.label | global_password |
| test3.cpp:129:39:129:47 | password1 | semmle.label | password1 |
| test3.cpp:132:8:132:15 | password | semmle.label | password |
| test3.cpp:134:11:134:18 | password | semmle.label | password |
| test3.cpp:138:21:138:22 | call to id | semmle.label | call to id |
| test3.cpp:138:24:138:32 | password1 | semmle.label | password1 |
| test3.cpp:140:15:140:17 | ptr | semmle.label | ptr |
| test3.cpp:144:16:144:29 | call to get_global_str | semmle.label | call to get_global_str |
| test3.cpp:146:15:146:18 | data | semmle.label | data |
| test3.cpp:152:29:152:36 | password | semmle.label | password |
| test3.cpp:159:15:159:20 | buffer | semmle.label | buffer |
| test3.cpp:171:8:171:15 | password | semmle.label | password |
| test3.cpp:173:15:173:22 | password | semmle.label | password |
| test3.cpp:175:3:175:17 | call to decrypt_inplace | semmle.label | call to decrypt_inplace |
| test3.cpp:175:19:175:26 | password | semmle.label | password |
| test3.cpp:179:8:179:15 | password | semmle.label | password |
| test3.cpp:181:15:181:22 | password | semmle.label | password |
| test3.cpp:184:3:184:17 | call to decrypt_inplace | semmle.label | call to decrypt_inplace |
| test3.cpp:184:19:184:26 | password | semmle.label | password |
| test3.cpp:188:8:188:15 | password | semmle.label | password |
| test3.cpp:191:15:191:22 | password | semmle.label | password |
| test3.cpp:193:18:193:28 | call to rtn_decrypt | semmle.label | call to rtn_decrypt |
| test3.cpp:193:30:193:37 | password | semmle.label | password |
| test3.cpp:197:8:197:15 | password | semmle.label | password |
| test3.cpp:199:3:199:17 | call to encrypt_inplace | semmle.label | call to encrypt_inplace |
| test3.cpp:199:19:199:26 | password | semmle.label | password |
| test3.cpp:201:15:201:22 | password | semmle.label | password |
| test3.cpp:205:8:205:15 | password | semmle.label | password |
| test3.cpp:207:3:207:17 | call to encrypt_inplace | semmle.label | call to encrypt_inplace |
| test3.cpp:207:19:207:26 | password | semmle.label | password |
| test3.cpp:210:15:210:22 | password | semmle.label | password |
| test3.cpp:214:8:214:15 | password | semmle.label | password |
| test3.cpp:217:18:217:28 | call to rtn_encrypt | semmle.label | call to rtn_encrypt |
| test3.cpp:217:18:217:28 | call to rtn_encrypt | semmle.label | call to rtn_encrypt |
| test3.cpp:217:30:217:37 | password | semmle.label | password |
| test3.cpp:219:15:219:26 | password_ptr | semmle.label | password_ptr |
| test3.cpp:225:34:225:41 | password | semmle.label | password |
| test3.cpp:227:22:227:29 | password | semmle.label | password |
| test3.cpp:228:26:228:33 | password | semmle.label | password |
| test3.cpp:239:7:239:14 | password | semmle.label | password |
| test3.cpp:241:8:241:15 | password | semmle.label | password |
| test3.cpp:242:8:242:15 | password | semmle.label | password |
| test3.cpp:252:8:252:16 | password1 | semmle.label | password1 |
| test3.cpp:252:24:252:32 | password2 | semmle.label | password2 |
| test3.cpp:254:15:254:23 | password1 | semmle.label | password1 |
| test3.cpp:256:3:256:19 | call to decrypt_to_buffer | semmle.label | call to decrypt_to_buffer |
| test3.cpp:256:21:256:29 | password1 | semmle.label | password1 |
| test3.cpp:256:32:256:40 | password2 | semmle.label | password2 |
| test3.cpp:260:8:260:16 | password1 | semmle.label | password1 |
| test3.cpp:260:24:260:32 | password2 | semmle.label | password2 |
| test3.cpp:262:3:262:19 | call to encrypt_to_buffer | semmle.label | call to encrypt_to_buffer |
| test3.cpp:262:21:262:29 | password1 | semmle.label | password1 |
| test3.cpp:262:32:262:40 | password2 | semmle.label | password2 |
| test3.cpp:264:15:264:23 | password2 | semmle.label | password2 |
| test3.cpp:268:19:268:26 | password | semmle.label | password |
| test3.cpp:272:15:272:18 | data | semmle.label | data |
| test3.cpp:278:20:278:23 | data | semmle.label | data |
| test3.cpp:278:20:278:23 | data | semmle.label | data |
| test3.cpp:280:14:280:17 | data | semmle.label | data |
| test3.cpp:283:20:283:23 | data | semmle.label | data |
| test3.cpp:283:20:283:23 | data | semmle.label | data |
| test3.cpp:285:14:285:17 | data | semmle.label | data |
| test3.cpp:288:20:288:23 | data | semmle.label | data |
| test3.cpp:290:14:290:17 | data | semmle.label | data |
| test3.cpp:293:20:293:23 | data | semmle.label | data |
| test3.cpp:293:20:293:23 | data | semmle.label | data |
| test3.cpp:295:14:295:17 | data | semmle.label | data |
| test3.cpp:298:20:298:23 | data | semmle.label | data |
| test3.cpp:300:14:300:17 | data | semmle.label | data |
| test3.cpp:308:41:308:49 | password1 | semmle.label | password1 |
| test3.cpp:308:58:308:66 | password2 | semmle.label | password2 |
| test3.cpp:312:3:312:17 | call to encrypt_inplace | semmle.label | call to encrypt_inplace |
| test3.cpp:312:19:312:27 | password1 | semmle.label | password1 |
| test3.cpp:313:11:313:19 | password1 | semmle.label | password1 |
| test3.cpp:313:11:313:19 | ref arg password1 | semmle.label | ref arg password1 |
| test3.cpp:314:11:314:19 | password1 | semmle.label | password1 |
| test3.cpp:316:11:316:19 | password1 | semmle.label | password1 |
| test3.cpp:316:11:316:19 | ref arg password1 | semmle.label | ref arg password1 |
| test3.cpp:317:11:317:19 | password1 | semmle.label | password1 |
| test3.cpp:324:11:324:14 | data | semmle.label | data |
| test3.cpp:324:11:324:14 | ref arg data | semmle.label | ref arg data |
| test3.cpp:325:11:325:14 | data | semmle.label | data |
| test3.cpp:339:9:339:16 | password | semmle.label | password |
| test3.cpp:341:16:341:23 | password | semmle.label | password |
| test3.cpp:350:9:350:16 | password | semmle.label | password |
| test3.cpp:352:16:352:23 | password | semmle.label | password |
| test3.cpp:353:4:353:18 | call to decrypt_inplace | semmle.label | call to decrypt_inplace |
| test3.cpp:353:20:353:27 | password | semmle.label | password |
| test.cpp:41:23:41:43 | cleartext password! | semmle.label | cleartext password! |
| test.cpp:48:21:48:27 | call to encrypt | semmle.label | call to encrypt |
| test.cpp:48:29:48:39 | thePassword | semmle.label | thePassword |
| test.cpp:66:23:66:43 | cleartext password! | semmle.label | cleartext password! |
| test.cpp:76:21:76:27 | call to encrypt | semmle.label | call to encrypt |
| test.cpp:76:29:76:39 | thePassword | semmle.label | thePassword |
| test3.cpp:20:15:20:23 | password1 | semmle.label | password1 |
| test3.cpp:24:15:24:23 | password2 | semmle.label | password2 |
| test3.cpp:41:15:41:22 | password | semmle.label | password |
| test3.cpp:49:15:49:22 | password | semmle.label | password |
| test3.cpp:68:21:68:29 | password1 | semmle.label | password1 |
| test3.cpp:70:15:70:17 | ptr | semmle.label | ptr |
| test3.cpp:75:15:75:22 | password | semmle.label | password |
| test3.cpp:77:15:77:17 | ptr | semmle.label | ptr |
| test3.cpp:95:12:95:19 | password | semmle.label | password |
| test3.cpp:106:20:106:25 | buffer | semmle.label | buffer |
| test3.cpp:108:14:108:19 | buffer | semmle.label | buffer |
| test3.cpp:111:28:111:33 | buffer | semmle.label | buffer |
| test3.cpp:113:9:113:14 | buffer | semmle.label | buffer |
| test3.cpp:120:9:120:23 | global_password | semmle.label | global_password |
| test3.cpp:128:11:128:18 | password | semmle.label | password |
| test3.cpp:132:21:132:22 | call to id | semmle.label | call to id |
| test3.cpp:132:24:132:32 | password1 | semmle.label | password1 |
| test3.cpp:134:15:134:17 | ptr | semmle.label | ptr |
| test3.cpp:138:16:138:29 | call to get_global_str | semmle.label | call to get_global_str |
| test3.cpp:140:15:140:18 | data | semmle.label | data |
| test3.cpp:151:19:151:26 | password | semmle.label | password |
| test3.cpp:153:15:153:20 | buffer | semmle.label | buffer |
subpaths
| test3.cpp:138:24:138:32 | password1 | test3.cpp:117:28:117:33 | buffer | test3.cpp:119:9:119:14 | buffer | test3.cpp:138:21:138:22 | call to id |
| test3.cpp:313:11:313:19 | password1 | test3.cpp:278:20:278:23 | data | test3.cpp:278:20:278:23 | data | test3.cpp:313:11:313:19 | ref arg password1 |
| test3.cpp:316:11:316:19 | password1 | test3.cpp:283:20:283:23 | data | test3.cpp:283:20:283:23 | data | test3.cpp:316:11:316:19 | ref arg password1 |
| test3.cpp:324:11:324:14 | data | test3.cpp:293:20:293:23 | data | test3.cpp:293:20:293:23 | data | test3.cpp:324:11:324:14 | ref arg data |
| test3.cpp:132:24:132:32 | password1 | test3.cpp:111:28:111:33 | buffer | test3.cpp:113:9:113:14 | buffer | test3.cpp:132:21:132:22 | call to id |
#select
| test3.cpp:22:3:22:6 | call to send | test3.cpp:17:28:17:36 | password1 | test3.cpp:22:15:22:23 | password1 | This operation transmits 'password1', which may contain unencrypted sensitive data from $@ | test3.cpp:17:28:17:36 | password1 | password1 |
| test3.cpp:26:3:26:6 | call to send | test3.cpp:17:51:17:59 | password2 | test3.cpp:26:15:26:23 | password2 | This operation transmits 'password2', which may contain unencrypted sensitive data from $@ | test3.cpp:17:51:17:59 | password2 | password2 |
| test3.cpp:47:3:47:6 | call to recv | test3.cpp:45:8:45:15 | password | test3.cpp:47:15:47:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:45:8:45:15 | password | password |
| test3.cpp:55:3:55:6 | call to recv | test3.cpp:53:8:53:15 | password | test3.cpp:55:15:55:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:53:8:53:15 | password | password |
| test3.cpp:76:3:76:6 | call to send | test3.cpp:71:32:71:40 | password1 | test3.cpp:76:15:76:17 | ptr | This operation transmits 'ptr', which may contain unencrypted sensitive data from $@ | test3.cpp:71:32:71:40 | password1 | password1 |
| test3.cpp:83:3:83:6 | call to recv | test3.cpp:80:8:80:15 | password | test3.cpp:83:15:83:17 | ptr | This operation receives into 'ptr', which may put unencrypted sensitive data into $@ | test3.cpp:80:8:80:15 | password | password |
| test3.cpp:101:3:101:6 | call to read | test3.cpp:98:8:98:15 | password | test3.cpp:101:12:101:19 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:98:8:98:15 | password | password |
| test3.cpp:114:2:114:5 | call to recv | test3.cpp:132:8:132:15 | password | test3.cpp:114:14:114:19 | buffer | This operation receives into 'buffer', which may put unencrypted sensitive data into $@ | test3.cpp:132:8:132:15 | password | password |
| test3.cpp:140:3:140:6 | call to send | test3.cpp:129:39:129:47 | password1 | test3.cpp:140:15:140:17 | ptr | This operation transmits 'ptr', which may contain unencrypted sensitive data from $@ | test3.cpp:129:39:129:47 | password1 | password1 |
| test3.cpp:146:3:146:6 | call to send | test3.cpp:126:9:126:23 | global_password | test3.cpp:146:15:146:18 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:126:9:126:23 | global_password | global_password |
| test3.cpp:159:3:159:6 | call to send | test3.cpp:152:29:152:36 | password | test3.cpp:159:15:159:20 | buffer | This operation transmits 'buffer', which may contain unencrypted sensitive data from $@ | test3.cpp:152:29:152:36 | password | password |
| test3.cpp:227:2:227:5 | call to send | test3.cpp:225:34:225:41 | password | test3.cpp:227:22:227:29 | password | This operation transmits 'password', which may contain unencrypted sensitive data from $@ | test3.cpp:225:34:225:41 | password | password |
| test3.cpp:228:2:228:5 | call to send | test3.cpp:225:34:225:41 | password | test3.cpp:228:26:228:33 | password | This operation transmits 'password', which may contain unencrypted sensitive data from $@ | test3.cpp:225:34:225:41 | password | password |
| test3.cpp:241:2:241:6 | call to fgets | test3.cpp:239:7:239:14 | password | test3.cpp:241:8:241:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:239:7:239:14 | password | password |
| test3.cpp:242:2:242:6 | call to fgets | test3.cpp:239:7:239:14 | password | test3.cpp:242:8:242:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:239:7:239:14 | password | password |
| test3.cpp:272:3:272:6 | call to send | test3.cpp:268:19:268:26 | password | test3.cpp:272:15:272:18 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:268:19:268:26 | password | password |
| test3.cpp:295:2:295:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:295:14:295:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 |
| test3.cpp:300:2:300:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:300:14:300:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 |
| test3.cpp:341:4:341:7 | call to recv | test3.cpp:339:9:339:16 | password | test3.cpp:341:16:341:23 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:339:9:339:16 | password | password |
| test3.cpp:20:3:20:6 | call to send | test3.cpp:20:15:20:23 | password1 | test3.cpp:20:15:20:23 | password1 | This operation transmits 'password1', which may contain unencrypted sensitive data from $@ | test3.cpp:20:15:20:23 | password1 | password1 |
| test3.cpp:24:3:24:6 | call to send | test3.cpp:24:15:24:23 | password2 | test3.cpp:24:15:24:23 | password2 | This operation transmits 'password2', which may contain unencrypted sensitive data from $@ | test3.cpp:24:15:24:23 | password2 | password2 |
| test3.cpp:41:3:41:6 | call to recv | test3.cpp:41:15:41:22 | password | test3.cpp:41:15:41:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:41:15:41:22 | password | password |
| test3.cpp:49:3:49:6 | call to recv | test3.cpp:49:15:49:22 | password | test3.cpp:49:15:49:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:49:15:49:22 | password | password |
| test3.cpp:70:3:70:6 | call to send | test3.cpp:68:21:68:29 | password1 | test3.cpp:70:15:70:17 | ptr | This operation transmits 'ptr', which may contain unencrypted sensitive data from $@ | test3.cpp:68:21:68:29 | password1 | password1 |
| test3.cpp:77:3:77:6 | call to recv | test3.cpp:75:15:75:22 | password | test3.cpp:77:15:77:17 | ptr | This operation receives into 'ptr', which may put unencrypted sensitive data into $@ | test3.cpp:75:15:75:22 | password | password |
| test3.cpp:95:3:95:6 | call to read | test3.cpp:95:12:95:19 | password | test3.cpp:95:12:95:19 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:95:12:95:19 | password | password |
| test3.cpp:108:2:108:5 | call to recv | test3.cpp:128:11:128:18 | password | test3.cpp:108:14:108:19 | buffer | This operation receives into 'buffer', which may put unencrypted sensitive data into $@ | test3.cpp:128:11:128:18 | password | password |
| test3.cpp:134:3:134:6 | call to send | test3.cpp:132:24:132:32 | password1 | test3.cpp:134:15:134:17 | ptr | This operation transmits 'ptr', which may contain unencrypted sensitive data from $@ | test3.cpp:132:24:132:32 | password1 | password1 |
| test3.cpp:140:3:140:6 | call to send | test3.cpp:120:9:120:23 | global_password | test3.cpp:140:15:140:18 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:120:9:120:23 | global_password | global_password |
| test3.cpp:153:3:153:6 | call to send | test3.cpp:151:19:151:26 | password | test3.cpp:153:15:153:20 | buffer | This operation transmits 'buffer', which may contain unencrypted sensitive data from $@ | test3.cpp:151:19:151:26 | password | password |

View File

@@ -1,8 +1,6 @@
typedef unsigned long size_t;
#define STDIN_FILENO (0)
#define STDOUT_FILENO (1)
int stdout_fileno = STDOUT_FILENO;
size_t strlen(const char *s);
@@ -33,10 +31,6 @@ void test_send(const char *password1, const char *password2, const char *passwor
{
send(val(), message, strlen(message), val()); // GOOD: `message` is not a password
}
{
send(stdout_fileno, password2, strlen(password2), val()); // GOOD: `password2` is sent to stdout, not a network socket (this may be an issue but is not within the scope of the `cpp/cleartext-transmission` query)
}
}
void test_receive()
@@ -131,7 +125,7 @@ void test_interprocedural(const char *password1)
{
char password[256];
my_recv(password, 256); // BAD: `password` is received plaintext [detected in `my_recv`]
my_recv(password, 256); // BAD: `password` is received plaintext [detected on line 108]
}
{
@@ -159,200 +153,3 @@ void test_taint(const char *password)
send(val(), buffer, 16, val()); // BAD: `password` is (partially) sent plaintext
}
}
void encrypt_inplace(char *buffer);
void decrypt_inplace(char *buffer);
char *rtn_encrypt(const char *buffer);
char *rtn_decrypt(const char *buffer);
void test_decrypt()
{
{
char password[256];
recv(val(), password, 256, val()); // GOOD: password is encrypted
decrypt_inplace(password); // proof that `password` was in fact encrypted
}
{
char password[256];
recv(val(), password, 256, val()); // GOOD: password is encrypted
password[255] = 0;
decrypt_inplace(password); // proof that `password` was in fact encrypted
}
{
char password[256];
char *password_ptr;
recv(val(), password, 256, val()); // GOOD: password is encrypted
password_ptr = rtn_decrypt(password); // proof that `password` was in fact encrypted
}
{
char password[256];
encrypt_inplace(password); // proof that `password` is in fact encrypted
send(val(), password, strlen(password), val()); // GOOD: password is encrypted
}
{
char password[256];
encrypt_inplace(password); // proof that `password` is in fact encrypted
password[255] = 0;
send(val(), password, strlen(password), val()); // GOOD: password is encrypted
}
{
char password[256];
char *password_ptr;
password_ptr = rtn_encrypt(password); // proof that `password` is in fact encrypted
send(val(), password_ptr, strlen(password_ptr), val()); // GOOD: password is encrypted
}
}
int get_socket(int from);
void test_more_stdio(const char *password)
{
send(get_socket(1), password, 128, val()); // GOOD: `getsocket(1)` is probably standard output [FALSE POSITIVE]
send(get_socket(val()), password, 128, val()); // BAD
}
typedef struct {} FILE;
char *fgets(char *s, int n, FILE *stream);
FILE *get_stdstream(int index);
#define STDIN_STREAM (get_stdstream(0))
void test_fgets(FILE *stream)
{
char password[128];
fgets(password, 128, stream); // BAD
fgets(password, 128, STDIN_STREAM); // GOOD: `STDIN_STREAM` is probably standard input [FALSE POSITIVE]
}
void encrypt_to_buffer(const char *input, char* output);
void decrypt_to_buffer(const char *input, char* output);
char *strcpy(char *s1, const char *s2);
void test_crypt_more()
{
{
char password1[256], password2[256];
recv(val(), password1, 256, val()); // GOOD: password is encrypted
decrypt_to_buffer(password1, password2); // proof that `password1` was in fact encrypted
}
{
char password1[256], password2[256];
encrypt_to_buffer(password1, password2); // proof that `password2` is in fact encrypted
send(val(), password2, strlen(password2), val()); // GOOD: password is encrypted
}
{
char data[256], password[256];
strcpy(data, password); // not proof of anything
send(val(), data, strlen(data), val()); // BAD: password is sent plaintext
}
}
bool cond();
void target1(char *data)
{
send(val(), data, strlen(data), val()); // GOOD: encrypted
}
void target2(char *data)
{
send(val(), data, strlen(data), val()); // BAD: from one source this is a plaintext password [NOT DETECTED]
}
void target3(char *data)
{
send(val(), data, strlen(data), val()); // BAD: data is a plaintext password [NOT DETECTED]
}
void target4(char *data)
{
send(val(), data, strlen(data), val()); // BAD: data is a plaintext password
}
void target5(char *data)
{
send(val(), data, strlen(data), val()); // BAD: from one source this is a plaintext password
}
void target6(char *data)
{
send(val(), data, strlen(data), val()); // GOOD: not a password
}
void test_multiple_sources_source(char *password1, char *password2)
{
if (cond())
{
encrypt_inplace(password1);
target1(password1);
target2(password1);
} else {
target2(password1);
target3(password1);
}
if (cond())
{
char *data = password2;
target4(data);
target5(data);
} else {
char *data = "harmless";
target5(data);
target6(data);
}
}
void test_loops()
{
{
while (cond())
{
char password[256];
recv(val(), password, 256, val()); // BAD: not encrypted
// ...
}
}
{
while (cond())
{
char password[256];
recv(val(), password, 256, val()); // GOOD: password is encrypted
decrypt_inplace(password); // proof that `password` was in fact encrypted
// ...
}
}
}

View File

@@ -1,54 +0,0 @@
import csharp
import cil
import semmle.code.csharp.dataflow.internal.DataFlowPrivate
import semmle.code.csharp.dataflow.internal.DataFlowPublic
import semmle.code.csharp.dataflow.internal.DataFlowImplConsistency::Consistency
private class MyConsistencyConfiguration extends ConsistencyConfiguration {
override predicate uniqueEnclosingCallableExclude(Node n) {
// TODO: Remove once static initializers are folded into the
// static constructors
exists(ControlFlow::Node cfn |
cfn.getElement() = any(FieldOrProperty f | f.isStatic()).getAChild+() and
cfn = n.getControlFlowNode()
)
}
override predicate uniqueNodeLocationExclude(Node n) {
// Methods with multiple implementations
n instanceof ParameterNode
or
this.missingLocationExclude(n)
}
override predicate missingLocationExclude(Node n) {
// Some CIL methods are missing locations
n.asParameter() instanceof CIL::Parameter
}
override predicate postWithInFlowExclude(Node n) {
n instanceof SummaryNode
or
n.asExpr().(ObjectCreation).hasInitializer()
}
override predicate argHasPostUpdateExclude(ArgumentNode n) {
n instanceof SummaryNode
or
n.asExpr().(Expr).stripCasts().getType() =
any(Type t |
not t instanceof RefType and
not t = any(TypeParameter tp | not tp.isValueType())
or
t instanceof NullType
)
or
n instanceof ImplicitCapturedArgumentNode
or
n instanceof ParamsArgumentNode
or
n.asExpr() instanceof CIL::Expr
}
override predicate reverseReadExclude(Node n) { n.asExpr() = any(AwaitExpr ae).getExpr() }
}

View File

@@ -89,7 +89,7 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN
override Location getLocation() { result = Element.super.getLocation() }
override Location getALocation() { cil_method_location(this.getUnboundMethod+(), result) }
override Location getALocation() { cil_method_location(this.getUnboundDeclaration(), result) }
override MethodParameter getParameter(int n) {
if this.isStatic()

View File

@@ -80,8 +80,7 @@ module Gvn {
LeafType() {
not this instanceof GenericType and
not this instanceof TypeParameter and
not this instanceof DynamicType and
not this instanceof TupleType
not this instanceof DynamicType
}
}
@@ -479,8 +478,6 @@ module Gvn {
GvnType getGlobalValueNumber(Type t) {
result = TLeafGvnType(t)
or
result = TLeafGvnType(t.(TupleType).getUnderlyingType())
or
t instanceof DynamicType and
result = TLeafGvnType(any(ObjectType ot))
or

View File

@@ -585,7 +585,7 @@ class IEnumerableFlow extends LibraryTypeDataFlow, RefType {
sink = getDelegateFlowSinkArg(m, 1, 1) and
sinkAp = AccessPath::empty()
or
source = getDelegateFlowSourceArg(m, 1) and
source = TCallableFlowSourceDelegateArg(1) and
sourceAp = AccessPath::empty() and
sink = TCallableFlowSinkReturn() and
sinkAp = AccessPath::empty()
@@ -603,7 +603,7 @@ class IEnumerableFlow extends LibraryTypeDataFlow, RefType {
sink = getDelegateFlowSinkArg(m, 2, 0) and
sinkAp = AccessPath::empty()
or
source = getDelegateFlowSourceArg(m, 2) and
source = TCallableFlowSourceDelegateArg(2) and
sourceAp = AccessPath::empty() and
sink = TCallableFlowSinkReturn() and
sinkAp = AccessPath::empty()
@@ -621,12 +621,12 @@ class IEnumerableFlow extends LibraryTypeDataFlow, RefType {
sink = getDelegateFlowSinkArg(m, 2, 0) and
sinkAp = AccessPath::empty()
or
source = getDelegateFlowSourceArg(m, 2) and
source = TCallableFlowSourceDelegateArg(2) and
sourceAp = AccessPath::empty() and
sink = getDelegateFlowSinkArg(m, 3, 0) and
sinkAp = AccessPath::empty()
or
source = getDelegateFlowSourceArg(m, 3) and
source = TCallableFlowSourceDelegateArg(3) and
sourceAp = AccessPath::empty() and
sink = TCallableFlowSinkReturn() and
sinkAp = AccessPath::empty()
@@ -841,7 +841,7 @@ class IEnumerableFlow extends LibraryTypeDataFlow, RefType {
sink = getDelegateFlowSinkArg(m, 4, 1) and
sinkAp = AccessPath::empty()
or
source = getDelegateFlowSourceArg(m, 4) and
source = TCallableFlowSourceDelegateArg(4) and
sourceAp = AccessPath::empty() and
sink = TCallableFlowSinkReturn() and
sinkAp = AccessPath::element()
@@ -924,7 +924,7 @@ class IEnumerableFlow extends LibraryTypeDataFlow, RefType {
sink = getDelegateFlowSinkArg(m, 1, 0) and
sinkAp = AccessPath::empty()
or
source = getDelegateFlowSourceArg(m, 1) and
source = TCallableFlowSourceDelegateArg(1) and
sourceAp = AccessPath::empty() and
sink = TCallableFlowSinkReturn() and
sinkAp = AccessPath::element()
@@ -943,12 +943,12 @@ class IEnumerableFlow extends LibraryTypeDataFlow, RefType {
sink = getDelegateFlowSinkArg(m, 2, 0) and
sinkAp = AccessPath::empty()
or
source = getDelegateFlowSourceArg(m, 1) and
source = TCallableFlowSourceDelegateArg(1) and
sourceAp = AccessPath::element() and
sink = getDelegateFlowSinkArg(m, 2, 1) and
sinkAp = AccessPath::empty()
or
source = getDelegateFlowSourceArg(m, 2) and
source = TCallableFlowSourceDelegateArg(2) and
sourceAp = AccessPath::empty() and
sink = TCallableFlowSinkReturn() and
sinkAp = AccessPath::element()

View File

@@ -15,23 +15,11 @@ module Consistency {
class ConsistencyConfiguration extends TConsistencyConfiguration {
string toString() { none() }
/** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */
predicate uniqueEnclosingCallableExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */
predicate uniqueNodeLocationExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `missingLocation`. */
predicate missingLocationExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `postWithInFlow`. */
predicate postWithInFlowExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `argHasPostUpdate`. */
predicate argHasPostUpdateExclude(ArgumentNode n) { none() }
/** Holds if `n` should be excluded from the consistency test `reverseRead`. */
predicate reverseReadExclude(Node n) { none() }
}
private class RelevantNode extends Node {
@@ -58,7 +46,6 @@ module Consistency {
n instanceof RelevantNode and
c = count(nodeGetEnclosingCallable(n)) and
c != 1 and
not any(ConsistencyConfiguration conf).uniqueEnclosingCallableExclude(n) and
msg = "Node should have one enclosing callable but has " + c + "."
)
}
@@ -79,7 +66,6 @@ module Consistency {
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
) and
c != 1 and
not any(ConsistencyConfiguration conf).uniqueNodeLocationExclude(n) and
msg = "Node should have one location but has " + c + "."
)
}
@@ -90,8 +76,7 @@ module Consistency {
strictcount(Node n |
not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
) and
not any(ConsistencyConfiguration conf).missingLocationExclude(n)
)
) and
msg = "Nodes without location: " + c
)
@@ -187,7 +172,6 @@ module Consistency {
query predicate reverseRead(Node n, string msg) {
exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and
not any(ConsistencyConfiguration conf).reverseReadExclude(n) and
msg = "Origin of readStep is missing a PostUpdateNode."
}

View File

@@ -65,9 +65,7 @@ abstract class NodeImpl extends Node {
private class ExprNodeImpl extends ExprNode, NodeImpl {
override DataFlowCallable getEnclosingCallableImpl() {
result = this.getExpr().(CIL::Expr).getEnclosingCallable()
or
result = this.getControlFlowNodeImpl().getEnclosingCallable()
result = this.getExpr().getEnclosingCallable()
}
override DotNet::Type getTypeImpl() {
@@ -620,7 +618,6 @@ private predicate arrayRead(Expr e1, ArrayRead e2) { e1 = e2.getQualifier() }
private Type getCSharpType(DotNet::Type t) {
result = t
or
not t instanceof Type and
result.matchesHandle(t)
}
@@ -691,7 +688,7 @@ private module Cached {
not def.(Ssa::ExplicitDefinition).getADefinition() instanceof
AssignableDefinitions::ImplicitParameterDefinition
} or
TExplicitParameterNode(DotNet::Parameter p) { p = any(DataFlowCallable c).getAParameter() } or
TExplicitParameterNode(DotNet::Parameter p) { p.isUnboundDeclaration() } or
TInstanceParameterNode(Callable c) {
c.isUnboundDeclaration() and not c.(Modifiable).isStatic()
} or
@@ -710,28 +707,25 @@ private module Cached {
TObjectInitializerNode(ControlFlow::Nodes::ElementNode cfn) {
cfn.getElement().(ObjectCreation).hasInitializer()
} or
TExprPostUpdateNode(ControlFlow::Nodes::ExprNode cfn) {
exists(Expr e | e = cfn.getExpr() |
exists(Type t | t = e.(Argument).stripCasts().getType() |
t instanceof RefType and
not t instanceof NullType
or
t = any(TypeParameter tp | not tp.isValueType())
)
TExprPostUpdateNode(ControlFlow::Nodes::ElementNode cfn) {
exists(Argument a, Type t |
a = cfn.getElement() and
t = a.stripCasts().getType()
|
t instanceof RefType and
not t instanceof NullType
or
fieldOrPropertyStore(_, _, _, e, true)
or
arrayStore(_, _, e, true)
or
// needed for reverse stores; e.g. `x.f1.f2 = y` induces
// a store step of `f1` into `x`
exists(TExprPostUpdateNode upd, Expr read |
upd = TExprPostUpdateNode(read.getAControlFlowNode())
|
fieldOrPropertyRead(e, _, read)
or
arrayRead(e, read)
)
t = any(TypeParameter tp | not tp.isValueType())
)
or
fieldOrPropertyStore(_, _, _, cfn.getElement(), true)
or
arrayStore(_, _, cfn.getElement(), true)
or
exists(TExprPostUpdateNode upd, FieldOrPropertyAccess fla |
upd = TExprPostUpdateNode(fla.getAControlFlowNode())
|
cfn.getElement() = fla.getQualifier()
)
} or
TSummaryNode(FlowSummary::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
@@ -1442,7 +1436,7 @@ private module OutNodes {
import OutNodes
/** A data-flow node used to model flow summaries. */
class SummaryNode extends NodeImpl, TSummaryNode {
private class SummaryNode extends NodeImpl, TSummaryNode {
private FlowSummary::SummarizedCallable c;
private FlowSummaryImpl::Private::SummaryNodeState state;

View File

@@ -75,7 +75,7 @@ class ExponentialRegexDataflow extends DataFlow2::Configuration {
/**
* An expression passed as the `input` to a call to a `Regex` method, where the regex appears to
* have exponential behavior.
* have exponential behaviour.
*/
class ExponentialRegexSink extends DataFlow::ExprNode, Sink {
ExponentialRegexSink() {

View File

@@ -20,7 +20,7 @@ class Parameter extends Variable, @dotnet_parameter {
/** Gets the position of this parameter, excluding the `this` parameter. */
int getPosition() { this = this.getDeclaringElement().getParameter(result) }
/** Gets the callable defining this parameter, if any. */
/** Gets the callable defining this parameter. */
Callable getCallable() { result = this.getDeclaringElement() }
/** Gets the declaring `Parameterizable`. */

View File

@@ -171,7 +171,6 @@ Python built-in support
Twisted, Web framework
Flask-Admin, Web framework
starlette, Asynchronous Server Gateway Interface (ASGI)
requests, HTTP client
dill, Serialization
PyYAML, Serialization
ruamel.yaml, Serialization

View File

@@ -130,7 +130,7 @@ private class NumberTaintPreservingCallable extends TaintPreservingCallable {
* included in this type however, then a tainted `Container` would imply that its `field` is also
* tainted (but not vice versa).
*
* Note that `TaintTracking::Configuration` applies this behavior by default to array, collection,
* Note that `TaintTracking::Configuration` applies this behaviour by default to array, collection,
* map-key and map-value content, so that e.g. a tainted `Map` is assumed to have tainted keys and values.
*/
abstract class TaintInheritingContent extends DataFlow::Content { }

View File

@@ -15,23 +15,11 @@ module Consistency {
class ConsistencyConfiguration extends TConsistencyConfiguration {
string toString() { none() }
/** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */
predicate uniqueEnclosingCallableExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */
predicate uniqueNodeLocationExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `missingLocation`. */
predicate missingLocationExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `postWithInFlow`. */
predicate postWithInFlowExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `argHasPostUpdate`. */
predicate argHasPostUpdateExclude(ArgumentNode n) { none() }
/** Holds if `n` should be excluded from the consistency test `reverseRead`. */
predicate reverseReadExclude(Node n) { none() }
}
private class RelevantNode extends Node {
@@ -58,7 +46,6 @@ module Consistency {
n instanceof RelevantNode and
c = count(nodeGetEnclosingCallable(n)) and
c != 1 and
not any(ConsistencyConfiguration conf).uniqueEnclosingCallableExclude(n) and
msg = "Node should have one enclosing callable but has " + c + "."
)
}
@@ -79,7 +66,6 @@ module Consistency {
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
) and
c != 1 and
not any(ConsistencyConfiguration conf).uniqueNodeLocationExclude(n) and
msg = "Node should have one location but has " + c + "."
)
}
@@ -90,8 +76,7 @@ module Consistency {
strictcount(Node n |
not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
) and
not any(ConsistencyConfiguration conf).missingLocationExclude(n)
)
) and
msg = "Nodes without location: " + c
)
@@ -187,7 +172,6 @@ module Consistency {
query predicate reverseRead(Node n, string msg) {
exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and
not any(ConsistencyConfiguration conf).reverseReadExclude(n) and
msg = "Origin of readStep is missing a PostUpdateNode."
}

View File

@@ -85,7 +85,7 @@ SupportMethod getASupportMethod() {
}
/**
* Returns a CSV specification of the taint-/value-propagation behavior of a test support method (`get` or `newWith` method).
* Returns a CSV specification of the taint-/value-propagation behaviour of a test support method (`get` or `newWith` method).
*/
query string getASupportMethodModel() { result = getASupportMethod().getCsvModel() }

View File

@@ -1,3 +0,0 @@
lgtm,codescanning
* Support for handlebars templates has improved. Raw interpolation tags of the form `{{& ... }}` are now recognized,
as well as whitespace-trimming tags like `{{~ ... }}`.

View File

@@ -43,7 +43,7 @@ public class Main {
* A version identifier that should be updated every time the extractor changes in such a way that
* it may produce different tuples for the same file under the same {@link ExtractorConfig}.
*/
public static final String EXTRACTOR_VERSION = "2021-12-17";
public static final String EXTRACTOR_VERSION = "2021-11-23";
public static final Pattern NEWLINE = Pattern.compile("\n");

View File

@@ -7,8 +7,8 @@ import com.semmle.util.locations.Position;
import com.semmle.util.trap.TrapWriter.Label;
public class TemplateEngines {
private static final String MUSTACHE_TAG_TRIPLE = "\\{\\{\\{[~]?(.*?)[~]?\\}\\}\\}"; // {{{ x }}}
private static final String MUSTACHE_TAG_DOUBLE = "\\{\\{(?!\\{)[~&]?(.*?)[~]?\\}\\}"; // {{ x }}}
private static final String MUSTACHE_TAG_TRIPLE = "\\{\\{\\{(.*?)\\}\\}\\}"; // {{{ x }}}
private static final String MUSTACHE_TAG_DOUBLE = "\\{\\{(?!\\{)(.*?)\\}\\}"; // {{ x }}}
private static final String MUSTACHE_TAG_PERCENT = "\\{%(?!>)(.*?)%\\}"; // {% x %}
private static final String EJS_TAG = "<%(?![%<>}])[-=]?(.*?)[_-]?%>"; // <% x %>
@@ -22,7 +22,7 @@ public class TemplateEngines {
public static final Pattern TEMPLATE_TAGS =
Pattern.compile(
StringUtil.glue(
"|", MUSTACHE_TAG_DOUBLE, MUSTACHE_TAG_TRIPLE, MUSTACHE_TAG_PERCENT, EJS_TAG),
"|", TemplateEngines.MUSTACHE_TAG_DOUBLE, MUSTACHE_TAG_TRIPLE, MUSTACHE_TAG_PERCENT, EJS_TAG),
Pattern.DOTALL);
/**

View File

@@ -178,7 +178,7 @@ module Raw {
/**
* Returns a generated name for the entity. This name is generated such that
* entities with the same names have similar behavior.
* entities with the same names have similar behaviour.
*/
private string getApproximateNameForEntity(Entity entity) {
count(raw::DataFlow::CallNode call, int index | entityUsedAsArgumentToCall(entity, call, index)) =

View File

@@ -283,7 +283,7 @@ private module AccessPaths {
}
/** Get a name of a supported generic token-based feature. */
private string getASupportedFeatureName() {
string getASupportedFeatureName() {
result =
[
"enclosingFunctionName", "calleeName", "receiverName", "argumentIndex", "calleeApiName",
@@ -300,12 +300,5 @@ private string getASupportedFeatureName() {
predicate tokenFeatures(DataFlow::Node endpoint, string featureName, string featureValue) {
// Performance optimization: Restrict feature extraction to endpoints we've explicitly asked to featurize.
endpoint = any(FeaturizationConfig cfg).getAnEndpointToFeaturize() and
(
if strictcount(getTokenFeature(endpoint, featureName)) = 1
then featureValue = getTokenFeature(endpoint, featureName)
else (
// Performance note: this is a Cartesian product between all endpoints and feature names.
featureValue = "" and featureName = getASupportedFeatureName()
)
)
featureValue = getTokenFeature(endpoint, featureName)
}

View File

@@ -87,23 +87,19 @@ module ModelScoring {
class RelevantFeaturizationConfig extends EndpointFeatures::FeaturizationConfig {
RelevantFeaturizationConfig() { this = "RelevantFeaturization" }
override DataFlow::Node getAnEndpointToFeaturize() {
getCfg().isEffectiveSource(result) and any(DataFlow::Configuration cfg).hasFlow(result, _)
override DataFlow::Node getAnEndpointToFeaturize() { getCfg().isEffectiveSource(result) and any(DataFlow::Configuration cfg).hasFlow(result, _)
or
getCfg().isEffectiveSink(result) and any(DataFlow::Configuration cfg).hasFlow(_, result)
}
getCfg().isEffectiveSink(result) and any(DataFlow::Configuration cfg).hasFlow(_, result) }
}
DataFlow::Node getARequestedEndpoint() {
result = any(EndpointFeatures::FeaturizationConfig cfg).getAnEndpointToFeaturize()
}
DataFlow::Node getARequestedEndpoint() { result = any(EndpointFeatures::FeaturizationConfig cfg).getAnEndpointToFeaturize() }
private int getARequestedEndpointType() { result = any(EndpointType type).getEncoding() }
predicate endpointScores(DataFlow::Node endpoint, int encodedEndpointType, float score) =
scoreEndpoints(getARequestedEndpoint/0, getARequestedEndpointType/0,
EndpointFeatures::tokenFeatures/3, getACompatibleModelChecksum/0)(endpoint,
encodedEndpointType, score)
scoreEndpoints(getARequestedEndpoint/0, EndpointFeatures::tokenFeatures/3,
EndpointFeatures::getASupportedFeatureName/0, getARequestedEndpointType/0,
getACompatibleModelChecksum/0)(endpoint, encodedEndpointType, score)
}
/**

View File

@@ -22,7 +22,7 @@
* value `nonzero`;
*
* - at other times, the analysis does not have enough information
* to precisely model the behavior of certain program elements:
* to precisely model the behaviour of certain program elements:
* for example, the current flow analysis is intra-procedural,
* so it does not model parameter passing or return values, and
* hence has to make worst-case assumptions about the possible

View File

@@ -1035,7 +1035,7 @@ module DataFlow {
* Provides classes representing various kinds of calls.
*
* Subclass the classes in this module to introduce new kinds of calls. If you want to
* refine the behavior of the analysis on existing kinds of calls, subclass `InvokeNode`
* refine the behaviour of the analysis on existing kinds of calls, subclass `InvokeNode`
* instead.
*/
module Impl {

View File

@@ -551,11 +551,9 @@ module Templating {
private class MustacheStyleSyntax extends TemplateSyntax {
MustacheStyleSyntax() { this = "mustache" }
override string getRawInterpolationRegexp() {
result = "(?s)\\{\\{\\{(.*?)\\}\\}\\}|\\{\\{&(.*?)\\}\\}"
}
override string getRawInterpolationRegexp() { result = "(?s)\\{\\{\\{(.*?)\\}\\}\\}" }
override string getEscapingInterpolationRegexp() { result = "(?s)\\{\\{[^{&](.*?)\\}\\}" }
override string getEscapingInterpolationRegexp() { result = "(?s)\\{\\{[^{](.*?)\\}\\}" }
override string getAFileExtension() { result = ["hbs", "njk"] }

View File

@@ -3,7 +3,7 @@ import javascript
/**
* INTERNAL: Do not use in ordinary queries.
*
* Extraction metrics for profiling extraction behaviors.
* Extraction metrics for profiling extraction behaviours.
*/
module ExtractionMetrics {
/**

View File

@@ -1,7 +1,7 @@
/**
* @name Missing `MessageEvent.origin` verification in `postMessage` handlers
* @description Missing the `MessageEvent.origin` verification in `postMessage` handlers, allows any windows to send arbitrary data to the `MessageEvent` listener.
* This could lead to unexpected behavior, especially when `MessageEvent.data` is used in an unsafe way.
* This could lead to unexpected behaviour, especially when `MessageEvent.data` is used in an unsafe way.
* @kind problem
* @problem.severity warning
* @precision high

View File

@@ -48,15 +48,15 @@ nodes
| views/ejs_sinks.ejs:21:39:21:69 | <%= dataInEventHandlerString %> |
| views/ejs_sinks.ejs:21:39:21:69 | <%= dataInEventHandlerString %> |
| views/ejs_sinks.ejs:21:43:21:66 | dataInE ... rString |
| views/hbs_sinks.hbs:25:39:25:63 | {{ dataInGeneratedCode }} |
| views/hbs_sinks.hbs:25:39:25:63 | {{ dataInGeneratedCode }} |
| views/hbs_sinks.hbs:25:42:25:60 | dataInGeneratedCode |
| views/hbs_sinks.hbs:28:19:28:38 | {{ backslashSink1 }} |
| views/hbs_sinks.hbs:28:19:28:38 | {{ backslashSink1 }} |
| views/hbs_sinks.hbs:28:22:28:35 | backslashSink1 |
| views/hbs_sinks.hbs:33:39:33:68 | {{ dataInEventHandlerString }} |
| views/hbs_sinks.hbs:33:39:33:68 | {{ dataInEventHandlerString }} |
| views/hbs_sinks.hbs:33:42:33:65 | dataInE ... rString |
| views/hbs_sinks.hbs:13:39:13:63 | {{ dataInGeneratedCode }} |
| views/hbs_sinks.hbs:13:39:13:63 | {{ dataInGeneratedCode }} |
| views/hbs_sinks.hbs:13:42:13:60 | dataInGeneratedCode |
| views/hbs_sinks.hbs:16:19:16:38 | {{ backslashSink1 }} |
| views/hbs_sinks.hbs:16:19:16:38 | {{ backslashSink1 }} |
| views/hbs_sinks.hbs:16:22:16:35 | backslashSink1 |
| views/hbs_sinks.hbs:21:39:21:68 | {{ dataInEventHandlerString }} |
| views/hbs_sinks.hbs:21:39:21:68 | {{ dataInEventHandlerString }} |
| views/hbs_sinks.hbs:21:42:21:65 | dataInE ... rString |
| views/njk_sinks.njk:13:39:13:63 | {{ dataInGeneratedCode }} |
| views/njk_sinks.njk:13:39:13:63 | {{ dataInGeneratedCode }} |
| views/njk_sinks.njk:13:42:13:60 | dataInGeneratedCode |
@@ -86,12 +86,12 @@ edges
| app.js:17:25:17:48 | req.que ... shSink1 | views/ejs_sinks.ejs:16:23:16:36 | backslashSink1 |
| app.js:19:35:19:68 | req.que ... rString | views/ejs_sinks.ejs:21:43:21:66 | dataInE ... rString |
| app.js:19:35:19:68 | req.que ... rString | views/ejs_sinks.ejs:21:43:21:66 | dataInE ... rString |
| app.js:34:30:34:58 | req.que ... tedCode | views/hbs_sinks.hbs:25:42:25:60 | dataInGeneratedCode |
| app.js:34:30:34:58 | req.que ... tedCode | views/hbs_sinks.hbs:25:42:25:60 | dataInGeneratedCode |
| app.js:36:25:36:48 | req.que ... shSink1 | views/hbs_sinks.hbs:28:22:28:35 | backslashSink1 |
| app.js:36:25:36:48 | req.que ... shSink1 | views/hbs_sinks.hbs:28:22:28:35 | backslashSink1 |
| app.js:38:35:38:68 | req.que ... rString | views/hbs_sinks.hbs:33:42:33:65 | dataInE ... rString |
| app.js:38:35:38:68 | req.que ... rString | views/hbs_sinks.hbs:33:42:33:65 | dataInE ... rString |
| app.js:34:30:34:58 | req.que ... tedCode | views/hbs_sinks.hbs:13:42:13:60 | dataInGeneratedCode |
| app.js:34:30:34:58 | req.que ... tedCode | views/hbs_sinks.hbs:13:42:13:60 | dataInGeneratedCode |
| app.js:36:25:36:48 | req.que ... shSink1 | views/hbs_sinks.hbs:16:22:16:35 | backslashSink1 |
| app.js:36:25:36:48 | req.que ... shSink1 | views/hbs_sinks.hbs:16:22:16:35 | backslashSink1 |
| app.js:38:35:38:68 | req.que ... rString | views/hbs_sinks.hbs:21:42:21:65 | dataInE ... rString |
| app.js:38:35:38:68 | req.que ... rString | views/hbs_sinks.hbs:21:42:21:65 | dataInE ... rString |
| app.js:53:30:53:58 | req.que ... tedCode | views/njk_sinks.njk:13:42:13:60 | dataInGeneratedCode |
| app.js:53:30:53:58 | req.que ... tedCode | views/njk_sinks.njk:13:42:13:60 | dataInGeneratedCode |
| app.js:54:33:54:64 | req.que ... CodeRaw | views/njk_sinks.njk:14:45:14:66 | dataInG ... CodeRaw |
@@ -126,12 +126,12 @@ edges
| views/ejs_sinks.ejs:16:23:16:36 | backslashSink1 | views/ejs_sinks.ejs:16:19:16:39 | <%= backslashSink1 %> |
| views/ejs_sinks.ejs:21:43:21:66 | dataInE ... rString | views/ejs_sinks.ejs:21:39:21:69 | <%= dataInEventHandlerString %> |
| views/ejs_sinks.ejs:21:43:21:66 | dataInE ... rString | views/ejs_sinks.ejs:21:39:21:69 | <%= dataInEventHandlerString %> |
| views/hbs_sinks.hbs:25:42:25:60 | dataInGeneratedCode | views/hbs_sinks.hbs:25:39:25:63 | {{ dataInGeneratedCode }} |
| views/hbs_sinks.hbs:25:42:25:60 | dataInGeneratedCode | views/hbs_sinks.hbs:25:39:25:63 | {{ dataInGeneratedCode }} |
| views/hbs_sinks.hbs:28:22:28:35 | backslashSink1 | views/hbs_sinks.hbs:28:19:28:38 | {{ backslashSink1 }} |
| views/hbs_sinks.hbs:28:22:28:35 | backslashSink1 | views/hbs_sinks.hbs:28:19:28:38 | {{ backslashSink1 }} |
| views/hbs_sinks.hbs:33:42:33:65 | dataInE ... rString | views/hbs_sinks.hbs:33:39:33:68 | {{ dataInEventHandlerString }} |
| views/hbs_sinks.hbs:33:42:33:65 | dataInE ... rString | views/hbs_sinks.hbs:33:39:33:68 | {{ dataInEventHandlerString }} |
| views/hbs_sinks.hbs:13:42:13:60 | dataInGeneratedCode | views/hbs_sinks.hbs:13:39:13:63 | {{ dataInGeneratedCode }} |
| views/hbs_sinks.hbs:13:42:13:60 | dataInGeneratedCode | views/hbs_sinks.hbs:13:39:13:63 | {{ dataInGeneratedCode }} |
| views/hbs_sinks.hbs:16:22:16:35 | backslashSink1 | views/hbs_sinks.hbs:16:19:16:38 | {{ backslashSink1 }} |
| views/hbs_sinks.hbs:16:22:16:35 | backslashSink1 | views/hbs_sinks.hbs:16:19:16:38 | {{ backslashSink1 }} |
| views/hbs_sinks.hbs:21:42:21:65 | dataInE ... rString | views/hbs_sinks.hbs:21:39:21:68 | {{ dataInEventHandlerString }} |
| views/hbs_sinks.hbs:21:42:21:65 | dataInE ... rString | views/hbs_sinks.hbs:21:39:21:68 | {{ dataInEventHandlerString }} |
| views/njk_sinks.njk:13:42:13:60 | dataInGeneratedCode | views/njk_sinks.njk:13:39:13:63 | {{ dataInGeneratedCode }} |
| views/njk_sinks.njk:13:42:13:60 | dataInGeneratedCode | views/njk_sinks.njk:13:39:13:63 | {{ dataInGeneratedCode }} |
| views/njk_sinks.njk:14:45:14:66 | dataInG ... CodeRaw | views/njk_sinks.njk:14:45:14:73 | dataInG ... \| safe |
@@ -156,9 +156,9 @@ edges
| views/ejs_sinks.ejs:13:39:13:64 | <%= dataInGeneratedCode %> | app.js:15:30:15:58 | req.que ... tedCode | views/ejs_sinks.ejs:13:39:13:64 | <%= dataInGeneratedCode %> | $@ flows to here and is interpreted as code. | app.js:15:30:15:58 | req.que ... tedCode | User-provided value |
| views/ejs_sinks.ejs:16:19:16:39 | <%= backslashSink1 %> | app.js:17:25:17:48 | req.que ... shSink1 | views/ejs_sinks.ejs:16:19:16:39 | <%= backslashSink1 %> | $@ flows to here and is interpreted as code. | app.js:17:25:17:48 | req.que ... shSink1 | User-provided value |
| views/ejs_sinks.ejs:21:39:21:69 | <%= dataInEventHandlerString %> | app.js:19:35:19:68 | req.que ... rString | views/ejs_sinks.ejs:21:39:21:69 | <%= dataInEventHandlerString %> | $@ flows to here and is interpreted as code. | app.js:19:35:19:68 | req.que ... rString | User-provided value |
| views/hbs_sinks.hbs:25:39:25:63 | {{ dataInGeneratedCode }} | app.js:34:30:34:58 | req.que ... tedCode | views/hbs_sinks.hbs:25:39:25:63 | {{ dataInGeneratedCode }} | $@ flows to here and is interpreted as code. | app.js:34:30:34:58 | req.que ... tedCode | User-provided value |
| views/hbs_sinks.hbs:28:19:28:38 | {{ backslashSink1 }} | app.js:36:25:36:48 | req.que ... shSink1 | views/hbs_sinks.hbs:28:19:28:38 | {{ backslashSink1 }} | $@ flows to here and is interpreted as code. | app.js:36:25:36:48 | req.que ... shSink1 | User-provided value |
| views/hbs_sinks.hbs:33:39:33:68 | {{ dataInEventHandlerString }} | app.js:38:35:38:68 | req.que ... rString | views/hbs_sinks.hbs:33:39:33:68 | {{ dataInEventHandlerString }} | $@ flows to here and is interpreted as code. | app.js:38:35:38:68 | req.que ... rString | User-provided value |
| views/hbs_sinks.hbs:13:39:13:63 | {{ dataInGeneratedCode }} | app.js:34:30:34:58 | req.que ... tedCode | views/hbs_sinks.hbs:13:39:13:63 | {{ dataInGeneratedCode }} | $@ flows to here and is interpreted as code. | app.js:34:30:34:58 | req.que ... tedCode | User-provided value |
| views/hbs_sinks.hbs:16:19:16:38 | {{ backslashSink1 }} | app.js:36:25:36:48 | req.que ... shSink1 | views/hbs_sinks.hbs:16:19:16:38 | {{ backslashSink1 }} | $@ flows to here and is interpreted as code. | app.js:36:25:36:48 | req.que ... shSink1 | User-provided value |
| views/hbs_sinks.hbs:21:39:21:68 | {{ dataInEventHandlerString }} | app.js:38:35:38:68 | req.que ... rString | views/hbs_sinks.hbs:21:39:21:68 | {{ dataInEventHandlerString }} | $@ flows to here and is interpreted as code. | app.js:38:35:38:68 | req.que ... rString | User-provided value |
| views/njk_sinks.njk:13:39:13:63 | {{ dataInGeneratedCode }} | app.js:53:30:53:58 | req.que ... tedCode | views/njk_sinks.njk:13:39:13:63 | {{ dataInGeneratedCode }} | $@ flows to here and is interpreted as code. | app.js:53:30:53:58 | req.que ... tedCode | User-provided value |
| views/njk_sinks.njk:14:42:14:76 | {{ dataInGeneratedCodeRaw \| safe }} | app.js:54:33:54:64 | req.que ... CodeRaw | views/njk_sinks.njk:14:42:14:76 | {{ dataInGeneratedCodeRaw \| safe }} | $@ flows to here and is interpreted as code. | app.js:54:33:54:64 | req.que ... CodeRaw | User-provided value |
| views/njk_sinks.njk:15:46:15:91 | {{ dataInGeneratedCodeJsonRaw \| json \| safe }} | app.js:55:37:55:72 | req.que ... JsonRaw | views/njk_sinks.njk:15:46:15:91 | {{ dataInGeneratedCodeJsonRaw \| json \| safe }} | $@ flows to here and is interpreted as code. | app.js:55:37:55:72 | req.que ... JsonRaw | User-provided value |

View File

@@ -114,36 +114,21 @@ nodes
| views/ejs_sinks.ejs:22:39:22:72 | <%- dataInEventHandlerStringRaw %> |
| views/ejs_sinks.ejs:22:43:22:69 | dataInE ... ringRaw |
| views/ejs_sinks.ejs:24:44:24:50 | rawHtml |
| views/hbs_sinks.hbs:9:9:9:23 | {{{ rawHtml }}} |
| views/hbs_sinks.hbs:9:9:9:23 | {{{ rawHtml }}} |
| views/hbs_sinks.hbs:9:13:9:19 | rawHtml |
| views/hbs_sinks.hbs:10:9:10:23 | {{{~rawHtml }}} |
| views/hbs_sinks.hbs:10:9:10:23 | {{{~rawHtml }}} |
| views/hbs_sinks.hbs:10:13:10:19 | rawHtml |
| views/hbs_sinks.hbs:11:9:11:23 | {{{ rawHtml~}}} |
| views/hbs_sinks.hbs:11:9:11:23 | {{{ rawHtml~}}} |
| views/hbs_sinks.hbs:11:13:11:19 | rawHtml |
| views/hbs_sinks.hbs:12:9:12:23 | {{{~rawHtml~}}} |
| views/hbs_sinks.hbs:12:9:12:23 | {{{~rawHtml~}}} |
| views/hbs_sinks.hbs:12:13:12:19 | rawHtml |
| views/hbs_sinks.hbs:13:9:13:25 | {{{~ rawHtml ~}}} |
| views/hbs_sinks.hbs:13:9:13:25 | {{{~ rawHtml ~}}} |
| views/hbs_sinks.hbs:13:14:13:20 | rawHtml |
| views/hbs_sinks.hbs:15:9:15:22 | {{& rawHtml }} |
| views/hbs_sinks.hbs:15:9:15:22 | {{& rawHtml }} |
| views/hbs_sinks.hbs:15:13:15:19 | rawHtml |
| views/hbs_sinks.hbs:19:9:19:34 | {{{ object.rawHtmlProp }}} |
| views/hbs_sinks.hbs:19:9:19:34 | {{{ object.rawHtmlProp }}} |
| views/hbs_sinks.hbs:19:13:19:30 | object.rawHtmlProp |
| views/hbs_sinks.hbs:23:43:23:72 | {{{ dataInStringLiteralRaw }}} |
| views/hbs_sinks.hbs:23:43:23:72 | {{{ dataInStringLiteralRaw }}} |
| views/hbs_sinks.hbs:23:47:23:68 | dataInS ... eralRaw |
| views/hbs_sinks.hbs:26:42:26:71 | {{{ dataInGeneratedCodeRaw }}} |
| views/hbs_sinks.hbs:26:42:26:71 | {{{ dataInGeneratedCodeRaw }}} |
| views/hbs_sinks.hbs:26:46:26:67 | dataInG ... CodeRaw |
| views/hbs_sinks.hbs:34:39:34:73 | {{{ dataInEventHandlerStringRaw }}} |
| views/hbs_sinks.hbs:34:39:34:73 | {{{ dataInEventHandlerStringRaw }}} |
| views/hbs_sinks.hbs:34:43:34:69 | dataInE ... ringRaw |
| views/hbs_sinks.hbs:4:9:4:23 | {{{ rawHtml }}} |
| views/hbs_sinks.hbs:4:9:4:23 | {{{ rawHtml }}} |
| views/hbs_sinks.hbs:4:13:4:19 | rawHtml |
| views/hbs_sinks.hbs:7:9:7:34 | {{{ object.rawHtmlProp }}} |
| views/hbs_sinks.hbs:7:9:7:34 | {{{ object.rawHtmlProp }}} |
| views/hbs_sinks.hbs:7:13:7:30 | object.rawHtmlProp |
| views/hbs_sinks.hbs:11:43:11:72 | {{{ dataInStringLiteralRaw }}} |
| views/hbs_sinks.hbs:11:43:11:72 | {{{ dataInStringLiteralRaw }}} |
| views/hbs_sinks.hbs:11:47:11:68 | dataInS ... eralRaw |
| views/hbs_sinks.hbs:14:42:14:71 | {{{ dataInGeneratedCodeRaw }}} |
| views/hbs_sinks.hbs:14:42:14:71 | {{{ dataInGeneratedCodeRaw }}} |
| views/hbs_sinks.hbs:14:46:14:67 | dataInG ... CodeRaw |
| views/hbs_sinks.hbs:22:39:22:73 | {{{ dataInEventHandlerStringRaw }}} |
| views/hbs_sinks.hbs:22:39:22:73 | {{{ dataInEventHandlerStringRaw }}} |
| views/hbs_sinks.hbs:22:43:22:69 | dataInE ... ringRaw |
| views/njk_sinks.njk:4:12:4:18 | rawHtml |
| views/njk_sinks.njk:4:12:4:18 | rawHtml |
| views/njk_sinks.njk:7:12:7:29 | object.rawHtmlProp |
@@ -172,26 +157,16 @@ edges
| app.js:16:33:16:64 | req.que ... CodeRaw | views/ejs_sinks.ejs:14:46:14:67 | dataInG ... CodeRaw |
| app.js:20:38:20:74 | req.que ... ringRaw | views/ejs_sinks.ejs:22:43:22:69 | dataInE ... ringRaw |
| app.js:20:38:20:74 | req.que ... ringRaw | views/ejs_sinks.ejs:22:43:22:69 | dataInE ... ringRaw |
| app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:9:13:9:19 | rawHtml |
| app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:9:13:9:19 | rawHtml |
| app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:10:13:10:19 | rawHtml |
| app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:10:13:10:19 | rawHtml |
| app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:11:13:11:19 | rawHtml |
| app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:11:13:11:19 | rawHtml |
| app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:12:13:12:19 | rawHtml |
| app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:12:13:12:19 | rawHtml |
| app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:13:14:13:20 | rawHtml |
| app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:13:14:13:20 | rawHtml |
| app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:15:13:15:19 | rawHtml |
| app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:15:13:15:19 | rawHtml |
| app.js:30:26:30:46 | req.que ... tmlProp | views/hbs_sinks.hbs:19:13:19:30 | object.rawHtmlProp |
| app.js:30:26:30:46 | req.que ... tmlProp | views/hbs_sinks.hbs:19:13:19:30 | object.rawHtmlProp |
| app.js:33:33:33:64 | req.que ... eralRaw | views/hbs_sinks.hbs:23:47:23:68 | dataInS ... eralRaw |
| app.js:33:33:33:64 | req.que ... eralRaw | views/hbs_sinks.hbs:23:47:23:68 | dataInS ... eralRaw |
| app.js:35:33:35:64 | req.que ... CodeRaw | views/hbs_sinks.hbs:26:46:26:67 | dataInG ... CodeRaw |
| app.js:35:33:35:64 | req.que ... CodeRaw | views/hbs_sinks.hbs:26:46:26:67 | dataInG ... CodeRaw |
| app.js:39:38:39:74 | req.que ... ringRaw | views/hbs_sinks.hbs:34:43:34:69 | dataInE ... ringRaw |
| app.js:39:38:39:74 | req.que ... ringRaw | views/hbs_sinks.hbs:34:43:34:69 | dataInE ... ringRaw |
| app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:4:13:4:19 | rawHtml |
| app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:4:13:4:19 | rawHtml |
| app.js:30:26:30:46 | req.que ... tmlProp | views/hbs_sinks.hbs:7:13:7:30 | object.rawHtmlProp |
| app.js:30:26:30:46 | req.que ... tmlProp | views/hbs_sinks.hbs:7:13:7:30 | object.rawHtmlProp |
| app.js:33:33:33:64 | req.que ... eralRaw | views/hbs_sinks.hbs:11:47:11:68 | dataInS ... eralRaw |
| app.js:33:33:33:64 | req.que ... eralRaw | views/hbs_sinks.hbs:11:47:11:68 | dataInS ... eralRaw |
| app.js:35:33:35:64 | req.que ... CodeRaw | views/hbs_sinks.hbs:14:46:14:67 | dataInG ... CodeRaw |
| app.js:35:33:35:64 | req.que ... CodeRaw | views/hbs_sinks.hbs:14:46:14:67 | dataInG ... CodeRaw |
| app.js:39:38:39:74 | req.que ... ringRaw | views/hbs_sinks.hbs:22:43:22:69 | dataInE ... ringRaw |
| app.js:39:38:39:74 | req.que ... ringRaw | views/hbs_sinks.hbs:22:43:22:69 | dataInE ... ringRaw |
| app.js:46:18:46:34 | req.query.rawHtml | views/njk_sinks.njk:4:12:4:18 | rawHtml |
| app.js:46:18:46:34 | req.query.rawHtml | views/njk_sinks.njk:4:12:4:18 | rawHtml |
| app.js:46:18:46:34 | req.query.rawHtml | views/njk_sinks.njk:4:12:4:18 | rawHtml |
@@ -281,26 +256,16 @@ edges
| views/ejs_sinks.ejs:22:43:22:69 | dataInE ... ringRaw | views/ejs_sinks.ejs:22:39:22:72 | <%- dataInEventHandlerStringRaw %> |
| views/ejs_sinks.ejs:22:43:22:69 | dataInE ... ringRaw | views/ejs_sinks.ejs:22:39:22:72 | <%- dataInEventHandlerStringRaw %> |
| views/ejs_sinks.ejs:24:44:24:50 | rawHtml | views/ejs_include1.ejs:1:5:1:7 | foo |
| views/hbs_sinks.hbs:9:13:9:19 | rawHtml | views/hbs_sinks.hbs:9:9:9:23 | {{{ rawHtml }}} |
| views/hbs_sinks.hbs:9:13:9:19 | rawHtml | views/hbs_sinks.hbs:9:9:9:23 | {{{ rawHtml }}} |
| views/hbs_sinks.hbs:10:13:10:19 | rawHtml | views/hbs_sinks.hbs:10:9:10:23 | {{{~rawHtml }}} |
| views/hbs_sinks.hbs:10:13:10:19 | rawHtml | views/hbs_sinks.hbs:10:9:10:23 | {{{~rawHtml }}} |
| views/hbs_sinks.hbs:11:13:11:19 | rawHtml | views/hbs_sinks.hbs:11:9:11:23 | {{{ rawHtml~}}} |
| views/hbs_sinks.hbs:11:13:11:19 | rawHtml | views/hbs_sinks.hbs:11:9:11:23 | {{{ rawHtml~}}} |
| views/hbs_sinks.hbs:12:13:12:19 | rawHtml | views/hbs_sinks.hbs:12:9:12:23 | {{{~rawHtml~}}} |
| views/hbs_sinks.hbs:12:13:12:19 | rawHtml | views/hbs_sinks.hbs:12:9:12:23 | {{{~rawHtml~}}} |
| views/hbs_sinks.hbs:13:14:13:20 | rawHtml | views/hbs_sinks.hbs:13:9:13:25 | {{{~ rawHtml ~}}} |
| views/hbs_sinks.hbs:13:14:13:20 | rawHtml | views/hbs_sinks.hbs:13:9:13:25 | {{{~ rawHtml ~}}} |
| views/hbs_sinks.hbs:15:13:15:19 | rawHtml | views/hbs_sinks.hbs:15:9:15:22 | {{& rawHtml }} |
| views/hbs_sinks.hbs:15:13:15:19 | rawHtml | views/hbs_sinks.hbs:15:9:15:22 | {{& rawHtml }} |
| views/hbs_sinks.hbs:19:13:19:30 | object.rawHtmlProp | views/hbs_sinks.hbs:19:9:19:34 | {{{ object.rawHtmlProp }}} |
| views/hbs_sinks.hbs:19:13:19:30 | object.rawHtmlProp | views/hbs_sinks.hbs:19:9:19:34 | {{{ object.rawHtmlProp }}} |
| views/hbs_sinks.hbs:23:47:23:68 | dataInS ... eralRaw | views/hbs_sinks.hbs:23:43:23:72 | {{{ dataInStringLiteralRaw }}} |
| views/hbs_sinks.hbs:23:47:23:68 | dataInS ... eralRaw | views/hbs_sinks.hbs:23:43:23:72 | {{{ dataInStringLiteralRaw }}} |
| views/hbs_sinks.hbs:26:46:26:67 | dataInG ... CodeRaw | views/hbs_sinks.hbs:26:42:26:71 | {{{ dataInGeneratedCodeRaw }}} |
| views/hbs_sinks.hbs:26:46:26:67 | dataInG ... CodeRaw | views/hbs_sinks.hbs:26:42:26:71 | {{{ dataInGeneratedCodeRaw }}} |
| views/hbs_sinks.hbs:34:43:34:69 | dataInE ... ringRaw | views/hbs_sinks.hbs:34:39:34:73 | {{{ dataInEventHandlerStringRaw }}} |
| views/hbs_sinks.hbs:34:43:34:69 | dataInE ... ringRaw | views/hbs_sinks.hbs:34:39:34:73 | {{{ dataInEventHandlerStringRaw }}} |
| views/hbs_sinks.hbs:4:13:4:19 | rawHtml | views/hbs_sinks.hbs:4:9:4:23 | {{{ rawHtml }}} |
| views/hbs_sinks.hbs:4:13:4:19 | rawHtml | views/hbs_sinks.hbs:4:9:4:23 | {{{ rawHtml }}} |
| views/hbs_sinks.hbs:7:13:7:30 | object.rawHtmlProp | views/hbs_sinks.hbs:7:9:7:34 | {{{ object.rawHtmlProp }}} |
| views/hbs_sinks.hbs:7:13:7:30 | object.rawHtmlProp | views/hbs_sinks.hbs:7:9:7:34 | {{{ object.rawHtmlProp }}} |
| views/hbs_sinks.hbs:11:47:11:68 | dataInS ... eralRaw | views/hbs_sinks.hbs:11:43:11:72 | {{{ dataInStringLiteralRaw }}} |
| views/hbs_sinks.hbs:11:47:11:68 | dataInS ... eralRaw | views/hbs_sinks.hbs:11:43:11:72 | {{{ dataInStringLiteralRaw }}} |
| views/hbs_sinks.hbs:14:46:14:67 | dataInG ... CodeRaw | views/hbs_sinks.hbs:14:42:14:71 | {{{ dataInGeneratedCodeRaw }}} |
| views/hbs_sinks.hbs:14:46:14:67 | dataInG ... CodeRaw | views/hbs_sinks.hbs:14:42:14:71 | {{{ dataInGeneratedCodeRaw }}} |
| views/hbs_sinks.hbs:22:43:22:69 | dataInE ... ringRaw | views/hbs_sinks.hbs:22:39:22:73 | {{{ dataInEventHandlerStringRaw }}} |
| views/hbs_sinks.hbs:22:43:22:69 | dataInE ... ringRaw | views/hbs_sinks.hbs:22:39:22:73 | {{{ dataInEventHandlerStringRaw }}} |
| views/njk_sinks.njk:15:49:15:74 | dataInG ... JsonRaw | views/njk_sinks.njk:15:49:15:81 | dataInG ... \| json |
| views/njk_sinks.njk:15:49:15:74 | dataInG ... JsonRaw | views/njk_sinks.njk:15:49:15:81 | dataInG ... \| json |
#select
@@ -326,16 +291,11 @@ edges
| views/ejs_sinks.ejs:11:43:11:71 | <%- dataInStringLiteralRaw %> | app.js:14:33:14:64 | req.que ... eralRaw | views/ejs_sinks.ejs:11:43:11:71 | <%- dataInStringLiteralRaw %> | Cross-site scripting vulnerability due to $@. | app.js:14:33:14:64 | req.que ... eralRaw | user-provided value |
| views/ejs_sinks.ejs:14:42:14:70 | <%- dataInGeneratedCodeRaw %> | app.js:16:33:16:64 | req.que ... CodeRaw | views/ejs_sinks.ejs:14:42:14:70 | <%- dataInGeneratedCodeRaw %> | Cross-site scripting vulnerability due to $@. | app.js:16:33:16:64 | req.que ... CodeRaw | user-provided value |
| views/ejs_sinks.ejs:22:39:22:72 | <%- dataInEventHandlerStringRaw %> | app.js:20:38:20:74 | req.que ... ringRaw | views/ejs_sinks.ejs:22:39:22:72 | <%- dataInEventHandlerStringRaw %> | Cross-site scripting vulnerability due to $@. | app.js:20:38:20:74 | req.que ... ringRaw | user-provided value |
| views/hbs_sinks.hbs:9:9:9:23 | {{{ rawHtml }}} | app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:9:9:9:23 | {{{ rawHtml }}} | Cross-site scripting vulnerability due to $@. | app.js:27:18:27:34 | req.query.rawHtml | user-provided value |
| views/hbs_sinks.hbs:10:9:10:23 | {{{~rawHtml }}} | app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:10:9:10:23 | {{{~rawHtml }}} | Cross-site scripting vulnerability due to $@. | app.js:27:18:27:34 | req.query.rawHtml | user-provided value |
| views/hbs_sinks.hbs:11:9:11:23 | {{{ rawHtml~}}} | app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:11:9:11:23 | {{{ rawHtml~}}} | Cross-site scripting vulnerability due to $@. | app.js:27:18:27:34 | req.query.rawHtml | user-provided value |
| views/hbs_sinks.hbs:12:9:12:23 | {{{~rawHtml~}}} | app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:12:9:12:23 | {{{~rawHtml~}}} | Cross-site scripting vulnerability due to $@. | app.js:27:18:27:34 | req.query.rawHtml | user-provided value |
| views/hbs_sinks.hbs:13:9:13:25 | {{{~ rawHtml ~}}} | app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:13:9:13:25 | {{{~ rawHtml ~}}} | Cross-site scripting vulnerability due to $@. | app.js:27:18:27:34 | req.query.rawHtml | user-provided value |
| views/hbs_sinks.hbs:15:9:15:22 | {{& rawHtml }} | app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:15:9:15:22 | {{& rawHtml }} | Cross-site scripting vulnerability due to $@. | app.js:27:18:27:34 | req.query.rawHtml | user-provided value |
| views/hbs_sinks.hbs:19:9:19:34 | {{{ object.rawHtmlProp }}} | app.js:30:26:30:46 | req.que ... tmlProp | views/hbs_sinks.hbs:19:9:19:34 | {{{ object.rawHtmlProp }}} | Cross-site scripting vulnerability due to $@. | app.js:30:26:30:46 | req.que ... tmlProp | user-provided value |
| views/hbs_sinks.hbs:23:43:23:72 | {{{ dataInStringLiteralRaw }}} | app.js:33:33:33:64 | req.que ... eralRaw | views/hbs_sinks.hbs:23:43:23:72 | {{{ dataInStringLiteralRaw }}} | Cross-site scripting vulnerability due to $@. | app.js:33:33:33:64 | req.que ... eralRaw | user-provided value |
| views/hbs_sinks.hbs:26:42:26:71 | {{{ dataInGeneratedCodeRaw }}} | app.js:35:33:35:64 | req.que ... CodeRaw | views/hbs_sinks.hbs:26:42:26:71 | {{{ dataInGeneratedCodeRaw }}} | Cross-site scripting vulnerability due to $@. | app.js:35:33:35:64 | req.que ... CodeRaw | user-provided value |
| views/hbs_sinks.hbs:34:39:34:73 | {{{ dataInEventHandlerStringRaw }}} | app.js:39:38:39:74 | req.que ... ringRaw | views/hbs_sinks.hbs:34:39:34:73 | {{{ dataInEventHandlerStringRaw }}} | Cross-site scripting vulnerability due to $@. | app.js:39:38:39:74 | req.que ... ringRaw | user-provided value |
| views/hbs_sinks.hbs:4:9:4:23 | {{{ rawHtml }}} | app.js:27:18:27:34 | req.query.rawHtml | views/hbs_sinks.hbs:4:9:4:23 | {{{ rawHtml }}} | Cross-site scripting vulnerability due to $@. | app.js:27:18:27:34 | req.query.rawHtml | user-provided value |
| views/hbs_sinks.hbs:7:9:7:34 | {{{ object.rawHtmlProp }}} | app.js:30:26:30:46 | req.que ... tmlProp | views/hbs_sinks.hbs:7:9:7:34 | {{{ object.rawHtmlProp }}} | Cross-site scripting vulnerability due to $@. | app.js:30:26:30:46 | req.que ... tmlProp | user-provided value |
| views/hbs_sinks.hbs:11:43:11:72 | {{{ dataInStringLiteralRaw }}} | app.js:33:33:33:64 | req.que ... eralRaw | views/hbs_sinks.hbs:11:43:11:72 | {{{ dataInStringLiteralRaw }}} | Cross-site scripting vulnerability due to $@. | app.js:33:33:33:64 | req.que ... eralRaw | user-provided value |
| views/hbs_sinks.hbs:14:42:14:71 | {{{ dataInGeneratedCodeRaw }}} | app.js:35:33:35:64 | req.que ... CodeRaw | views/hbs_sinks.hbs:14:42:14:71 | {{{ dataInGeneratedCodeRaw }}} | Cross-site scripting vulnerability due to $@. | app.js:35:33:35:64 | req.que ... CodeRaw | user-provided value |
| views/hbs_sinks.hbs:22:39:22:73 | {{{ dataInEventHandlerStringRaw }}} | app.js:39:38:39:74 | req.que ... ringRaw | views/hbs_sinks.hbs:22:39:22:73 | {{{ dataInEventHandlerStringRaw }}} | Cross-site scripting vulnerability due to $@. | app.js:39:38:39:74 | req.que ... ringRaw | user-provided value |
| views/njk_sinks.njk:4:12:4:18 | rawHtml | app.js:46:18:46:34 | req.query.rawHtml | views/njk_sinks.njk:4:12:4:18 | rawHtml | Cross-site scripting vulnerability due to $@. | app.js:46:18:46:34 | req.query.rawHtml | user-provided value |
| views/njk_sinks.njk:7:12:7:29 | object.rawHtmlProp | app.js:49:26:49:46 | req.que ... tmlProp | views/njk_sinks.njk:7:12:7:29 | object.rawHtmlProp | Cross-site scripting vulnerability due to $@. | app.js:49:26:49:46 | req.que ... tmlProp | user-provided value |
| views/njk_sinks.njk:11:46:11:67 | dataInS ... eralRaw | app.js:52:33:52:64 | req.que ... eralRaw | views/njk_sinks.njk:11:46:11:67 | dataInS ... eralRaw | Cross-site scripting vulnerability due to $@. | app.js:52:33:52:64 | req.que ... eralRaw | user-provided value |

View File

@@ -59,17 +59,12 @@ xssSink
| views/ejs_sinks.ejs:14:42:14:70 | <%- dataInGeneratedCodeRaw %> |
| views/ejs_sinks.ejs:22:39:22:72 | <%- dataInEventHandlerStringRaw %> |
| views/ejs_sinks.ejs:24:9:24:57 | <%- include('ejs_include1', { foo: rawHtml }) _%> |
| views/hbs_sinks.hbs:9:9:9:23 | {{{ rawHtml }}} |
| views/hbs_sinks.hbs:10:9:10:23 | {{{~rawHtml }}} |
| views/hbs_sinks.hbs:11:9:11:23 | {{{ rawHtml~}}} |
| views/hbs_sinks.hbs:12:9:12:23 | {{{~rawHtml~}}} |
| views/hbs_sinks.hbs:13:9:13:25 | {{{~ rawHtml ~}}} |
| views/hbs_sinks.hbs:15:9:15:22 | {{& rawHtml }} |
| views/hbs_sinks.hbs:17:9:17:32 | {{{ rawHtmlSafeValue }}} |
| views/hbs_sinks.hbs:19:9:19:34 | {{{ object.rawHtmlProp }}} |
| views/hbs_sinks.hbs:23:43:23:72 | {{{ dataInStringLiteralRaw }}} |
| views/hbs_sinks.hbs:26:42:26:71 | {{{ dataInGeneratedCodeRaw }}} |
| views/hbs_sinks.hbs:34:39:34:73 | {{{ dataInEventHandlerStringRaw }}} |
| views/hbs_sinks.hbs:4:9:4:23 | {{{ rawHtml }}} |
| views/hbs_sinks.hbs:5:9:5:32 | {{{ rawHtmlSafeValue }}} |
| views/hbs_sinks.hbs:7:9:7:34 | {{{ object.rawHtmlProp }}} |
| views/hbs_sinks.hbs:11:43:11:72 | {{{ dataInStringLiteralRaw }}} |
| views/hbs_sinks.hbs:14:42:14:71 | {{{ dataInGeneratedCodeRaw }}} |
| views/hbs_sinks.hbs:22:39:22:73 | {{{ dataInEventHandlerStringRaw }}} |
| views/instantiated_as_ejs.html:4:9:4:23 | <%- xss_sink %> |
| views/instantiated_as_hbs.html:7:9:7:24 | {{{ xss_sink }}} |
| views/njk_sinks.njk:4:12:4:18 | rawHtml |
@@ -88,9 +83,9 @@ codeInjectionSink
| views/ejs_sinks.ejs:13:39:13:64 | <%= dataInGeneratedCode %> |
| views/ejs_sinks.ejs:16:19:16:39 | <%= backslashSink1 %> |
| views/ejs_sinks.ejs:21:39:21:69 | <%= dataInEventHandlerString %> |
| views/hbs_sinks.hbs:25:39:25:63 | {{ dataInGeneratedCode }} |
| views/hbs_sinks.hbs:28:19:28:38 | {{ backslashSink1 }} |
| views/hbs_sinks.hbs:33:39:33:68 | {{ dataInEventHandlerString }} |
| views/hbs_sinks.hbs:13:39:13:63 | {{ dataInGeneratedCode }} |
| views/hbs_sinks.hbs:16:19:16:38 | {{ backslashSink1 }} |
| views/hbs_sinks.hbs:21:39:21:68 | {{ dataInEventHandlerString }} |
| views/njk_sinks.njk:13:39:13:63 | {{ dataInGeneratedCode }} |
| views/njk_sinks.njk:14:42:14:76 | {{ dataInGeneratedCodeRaw \| safe }} |
| views/njk_sinks.njk:15:46:15:91 | {{ dataInGeneratedCodeJsonRaw \| json \| safe }} |

View File

@@ -1,19 +1,7 @@
<html>
<body>
{{ escapedHtml }}
{{~ escapedHtml }}
{{ escapedHtml ~}}
{{~ escapedHtml ~}}
{{~escapedHtml~}}
{{{ rawHtml }}}
{{{~rawHtml }}}
{{{ rawHtml~}}}
{{{~rawHtml~}}}
{{{~ rawHtml ~}}}
{{& rawHtml }}
{{{ rawHtmlSafeValue }}}
{{{ object.rawHtmlProp }}}

View File

@@ -1,3 +0,0 @@
lgtm,codescanning
* Two new queries have been added for detecting Server-side request forgery (SSRF). _Full server-side request forgery_ (`py/full-ssrf`) will only alert when the URL is fully user-controlled, and _Partial server-side request forgery_ (`py/partial-ssrf`) will alert when any part of the URL is user-controlled. Only `py/full-ssrf` will be run by default.
* To support the new SSRF queries, the PyPI package `requests` have been modeled, along with `http.client.HTTP[S]Connection` from the standard library.

View File

@@ -812,72 +812,6 @@ module HTTP {
}
}
}
/** Provides classes for modeling HTTP clients. */
module Client {
/**
* A data-flow node that makes an outgoing HTTP request.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `HTTP::Client::Request::Range` instead.
*/
class Request extends DataFlow::Node instanceof Request::Range {
/**
* Gets a data-flow node that contributes to the URL of the request.
* Depending on the framework, a request may have multiple nodes which contribute to the URL.
*/
DataFlow::Node getAUrlPart() { result = super.getAUrlPart() }
/** Gets a string that identifies the framework used for this request. */
string getFramework() { result = super.getFramework() }
/**
* Holds if this request is made using a mode that disables SSL/TLS
* certificate validation, where `disablingNode` represents the point at
* which the validation was disabled, and `argumentOrigin` represents the origin
* of the argument that disabled the validation (which could be the same node as
* `disablingNode`).
*/
predicate disablesCertificateValidation(
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
) {
super.disablesCertificateValidation(disablingNode, argumentOrigin)
}
}
/** Provides a class for modeling new HTTP requests. */
module Request {
/**
* A data-flow node that makes an outgoing HTTP request.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `HTTP::Client::Request` instead.
*/
abstract class Range extends DataFlow::Node {
/**
* Gets a data-flow node that contributes to the URL of the request.
* Depending on the framework, a request may have multiple nodes which contribute to the URL.
*/
abstract DataFlow::Node getAUrlPart();
/** Gets a string that identifies the framework used for this request. */
abstract string getFramework();
/**
* Holds if this request is made using a mode that disables SSL/TLS
* certificate validation, where `disablingNode` represents the point at
* which the validation was disabled, and `argumentOrigin` represents the origin
* of the argument that disabled the validation (which could be the same node as
* `disablingNode`).
*/
abstract predicate disablesCertificateValidation(
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
);
}
}
// TODO: investigate whether we should treat responses to client requests as
// remote-flow-sources in general.
}
}
/**

View File

@@ -30,7 +30,6 @@ private import semmle.python.frameworks.Peewee
private import semmle.python.frameworks.Psycopg2
private import semmle.python.frameworks.Pydantic
private import semmle.python.frameworks.PyMySQL
private import semmle.python.frameworks.Requests
private import semmle.python.frameworks.RestFramework
private import semmle.python.frameworks.Rsa
private import semmle.python.frameworks.RuamelYaml

View File

@@ -15,23 +15,11 @@ module Consistency {
class ConsistencyConfiguration extends TConsistencyConfiguration {
string toString() { none() }
/** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */
predicate uniqueEnclosingCallableExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */
predicate uniqueNodeLocationExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `missingLocation`. */
predicate missingLocationExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `postWithInFlow`. */
predicate postWithInFlowExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `argHasPostUpdate`. */
predicate argHasPostUpdateExclude(ArgumentNode n) { none() }
/** Holds if `n` should be excluded from the consistency test `reverseRead`. */
predicate reverseReadExclude(Node n) { none() }
}
private class RelevantNode extends Node {
@@ -58,7 +46,6 @@ module Consistency {
n instanceof RelevantNode and
c = count(nodeGetEnclosingCallable(n)) and
c != 1 and
not any(ConsistencyConfiguration conf).uniqueEnclosingCallableExclude(n) and
msg = "Node should have one enclosing callable but has " + c + "."
)
}
@@ -79,7 +66,6 @@ module Consistency {
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
) and
c != 1 and
not any(ConsistencyConfiguration conf).uniqueNodeLocationExclude(n) and
msg = "Node should have one location but has " + c + "."
)
}
@@ -90,8 +76,7 @@ module Consistency {
strictcount(Node n |
not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
) and
not any(ConsistencyConfiguration conf).missingLocationExclude(n)
)
) and
msg = "Nodes without location: " + c
)
@@ -187,7 +172,6 @@ module Consistency {
query predicate reverseRead(Node n, string msg) {
exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and
not any(ConsistencyConfiguration conf).reverseReadExclude(n) and
msg = "Origin of readStep is missing a PostUpdateNode."
}

View File

@@ -1,171 +0,0 @@
/**
* Provides classes modeling security-relevant aspects of the `requests` PyPI package.
*
* See
* - https://pypi.org/project/requests/
* - https://docs.python-requests.org/en/latest/
*/
private import python
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.TaintTracking
private import semmle.python.frameworks.internal.InstanceTaintStepsHelper
private import semmle.python.frameworks.Stdlib
/**
* INTERNAL: Do not use.
*
* Provides models for the `requests` PyPI package.
*
* See
* - https://pypi.org/project/requests/
* - https://docs.python-requests.org/en/latest/
*/
private module Requests {
private class OutgoingRequestCall extends HTTP::Client::Request::Range, DataFlow::CallCfgNode {
string methodName;
OutgoingRequestCall() {
methodName in [HTTP::httpVerbLower(), "request"] and
(
this = API::moduleImport("requests").getMember(methodName).getACall()
or
exists(API::Node moduleExporting, API::Node sessionInstance |
moduleExporting in [
API::moduleImport("requests"), //
API::moduleImport("requests").getMember("sessions")
] and
sessionInstance = moduleExporting.getMember(["Session", "session"]).getReturn()
|
this = sessionInstance.getMember(methodName).getACall()
)
)
}
override DataFlow::Node getAUrlPart() {
result = this.getArgByName("url")
or
not methodName = "request" and
result = this.getArg(0)
or
methodName = "request" and
result = this.getArg(1)
}
/** Gets the `verify` argument to this outgoing requests call. */
DataFlow::Node getVerifyArg() { result = this.getArgByName("verify") }
override predicate disablesCertificateValidation(
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
) {
disablingNode = this.getVerifyArg() and
argumentOrigin = verifyArgBacktracker(disablingNode) and
argumentOrigin.asExpr().(ImmutableLiteral).booleanValue() = false and
not argumentOrigin.asExpr() instanceof None
}
override string getFramework() { result = "requests" }
}
/**
* Extra taint propagation for outgoing requests calls,
* to ensure that responses to user-controlled URL are tainted.
*/
private class OutgoingRequestCallTaintStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
nodeFrom = nodeTo.(OutgoingRequestCall).getAUrlPart()
}
}
/** Gets a back-reference to the verify argument `arg`. */
private DataFlow::TypeTrackingNode verifyArgBacktracker(
DataFlow::TypeBackTracker t, DataFlow::Node arg
) {
t.start() and
arg = any(OutgoingRequestCall c).getVerifyArg() and
result = arg.getALocalSource()
or
exists(DataFlow::TypeBackTracker t2 | result = verifyArgBacktracker(t2, arg).backtrack(t2, t))
}
/** Gets a back-reference to the verify argument `arg`. */
private DataFlow::LocalSourceNode verifyArgBacktracker(DataFlow::Node arg) {
result = verifyArgBacktracker(DataFlow::TypeBackTracker::end(), arg)
}
// ---------------------------------------------------------------------------
// Response
// ---------------------------------------------------------------------------
/**
* Provides models for the `requests.models.Response` class
*
* See https://docs.python-requests.org/en/latest/api/#requests.Response.
*/
module Response {
/** Gets a reference to the `requests.models.Response` class. */
private API::Node classRef() {
result = API::moduleImport("requests").getMember("models").getMember("Response")
or
result = API::moduleImport("requests").getMember("Response")
}
/**
* A source of instances of `requests.models.Response`, extend this class to model new instances.
*
* This can include instantiations of the class, return values from function
* calls, or a special parameter that will be set when functions are called by an external
* library.
*
* Use the predicate `Response::instance()` to get references to instances of `requests.models.Response`.
*/
abstract class InstanceSource extends DataFlow::LocalSourceNode { }
/** A direct instantiation of `requests.models.Response`. */
private class ClassInstantiation extends InstanceSource, DataFlow::CallCfgNode {
ClassInstantiation() { this = classRef().getACall() }
}
/** Return value from making a reuqest. */
private class RequestReturnValue extends InstanceSource, DataFlow::Node {
RequestReturnValue() { this = any(OutgoingRequestCall c) }
}
/** Gets a reference to an instance of `requests.models.Response`. */
private DataFlow::TypeTrackingNode instance(DataFlow::TypeTracker t) {
t.start() and
result instanceof InstanceSource
or
exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t))
}
/** Gets a reference to an instance of `requests.models.Response`. */
DataFlow::Node instance() { instance(DataFlow::TypeTracker::end()).flowsTo(result) }
/**
* Taint propagation for `requests.models.Response`.
*/
private class InstanceTaintSteps extends InstanceTaintStepsHelper {
InstanceTaintSteps() { this = "requests.models.Response" }
override DataFlow::Node getInstance() { result = instance() }
override string getAttributeName() {
result in ["text", "content", "raw", "links", "cookies", "headers"]
}
override string getMethodName() { result in ["json", "iter_content", "iter_lines"] }
override string getAsyncMethodName() { none() }
}
/** An attribute read that is a file-like instance. */
private class FileLikeInstances extends Stdlib::FileLikeObject::InstanceSource {
FileLikeInstances() {
this.(DataFlow::AttrRead).getObject() = instance() and
this.(DataFlow::AttrRead).getAttributeName() = "raw"
}
}
}
}

View File

@@ -2091,201 +2091,6 @@ private module StdlibPrivate {
}
}
// ---------------------------------------------------------------------------
// http.client (Python 3)
// httplib (Python 2)
// ---------------------------------------------------------------------------
/**
* Provides models for the `http.client.HTTPConnection` and `HTTPSConnection` classes
*
* See
* - https://docs.python.org/3.10/library/http.client.html#http.client.HTTPConnection
* - https://docs.python.org/3.10/library/http.client.html#http.client.HTTPSConnection
* - https://docs.python.org/2.7/library/httplib.html#httplib.HTTPConnection
* - https://docs.python.org/2.7/library/httplib.html#httplib.HTTPSConnection
*/
module HTTPConnection {
/** Gets a reference to the `http.client.HTTPConnection` class. */
private API::Node classRef() {
exists(string className | className in ["HTTPConnection", "HTTPSConnection"] |
// Python 3
result = API::moduleImport("http").getMember("client").getMember(className)
or
// Python 2
result = API::moduleImport("httplib").getMember(className)
or
result =
API::moduleImport("six").getMember("moves").getMember("http_client").getMember(className)
)
}
/**
* A source of instances of `http.client.HTTPConnection`, extend this class to model new instances.
*
* This can include instantiations of the class, return values from function
* calls, or a special parameter that will be set when functions are called by an external
* library.
*
* Use the predicate `HTTPConnection::instance()` to get references to instances of `http.client.HTTPConnection`.
*/
abstract class InstanceSource extends DataFlow::LocalSourceNode {
/** Gets the argument that specified the host, if any. */
abstract DataFlow::Node getHostArgument();
}
/** A direct instantiation of `http.client.HTTPConnection`. */
private class ClassInstantiation extends InstanceSource, DataFlow::CallCfgNode {
ClassInstantiation() { this = classRef().getACall() }
override DataFlow::Node getHostArgument() {
result in [this.getArg(0), this.getArgByName("host")]
}
}
/**
* Gets a reference to an instance of `http.client.HTTPConnection`,
* that was instantiated with host argument `hostArg`.
*/
private DataFlow::TypeTrackingNode instance(DataFlow::TypeTracker t, DataFlow::Node hostArg) {
t.start() and
hostArg = result.(InstanceSource).getHostArgument()
or
exists(DataFlow::TypeTracker t2 | result = instance(t2, hostArg).track(t2, t))
}
/**
* Gets a reference to an instance of `http.client.HTTPConnection`,
* that was instantiated with host argument `hostArg`.
*/
DataFlow::Node instance(DataFlow::Node hostArg) {
instance(DataFlow::TypeTracker::end(), hostArg).flowsTo(result)
}
/** A method call on a HTTPConnection that sends off a request */
private class RequestCall extends HTTP::Client::Request::Range, DataFlow::MethodCallNode {
RequestCall() { this.calls(instance(_), ["request", "_send_request", "putrequest"]) }
DataFlow::Node getUrlArg() { result in [this.getArg(1), this.getArgByName("url")] }
override DataFlow::Node getAUrlPart() {
result = this.getUrlArg()
or
this.getObject() = instance(result)
}
override string getFramework() { result = "http.client.HTTP[S]Connection" }
override predicate disablesCertificateValidation(
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
) {
// TODO: Proper alerting of insecure verification settings on SSLContext.
// Because that is not restricted to HTTP[S]Connection usage, we need something
// more general, and I would like to tackle that in future PR.
none()
}
}
/** A call to the `getresponse` method. */
private class HttpConnectionGetResponseCall extends DataFlow::MethodCallNode,
HTTPResponse::InstanceSource {
HttpConnectionGetResponseCall() { this.calls(instance(_), "getresponse") }
}
/**
* Extra taint propagation for `http.client.HTTPConnection`,
* to ensure that responses to user-controlled URL are tainted.
*/
private class AdditionalTaintStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
// constructor
exists(InstanceSource instanceSource |
nodeFrom = instanceSource.getHostArgument() and
nodeTo = instanceSource
)
or
// a request method
exists(RequestCall call |
nodeFrom = call.getUrlArg() and
nodeTo.(DataFlow::PostUpdateNode).getPreUpdateNode() = call.getObject()
)
or
// `getresponse` call
exists(HttpConnectionGetResponseCall call |
nodeFrom = call.getObject() and
nodeTo = call
)
}
}
}
/**
* Provides models for the `http.client.HTTPResponse` class
*
* See
* - https://docs.python.org/3.10/library/http.client.html#httpresponse-objects
* - https://docs.python.org/3/library/http.client.html#http.client.HTTPResponse.
*/
module HTTPResponse {
/** Gets a reference to the `http.client.HTTPResponse` class. */
private API::Node classRef() {
result = API::moduleImport("http").getMember("client").getMember("HTTPResponse")
}
/**
* A source of instances of `http.client.HTTPResponse`, extend this class to model new instances.
*
* A `http.client.HTTPResponse` is itself a file-like object.
*
* This can include instantiations of the class, return values from function
* calls, or a special parameter that will be set when functions are called by an external
* library.
*
* Use the predicate `HTTPResponse::instance()` to get references to instances of `http.client.HTTPResponse`.
*/
abstract class InstanceSource extends Stdlib::FileLikeObject::InstanceSource,
DataFlow::LocalSourceNode { }
/** A direct instantiation of `http.client.HTTPResponse`. */
private class ClassInstantiation extends InstanceSource, DataFlow::CallCfgNode {
ClassInstantiation() { this = classRef().getACall() }
}
/** Gets a reference to an instance of `http.client.HTTPResponse`. */
private DataFlow::TypeTrackingNode instance(DataFlow::TypeTracker t) {
t.start() and
result instanceof InstanceSource
or
exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t))
}
/** Gets a reference to an instance of `http.client.HTTPResponse`. */
DataFlow::Node instance() { instance(DataFlow::TypeTracker::end()).flowsTo(result) }
/**
* Taint propagation for `http.client.HTTPResponse`.
*/
private class InstanceTaintSteps extends InstanceTaintStepsHelper {
InstanceTaintSteps() { this = "http.client.HTTPResponse" }
override DataFlow::Node getInstance() { result = instance() }
override string getAttributeName() { result in ["headers", "msg", "reason", "url"] }
override string getMethodName() { result in ["getheader", "getheaders", "info", "geturl",] }
override string getAsyncMethodName() { none() }
}
/** An attribute read that is a HTTPMessage instance. */
private class HTTPMessageInstances extends Stdlib::HTTPMessage::InstanceSource {
HTTPMessageInstances() {
this.(DataFlow::AttrRead).accesses(instance(), ["headers", "msg"])
or
this.(DataFlow::MethodCallNode).calls(instance(), "info")
}
}
}
// ---------------------------------------------------------------------------
// sqlite3
// ---------------------------------------------------------------------------

View File

@@ -382,7 +382,7 @@ class BuiltinMethodObjectInternal extends CallableObjectInternal, TBuiltinMethod
/**
* Class representing bound-methods.
* Note that built-in methods, such as `[].append` are also represented as bound-methods.
* Although built-in methods and bound-methods are distinct classes in CPython, their behavior
* Although built-in methods and bound-methods are distinct classes in CPython, their behaviour
* is the same and we treat them identically.
*/
class BoundMethodObjectInternal extends CallableObjectInternal, TBoundMethod {

View File

@@ -1,84 +0,0 @@
/**
* Provides a taint-tracking configuration for detecting "Server-side request forgery" vulnerabilities.
*
* Note, for performance reasons: only import this file if
* `ServerSideRequestForgery::Configuration` is needed, otherwise
* `ServerSideRequestForgeryCustomizations` should be imported instead.
*/
private import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.Concepts
/**
* Provides a taint-tracking configuration for detecting "Server-side request forgery" vulnerabilities.
*
* This configuration has a sanitizer to limit results to cases where attacker has full control of URL.
* See `PartialServerSideRequestForgery` for a variant without this requirement.
*
* You should use the `partOfFullyControlledRequest` to only select results where all
* URL parts are fully controlled.
*/
module FullServerSideRequestForgery {
import ServerSideRequestForgeryCustomizations::ServerSideRequestForgery
/**
* A taint-tracking configuration for detecting "Server-side request forgery" vulnerabilities.
*/
class Configuration extends TaintTracking::Configuration {
Configuration() { this = "FullServerSideRequestForgery" }
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 FullUrlControlSanitizer
}
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof SanitizerGuard
}
}
}
/**
* Holds if all URL parts of `request` is fully user controlled.
*/
predicate fullyControlledRequest(HTTP::Client::Request request) {
exists(FullServerSideRequestForgery::Configuration fullConfig |
forall(DataFlow::Node urlPart | urlPart = request.getAUrlPart() |
fullConfig.hasFlow(_, urlPart)
)
)
}
/**
* Provides a taint-tracking configuration for detecting "Server-side request forgery" vulnerabilities.
*
* This configuration has results, even when the attacker does not have full control over the URL.
* See `FullServerSideRequestForgery` for variant that has this requirement.
*/
module PartialServerSideRequestForgery {
import ServerSideRequestForgeryCustomizations::ServerSideRequestForgery
/**
* A taint-tracking configuration for detecting "Server-side request forgery" vulnerabilities.
*/
class Configuration extends TaintTracking::Configuration {
Configuration() { this = "PartialServerSideRequestForgery" }
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 }
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof SanitizerGuard
}
}
}

View File

@@ -1,143 +0,0 @@
/**
* Provides default sources, sinks and sanitizers for detecting
* "Server-side request forgery"
* vulnerabilities, as well as extension points for adding your own.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.Concepts
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.dataflow.new.BarrierGuards
/**
* Provides default sources, sinks and sanitizers for detecting
* "Server-side request forgery"
* vulnerabilities, as well as extension points for adding your own.
*/
module ServerSideRequestForgery {
/**
* A data flow source for "Server-side request forgery" vulnerabilities.
*/
abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for "Server-side request forgery" vulnerabilities.
*/
abstract class Sink extends DataFlow::Node {
/**
* Gets the request this sink belongs to.
*/
abstract HTTP::Client::Request getRequest();
}
/**
* A sanitizer for "Server-side request forgery" vulnerabilities.
*/
abstract class Sanitizer extends DataFlow::Node { }
/**
* A sanitizer for "Server-side request forgery" vulnerabilities,
* that ensures the attacker does not have full control of the URL. (that is, might
* still be able to control path or query parameters).
*/
abstract class FullUrlControlSanitizer extends DataFlow::Node { }
/**
* A sanitizer guard for "Server-side request forgery" vulnerabilities.
*/
abstract class SanitizerGuard extends DataFlow::BarrierGuard { }
/**
* A source of remote user input, considered as a flow source.
*/
class RemoteFlowSourceAsSource extends Source, RemoteFlowSource { }
/** The URL of an HTTP request, considered as a sink. */
class HttpRequestUrlAsSink extends Sink {
HTTP::Client::Request req;
HttpRequestUrlAsSink() {
req.getAUrlPart() = this and
// if we extract the stdlib code for HTTPConnection, we will also find calls that
// make requests within the HTTPConnection implementation -- for example the
// `request` method calls the `_send_request` method internally. So without this
// extra bit of code, we would give alerts within the HTTPConnection
// implementation as well, which is just annoying.
//
// Notice that we're excluding based on the request location, and not the URL part
// location, since the URL part would be in user code for the scenario above.
//
// See comment for command injection sinks for more details.
not req.getScope().getEnclosingModule().getName() in ["http.client", "httplib"]
}
override HTTP::Client::Request getRequest() { result = req }
}
/**
* A comparison with a constant string, considered as a sanitizer-guard.
*/
class StringConstCompareAsSanitizerGuard extends SanitizerGuard, StringConstCompare { }
/**
* A string construction (concat, format, f-string) where the left side is not
* user-controlled.
*
* For all of these cases, we try to allow `http://` or `https://` on the left side
* since that will still allow full URL control.
*/
class StringConstructionAsFullUrlControlSanitizer extends FullUrlControlSanitizer {
StringConstructionAsFullUrlControlSanitizer() {
// string concat
exists(BinaryExprNode add |
add.getOp() instanceof Add and
add.getRight() = this.asCfgNode() and
not add.getLeft().getNode().(StrConst).getText().toLowerCase() in ["http://", "https://"]
)
or
// % formatting
exists(BinaryExprNode fmt |
fmt.getOp() instanceof Mod and
fmt.getRight() = this.asCfgNode() and
// detecting %-formatting is not super easy, so we simplify it to only handle
// when there is a **single** substitution going on.
not fmt.getLeft().getNode().(StrConst).getText().regexpMatch("^(?i)https?://%s[^%]*$")
)
or
// arguments to a format call
exists(DataFlow::MethodCallNode call, string httpPrefixRe |
httpPrefixRe = "^(?i)https?://(?:(\\{\\})|\\{([0-9]+)\\}|\\{([^0-9].*)\\}).*$"
|
call.getMethodName() = "format" and
(
if call.getObject().asExpr().(StrConst).getText().regexpMatch(httpPrefixRe)
then
exists(string text | text = call.getObject().asExpr().(StrConst).getText() |
// `http://{}...`
exists(text.regexpCapture(httpPrefixRe, 1)) and
this in [call.getArg(any(int i | i >= 1)), call.getArgByName(_)]
or
// `http://{123}...`
exists(int safeArgIndex | safeArgIndex = text.regexpCapture(httpPrefixRe, 2).toInt() |
this in [call.getArg(any(int i | i != safeArgIndex)), call.getArgByName(_)]
)
or
// `http://{abc}...`
exists(string safeArgName | safeArgName = text.regexpCapture(httpPrefixRe, 3) |
this in [call.getArg(_), call.getArgByName(any(string s | s != safeArgName))]
)
)
else this in [call.getArg(_), call.getArgByName(_)]
)
)
or
// f-string
exists(Fstring fstring |
if fstring.getValue(0).(StrConst).getText().toLowerCase() in ["http://", "https://"]
then fstring.getValue(any(int i | i >= 2)) = this.asExpr()
else fstring.getValue(any(int i | i >= 1)) = this.asExpr()
)
}
}
}

View File

@@ -1,11 +0,0 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<include src="ServerSideRequestForgery-start.inc.qhelp" />
<!-- query specific -->
<p>This query covers full SSRF, to find partial SSRF use the <code>py/partial-ssrf</code> query.</p>
</overview>
<include src="ServerSideRequestForgery-end.inc.qhelp" />
</qhelp>

View File

@@ -1,25 +0,0 @@
/**
* @name Full server-side request forgery
* @description Making a network request to a URL that is fully user-controlled allows for request forgery attacks.
* @kind path-problem
* @problem.severity error
* @security-severity 9.1
* @precision high
* @id py/full-ssrf
* @tags security
* external/cwe/cwe-918
*/
import python
import semmle.python.security.dataflow.ServerSideRequestForgery
import DataFlow::PathGraph
from
FullServerSideRequestForgery::Configuration fullConfig, DataFlow::PathNode source,
DataFlow::PathNode sink, HTTP::Client::Request request
where
request = sink.getNode().(FullServerSideRequestForgery::Sink).getRequest() and
fullConfig.hasFlowPath(source, sink) and
fullyControlledRequest(request)
select request, source, sink, "The full URL of this request depends on $@.", source.getNode(),
"a user-provided value"

View File

@@ -1,11 +0,0 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<include src="ServerSideRequestForgery-start.inc.qhelp" />
<!-- query specific -->
<p>This query covers partial SSRF, to find full SSRF use the <code>py/full-ssrf</code> query.</p>
</overview>
<include src="ServerSideRequestForgery-end.inc.qhelp" />
</qhelp>

View File

@@ -1,25 +0,0 @@
/**
* @name Partial server-side request forgery
* @description Making a network request to a URL that is partially user-controlled allows for request forgery attacks.
* @kind path-problem
* @problem.severity error
* @security-severity 9.1
* @precision medium
* @id py/partial-ssrf
* @tags security
* external/cwe/cwe-918
*/
import python
import semmle.python.security.dataflow.ServerSideRequestForgery
import DataFlow::PathGraph
from
PartialServerSideRequestForgery::Configuration partialConfig, DataFlow::PathNode source,
DataFlow::PathNode sink, HTTP::Client::Request request
where
request = sink.getNode().(PartialServerSideRequestForgery::Sink).getRequest() and
partialConfig.hasFlowPath(source, sink) and
not fullyControlledRequest(request)
select request, source, sink, "Part of the URL of this request depends on $@.", source.getNode(),
"a user-provided value"

View File

@@ -1,47 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<recommendation>
<p>To guard against SSRF attacks you should avoid putting user-provided input directly
into a request URL. Instead, either maintain a list of authorized URLs on the server and choose
from that list based on the input provided, or perform proper validation of the input.
</p>
</recommendation>
<example>
<p>The following example shows code vulnerable to a full SSRF attack, because it
uses untrusted input (HTTP request parameter) directly to construct a URL. By using
<code>evil.com#</code> as the <code>target</code> value, the requested URL will be
<code>https://evil.com#.example.com/data/</code>. It also shows how to remedy the
problem by using the user input select a known fixed string.
</p>
<sample src="examples/ServerSideRequestForgery_full.py" />
</example>
<example>
<p>
The following example shows code vulnerable to a partial SSRF attack, because it
uses untrusted input (HTTP request parameter) directly to construct a URL. By
using <code>../transfer-funds-to/123?amount=456</code> as the
<code>user_id</code> value, the requested URL will be
<code>https://api.example.com/transfer-funds-to/123?amount=456</code>. It also
shows how to remedy the problem by validating the input.
</p>
<sample src="examples/ServerSideRequestForgery_partial.py" />
</example>
<references>
<li>
<a href="https://owasp.org/www-community/attacks/Server_Side_Request_Forgery">OWASP SSRF article</a>
</li>
<li>
<a href="https://portswigger.net/web-security/ssrf">PortSwigger SSRF article</a>
</li>
</references>
</qhelp>

View File

@@ -1,31 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<fragment>
<p>Directly incorporating user input into an HTTP request without validating the input
can facilitate server-side request forgery (SSRF) attacks. In these attacks, the
request may be changed, directed at a different server, or via a different
protocol. This can allow the attacker to obtain sensitive information or perform
actions with escalated privilege.
</p>
<p>
We make a distinctions between how much of the URL an attacker can control:
</p>
<ul>
<li><b>Full SSRF</b>: where the full URL can be controlled.</li>
<li><b>Partial SSRF</b>: where only part of the URL can be controlled, such as the
path component of a URL to a hardcoded domain.</li>
</ul>
<p></p>
<p>
Partial control of a URL is often much harder to exploit. Therefore we have created a
separate query for each of these.
</p>
</fragment>
</qhelp>

View File

@@ -1,15 +0,0 @@
import requests
from flask import Flask, request
app = Flask(__name__)
@app.route("/full_ssrf")
def full_ssrf():
target = request.args["target"]
# BAD: user has full control of URL
resp = request.get("https://" + target + ".example.com/data/")
# GOOD: `subdomain` is controlled by the server.
subdomain = "europe" if target == "EU" else "world"
resp = request.get("https://" + subdomain + ".example.com/data/")

View File

@@ -1,15 +0,0 @@
import requests
from flask import Flask, request
app = Flask(__name__)
@app.route("/partial_ssrf")
def partial_ssrf():
user_id = request.args["user_id"]
# BAD: user can fully control the path component of the URL
resp = requests.get("https://api.example.com/user_info/" + user_id)
if user_id.isalnum():
# GOOD: user_id is restricted to be alpha-numeric, and cannot alter path component of URL
resp = requests.get("https://api.example.com/user_info/" + user_id)

View File

@@ -475,31 +475,3 @@ class CryptographicOperationTest extends InlineExpectationsTest {
)
}
}
class HttpClientRequestTest extends InlineExpectationsTest {
HttpClientRequestTest() { this = "HttpClientRequestTest" }
override string getARelevantTag() {
result in ["clientRequestUrlPart", "clientRequestCertValidationDisabled"]
}
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(location.getFile().getRelativePath()) and
exists(HTTP::Client::Request req, DataFlow::Node url |
url = req.getAUrlPart() and
location = url.getLocation() and
element = url.toString() and
value = prettyNodeForInlineTest(url) and
tag = "clientRequestUrlPart"
)
or
exists(location.getFile().getRelativePath()) and
exists(HTTP::Client::Request req |
req.disablesCertificateValidation(_, _) and
location = req.getLocation() and
element = req.toString() and
value = "" and
tag = "clientRequestCertValidationDisabled"
)
}
}

View File

@@ -1,2 +0,0 @@
import python
import experimental.meta.ConceptsTest

View File

@@ -1,3 +0,0 @@
argumentToEnsureNotTaintedNotMarkedAsSpurious
untaintedArgumentToEnsureTaintedNotMarkedAsMissing
failures

View File

@@ -1 +0,0 @@
import experimental.meta.InlineTaintTest

View File

@@ -1,55 +0,0 @@
import requests
from flask import Flask, request
app = Flask(__name__)
@app.route("/taint_test") # $ routeSetup="/taint_test"
def test_taint(): # $ requestHandler
url = request.args['untrusted_input']
# response from a request to a user-controlled URL should be considered
# user-controlled as well.
resp = requests.get(url) # $ clientRequestUrlPart=url
requests.Response
requests.models.Response
ensure_tainted(
url, # $ tainted
# see https://docs.python-requests.org/en/latest/api/#requests.Response
resp, # $ tainted
resp.text, # $ tainted
resp.content, # $ tainted
resp.json(), # $ tainted
# file-like
resp.raw, # $ tainted
resp.raw.read(), # $ tainted
resp.links, # $ tainted
resp.links['key'], # $ tainted
resp.links.get('key'), # $ tainted
resp.cookies, # $ tainted
resp.cookies['key'], # $ tainted
resp.cookies.get('key'), # $ tainted
resp.headers, # $ tainted
resp.headers['key'], # $ tainted
resp.headers.get('key'), # $ tainted
)
for content_chunk in resp.iter_content():
ensure_tainted(content_chunk) # $ tainted
for line in resp.iter_lines():
ensure_tainted(line) # $ tainted
# for now, we don't assume that the response to ANY outgoing request is a remote
# flow source, since this could lead to FPs.
# TODO: investigate whether we should consider this a remote flow source.
trusted_url = "https://internal-api-that-i-trust.com"
resp = requests.get(trusted_url) # $ clientRequestUrlPart=trusted_url
ensure__not_tainted(resp)

View File

@@ -1,50 +0,0 @@
import requests
resp = requests.get("url") # $ clientRequestUrlPart="url"
resp = requests.get(url="url") # $ clientRequestUrlPart="url"
resp = requests.request("GET", "url") # $ clientRequestUrlPart="url"
with requests.Session() as session:
resp = session.get("url") # $ clientRequestUrlPart="url"
resp = session.request(method="GET", url="url") # $ clientRequestUrlPart="url"
s = requests.Session()
resp = s.get("url") # $ clientRequestUrlPart="url"
s = requests.session()
resp = s.get("url") # $ clientRequestUrlPart="url"
# test full import path for Session
with requests.sessions.Session() as session:
resp = session.get("url") # $ clientRequestUrlPart="url"
# Low level access
req = requests.Request("GET", "url") # $ MISSING: clientRequestUrlPart="url"
resp = s.send(req.prepare())
# other methods than GET
resp = requests.post("url") # $ clientRequestUrlPart="url"
resp = requests.patch("url") # $ clientRequestUrlPart="url"
resp = requests.options("url") # $ clientRequestUrlPart="url"
# ==============================================================================
# Disabling certificate validation
# ==============================================================================
resp = requests.get("url", verify=False) # $ clientRequestUrlPart="url" clientRequestCertValidationDisabled
def make_get(verify_arg):
resp = requests.get("url", verify=verify_arg) # $ clientRequestUrlPart="url" clientRequestCertValidationDisabled
make_get(False)
with requests.Session() as session:
# see https://github.com/psf/requests/blob/39d0fdd9096f7dceccbc8f82e1eda7dd64717a8e/requests/sessions.py#L621
session.verify = False
resp = session.get("url") # $ clientRequestUrlPart="url" MISSING: clientRequestCertValidationDisabled
resp = session.get("url", verify=True) # $ clientRequestUrlPart="url"
req = requests.Request("GET", "url") # $ MISSING: clientRequestUrlPart="url"
resp = session.send(req.prepare()) # $ MISSING: clientRequestCertValidationDisabled

View File

@@ -1,170 +0,0 @@
import sys
import ssl
PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3
if PY2:
from httplib import HTTPConnection, HTTPSConnection
if PY3:
from http.client import HTTPConnection, HTTPSConnection
# NOTE: the URL may be relative to host, or may be full URL.
conn = HTTPConnection("example.com") # $ clientRequestUrlPart="example.com"
conn.request("GET", "/") # $ clientRequestUrlPart="/"
url = "http://example.com/"
conn.request("GET", url) # $ clientRequestUrlPart=url
# kwargs
conn = HTTPConnection(host="example.com") # $ clientRequestUrlPart="example.com"
conn.request(method="GET", url="/") # $ clientRequestUrlPart="/"
# using internal method... you shouldn't but you can
conn._send_request("GET", "url", body=None, headers={}, encode_chunked=False) # $ clientRequestUrlPart="url"
# low level sending of request
conn.putrequest("GET", "url") # $ clientRequestUrlPart="url"
conn.putheader("X-Foo", "value")
conn.endheaders(message_body=None)
# HTTPS
conn = HTTPSConnection("host") # $ clientRequestUrlPart="host"
conn.request("GET", "url") # $ clientRequestUrlPart="url"
# six aliases
import six
conn = six.moves.http_client.HTTPConnection("host") # $ clientRequestUrlPart="host"
conn.request("GET", "url") # $ clientRequestUrlPart="url"
conn = six.moves.http_client.HTTPSConnection("host") # $ clientRequestUrlPart="host"
conn.request("GET", "url") # $ clientRequestUrlPart="url"
# ==============================================================================
# Certificate validation disabled
# ==============================================================================
# default SSL context is the one given by `_create_default_https_context`
context = ssl._create_default_https_context()
assert context.check_hostname == True
assert context.verify_mode == ssl.CERT_REQUIRED
conn = HTTPSConnection("host", context=context) # $ clientRequestUrlPart="host"
conn.request("GET", "url") # $ clientRequestUrlPart="url"
# `_create_default_https_context` is currently just an alias for `create_default_context`
# which creates a context for SERVER_AUTH purpose.
context = ssl.create_default_context()
assert context.check_hostname == True
assert context.verify_mode == ssl.CERT_REQUIRED
conn = HTTPSConnection("host", context=context) # $ clientRequestUrlPart="host"
conn.request("GET", "url") # $ clientRequestUrlPart="url"
# however, if you supply your own SSLContext, you need to set it manually
context = ssl.SSLContext()
assert context.check_hostname == False
assert context.verify_mode == ssl.CERT_NONE
conn = HTTPSConnection("host", context=context) # $ clientRequestUrlPart="host"
conn.request("GET", "url") # $ clientRequestUrlPart="url" MISSING: clientRequestCertValidationDisabled
# and if you misunderstood whether to use server/client in the purpose, you will also
# get a context without hostname verification.
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
assert context.check_hostname == False
assert context.verify_mode == ssl.CERT_NONE
conn = HTTPSConnection("host", context=context) # $ clientRequestUrlPart="host"
conn.request("GET", "url") # $ clientRequestUrlPart="url" MISSING: clientRequestCertValidationDisabled
# NOTICE that current documentation says
#
# > Enabling hostname checking automatically sets verify_mode from CERT_NONE to
# > CERT_REQUIRED. It cannot be set back to CERT_NONE as long as hostname checking is
# > enabled.
# - https://docs.python.org/3.10/library/ssl.html#ssl.SSLContext.check_hostname
context = ssl.SSLContext()
context.check_hostname = True
assert context.verify_mode == ssl.CERT_REQUIRED
conn = HTTPSConnection("host", context=context) # $ clientRequestUrlPart="host"
conn.request("GET", "url") # $ clientRequestUrlPart="url"
# only setting verify_mode is not enough, since check_hostname is not enabled
context = ssl.SSLContext()
context.verify_mode = ssl.CERT_REQUIRED
assert context.check_hostname == False
conn = HTTPSConnection("host", context=context) # $ clientRequestUrlPart="host"
conn.request("GET", "url") # $ clientRequestUrlPart="url" MISSING: clientRequestCertValidationDisabled
# ==============================================================================
# taint test
# ==============================================================================
from flask import request
def taint_test():
host = request.args['host']
url = request.args['url']
conn = HTTPConnection(host) # $ clientRequestUrlPart=host
conn.request("GET", url) # $ clientRequestUrlPart=url
resp = conn.getresponse()
ensure_tainted(
# see
# https://docs.python.org/3.10/library/http.client.html#httpresponse-objects
# https://docs.python.org/3/library/http.client.html#http.client.HTTPResponse
# a HTTPResponse itself is file-like
resp, # $ tainted
resp.read(), # $ tainted
resp.getheader("name"), # $ tainted
resp.getheaders(), # $ tainted
# http.client.HTTPMessage
resp.headers, # $ tainted
resp.headers.get_all(), # $ tainted
# Alias for .headers
# http.client.HTTPMessage
resp.msg, # $ tainted
resp.msg.get_all(), # $ tainted
# Alias for .headers
resp.info(), # $ tainted
resp.info().get_all(), # $ tainted
# although this would usually be the textual version of the status
# ("OK" for 200), it is possible to put your own evil data in here.
resp.reason, # $ tainted
# the URL of the recourse that was visited, if redirects were followed.
# I don't see any reason this could not contain evil data.
resp.url, # $ tainted
resp.geturl(), # $ tainted
)
ensure_not_tainted(
resp.status,
resp.code,
resp.getcode(),
)
# check that only setting either host/url is enough to propagate taint
conn = HTTPConnection("host") # $ clientRequestUrlPart="host"
conn.request("GET", url) # $ clientRequestUrlPart=url
resp = conn.getresponse()
ensure_tainted(resp) # $ tainted
conn = HTTPConnection(host) # $ clientRequestUrlPart=host
conn.request("GET", "url") # $ clientRequestUrlPart="url"
resp = conn.getresponse()
ensure_tainted(resp) # $ tainted

View File

@@ -1,274 +0,0 @@
edges
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:8:17:8:23 | ControlFlowNode for request |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript |
| full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:13:18:13:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:13:18:13:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:19:18:19:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:19:18:19:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:23:18:23:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:23:18:23:20 | ControlFlowNode for url |
| full_partial_test.py:8:17:8:23 | ControlFlowNode for request | full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute |
| full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute | full_partial_test.py:8:17:8:41 | ControlFlowNode for Subscript |
| full_partial_test.py:8:17:8:41 | ControlFlowNode for Subscript | full_partial_test.py:23:18:23:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:37:18:37:29 | ControlFlowNode for Attribute |
| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:37:18:37:29 | ControlFlowNode for Attribute |
| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:38:17:38:23 | ControlFlowNode for request |
| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:38:17:38:28 | ControlFlowNode for Attribute |
| full_partial_test.py:37:18:37:29 | ControlFlowNode for Attribute | full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript |
| full_partial_test.py:37:18:37:29 | ControlFlowNode for Attribute | full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:42:18:42:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:42:18:42:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:45:18:45:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:45:18:45:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:48:18:48:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:48:18:48:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:51:18:51:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:51:18:51:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:54:18:54:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:54:18:54:20 | ControlFlowNode for url |
| full_partial_test.py:38:17:38:23 | ControlFlowNode for request | full_partial_test.py:38:17:38:28 | ControlFlowNode for Attribute |
| full_partial_test.py:38:17:38:28 | ControlFlowNode for Attribute | full_partial_test.py:38:17:38:41 | ControlFlowNode for Subscript |
| full_partial_test.py:38:17:38:41 | ControlFlowNode for Subscript | full_partial_test.py:48:18:48:20 | ControlFlowNode for url |
| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:57:18:57:29 | ControlFlowNode for Attribute |
| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:57:18:57:29 | ControlFlowNode for Attribute |
| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:58:17:58:23 | ControlFlowNode for request |
| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:58:17:58:28 | ControlFlowNode for Attribute |
| full_partial_test.py:57:18:57:29 | ControlFlowNode for Attribute | full_partial_test.py:57:18:57:48 | ControlFlowNode for Subscript |
| full_partial_test.py:57:18:57:29 | ControlFlowNode for Attribute | full_partial_test.py:57:18:57:48 | ControlFlowNode for Subscript |
| full_partial_test.py:57:18:57:48 | ControlFlowNode for Subscript | full_partial_test.py:62:18:62:20 | ControlFlowNode for url |
| full_partial_test.py:57:18:57:48 | ControlFlowNode for Subscript | full_partial_test.py:62:18:62:20 | ControlFlowNode for url |
| full_partial_test.py:57:18:57:48 | ControlFlowNode for Subscript | full_partial_test.py:65:18:65:20 | ControlFlowNode for url |
| full_partial_test.py:57:18:57:48 | ControlFlowNode for Subscript | full_partial_test.py:65:18:65:20 | ControlFlowNode for url |
| full_partial_test.py:57:18:57:48 | ControlFlowNode for Subscript | full_partial_test.py:67:38:67:58 | ControlFlowNode for Tuple |
| full_partial_test.py:58:17:58:23 | ControlFlowNode for request | full_partial_test.py:58:17:58:28 | ControlFlowNode for Attribute |
| full_partial_test.py:58:17:58:28 | ControlFlowNode for Attribute | full_partial_test.py:58:17:58:41 | ControlFlowNode for Subscript |
| full_partial_test.py:58:17:58:41 | ControlFlowNode for Subscript | full_partial_test.py:67:38:67:58 | ControlFlowNode for Tuple |
| full_partial_test.py:67:38:67:58 | ControlFlowNode for Tuple | full_partial_test.py:68:18:68:20 | ControlFlowNode for url |
| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:71:18:71:29 | ControlFlowNode for Attribute |
| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:71:18:71:29 | ControlFlowNode for Attribute |
| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:72:17:72:23 | ControlFlowNode for request |
| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:72:17:72:28 | ControlFlowNode for Attribute |
| full_partial_test.py:71:18:71:29 | ControlFlowNode for Attribute | full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript |
| full_partial_test.py:71:18:71:29 | ControlFlowNode for Attribute | full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript |
| full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript | full_partial_test.py:76:18:76:20 | ControlFlowNode for url |
| full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript | full_partial_test.py:76:18:76:20 | ControlFlowNode for url |
| full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript | full_partial_test.py:79:18:79:20 | ControlFlowNode for url |
| full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript | full_partial_test.py:79:18:79:20 | ControlFlowNode for url |
| full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript | full_partial_test.py:82:18:82:20 | ControlFlowNode for url |
| full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript | full_partial_test.py:82:18:82:20 | ControlFlowNode for url |
| full_partial_test.py:72:17:72:23 | ControlFlowNode for request | full_partial_test.py:72:17:72:28 | ControlFlowNode for Attribute |
| full_partial_test.py:72:17:72:28 | ControlFlowNode for Attribute | full_partial_test.py:72:17:72:41 | ControlFlowNode for Subscript |
| full_partial_test.py:72:17:72:41 | ControlFlowNode for Subscript | full_partial_test.py:82:18:82:20 | ControlFlowNode for url |
| full_partial_test.py:86:18:86:24 | ControlFlowNode for request | full_partial_test.py:86:18:86:29 | ControlFlowNode for Attribute |
| full_partial_test.py:86:18:86:29 | ControlFlowNode for Attribute | full_partial_test.py:86:18:86:48 | ControlFlowNode for Subscript |
| full_partial_test.py:86:18:86:48 | ControlFlowNode for Subscript | full_partial_test.py:89:18:89:20 | ControlFlowNode for url |
| full_partial_test.py:92:18:92:24 | ControlFlowNode for request | full_partial_test.py:92:18:92:29 | ControlFlowNode for Attribute |
| full_partial_test.py:92:18:92:29 | ControlFlowNode for Attribute | full_partial_test.py:92:18:92:48 | ControlFlowNode for Subscript |
| full_partial_test.py:92:18:92:48 | ControlFlowNode for Subscript | full_partial_test.py:95:18:95:20 | ControlFlowNode for url |
| full_partial_test.py:98:18:98:24 | ControlFlowNode for request | full_partial_test.py:98:18:98:29 | ControlFlowNode for Attribute |
| full_partial_test.py:98:18:98:29 | ControlFlowNode for Attribute | full_partial_test.py:98:18:98:48 | ControlFlowNode for Subscript |
| full_partial_test.py:98:18:98:48 | ControlFlowNode for Subscript | full_partial_test.py:101:18:101:20 | ControlFlowNode for url |
| full_partial_test.py:104:18:104:24 | ControlFlowNode for request | full_partial_test.py:104:18:104:29 | ControlFlowNode for Attribute |
| full_partial_test.py:104:18:104:29 | ControlFlowNode for Attribute | full_partial_test.py:104:18:104:48 | ControlFlowNode for Subscript |
| full_partial_test.py:104:18:104:48 | ControlFlowNode for Subscript | full_partial_test.py:107:18:107:20 | ControlFlowNode for url |
| full_partial_test.py:110:18:110:24 | ControlFlowNode for request | full_partial_test.py:110:18:110:29 | ControlFlowNode for Attribute |
| full_partial_test.py:110:18:110:29 | ControlFlowNode for Attribute | full_partial_test.py:110:18:110:48 | ControlFlowNode for Subscript |
| full_partial_test.py:110:18:110:48 | ControlFlowNode for Subscript | full_partial_test.py:116:18:116:20 | ControlFlowNode for url |
| full_partial_test.py:119:18:119:24 | ControlFlowNode for request | full_partial_test.py:119:18:119:29 | ControlFlowNode for Attribute |
| full_partial_test.py:119:18:119:29 | ControlFlowNode for Attribute | full_partial_test.py:119:18:119:48 | ControlFlowNode for Subscript |
| full_partial_test.py:119:18:119:48 | ControlFlowNode for Subscript | full_partial_test.py:122:18:122:20 | ControlFlowNode for url |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:25 | ControlFlowNode for request |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:25 | ControlFlowNode for request |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:11:18:11:24 | ControlFlowNode for request |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript |
| test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:11:18:11:24 | ControlFlowNode for request |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript |
| test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:11:18:11:24 | ControlFlowNode for request | test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute |
| test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute | test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript |
| test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | test_http_client.py:33:25:33:28 | ControlFlowNode for path |
| test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | test_http_client.py:37:25:37:28 | ControlFlowNode for path |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute |
| test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript |
| test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript |
| test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | test_requests.py:8:18:8:27 | ControlFlowNode for user_input |
| test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | test_requests.py:8:18:8:27 | ControlFlowNode for user_input |
nodes
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:8:17:8:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:8:17:8:41 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
| full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
| full_partial_test.py:13:18:13:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:13:18:13:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:19:18:19:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:19:18:19:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:23:18:23:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:23:18:23:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:37:18:37:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:37:18:37:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:38:17:38:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:38:17:38:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:38:17:38:41 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:42:18:42:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:42:18:42:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:45:18:45:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:45:18:45:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:48:18:48:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:48:18:48:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:51:18:51:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:51:18:51:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:54:18:54:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:54:18:54:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:57:18:57:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:57:18:57:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:57:18:57:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:57:18:57:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:58:17:58:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:58:17:58:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:58:17:58:41 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:62:18:62:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:62:18:62:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:65:18:65:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:65:18:65:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:67:38:67:58 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
| full_partial_test.py:68:18:68:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:71:18:71:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:71:18:71:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:72:17:72:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:72:17:72:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:72:17:72:41 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:76:18:76:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:76:18:76:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:79:18:79:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:79:18:79:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:82:18:82:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:82:18:82:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:86:18:86:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:86:18:86:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:86:18:86:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:89:18:89:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:92:18:92:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:92:18:92:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:92:18:92:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:95:18:95:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:98:18:98:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:98:18:98:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:98:18:98:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:101:18:101:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:104:18:104:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:104:18:104:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:104:18:104:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:107:18:107:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:110:18:110:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:110:18:110:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:110:18:110:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:116:18:116:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:119:18:119:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:119:18:119:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:119:18:119:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:122:18:122:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:11:18:11:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:33:25:33:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| test_http_client.py:37:25:37:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
| test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
subpaths
#select
| full_partial_test.py:10:5:10:28 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | The full URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:13:5:13:21 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:13:18:13:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:19:5:19:21 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:19:18:19:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:23:5:23:21 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:23:18:23:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:42:5:42:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:42:18:42:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:45:5:45:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:45:18:45:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:48:5:48:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:48:18:48:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:51:5:51:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:51:18:51:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:54:5:54:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:54:18:54:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:62:5:62:21 | ControlFlowNode for Attribute() | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:62:18:62:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:65:5:65:21 | ControlFlowNode for Attribute() | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:65:18:65:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:76:5:76:21 | ControlFlowNode for Attribute() | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:76:18:76:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:79:5:79:21 | ControlFlowNode for Attribute() | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:79:18:79:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:82:5:82:21 | ControlFlowNode for Attribute() | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:82:18:82:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value |
| test_requests.py:8:5:8:28 | ControlFlowNode for Attribute() | test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | The full URL of this request depends on $@. | test_requests.py:6:18:6:24 | ControlFlowNode for request | a user-provided value |

View File

@@ -1 +0,0 @@
Security/CWE-918/FullServerSideRequestForgery.ql

View File

@@ -1,271 +0,0 @@
edges
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:8:17:8:23 | ControlFlowNode for request |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript |
| full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:13:18:13:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:13:18:13:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:19:18:19:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:19:18:19:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:23:18:23:20 | ControlFlowNode for url |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | full_partial_test.py:23:18:23:20 | ControlFlowNode for url |
| full_partial_test.py:8:17:8:23 | ControlFlowNode for request | full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute |
| full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute | full_partial_test.py:8:17:8:41 | ControlFlowNode for Subscript |
| full_partial_test.py:8:17:8:41 | ControlFlowNode for Subscript | full_partial_test.py:23:18:23:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:37:18:37:29 | ControlFlowNode for Attribute |
| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:37:18:37:29 | ControlFlowNode for Attribute |
| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:38:17:38:23 | ControlFlowNode for request |
| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:38:17:38:28 | ControlFlowNode for Attribute |
| full_partial_test.py:37:18:37:29 | ControlFlowNode for Attribute | full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript |
| full_partial_test.py:37:18:37:29 | ControlFlowNode for Attribute | full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:42:18:42:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:42:18:42:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:45:18:45:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:45:18:45:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:48:18:48:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:48:18:48:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:51:18:51:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:51:18:51:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:54:18:54:20 | ControlFlowNode for url |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | full_partial_test.py:54:18:54:20 | ControlFlowNode for url |
| full_partial_test.py:38:17:38:23 | ControlFlowNode for request | full_partial_test.py:38:17:38:28 | ControlFlowNode for Attribute |
| full_partial_test.py:38:17:38:28 | ControlFlowNode for Attribute | full_partial_test.py:38:17:38:41 | ControlFlowNode for Subscript |
| full_partial_test.py:38:17:38:41 | ControlFlowNode for Subscript | full_partial_test.py:48:18:48:20 | ControlFlowNode for url |
| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:57:18:57:29 | ControlFlowNode for Attribute |
| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:57:18:57:29 | ControlFlowNode for Attribute |
| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:58:17:58:23 | ControlFlowNode for request |
| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:58:17:58:28 | ControlFlowNode for Attribute |
| full_partial_test.py:57:18:57:29 | ControlFlowNode for Attribute | full_partial_test.py:57:18:57:48 | ControlFlowNode for Subscript |
| full_partial_test.py:57:18:57:29 | ControlFlowNode for Attribute | full_partial_test.py:57:18:57:48 | ControlFlowNode for Subscript |
| full_partial_test.py:57:18:57:48 | ControlFlowNode for Subscript | full_partial_test.py:62:18:62:20 | ControlFlowNode for url |
| full_partial_test.py:57:18:57:48 | ControlFlowNode for Subscript | full_partial_test.py:62:18:62:20 | ControlFlowNode for url |
| full_partial_test.py:57:18:57:48 | ControlFlowNode for Subscript | full_partial_test.py:65:18:65:20 | ControlFlowNode for url |
| full_partial_test.py:57:18:57:48 | ControlFlowNode for Subscript | full_partial_test.py:65:18:65:20 | ControlFlowNode for url |
| full_partial_test.py:57:18:57:48 | ControlFlowNode for Subscript | full_partial_test.py:67:38:67:58 | ControlFlowNode for Tuple |
| full_partial_test.py:58:17:58:23 | ControlFlowNode for request | full_partial_test.py:58:17:58:28 | ControlFlowNode for Attribute |
| full_partial_test.py:58:17:58:28 | ControlFlowNode for Attribute | full_partial_test.py:58:17:58:41 | ControlFlowNode for Subscript |
| full_partial_test.py:58:17:58:41 | ControlFlowNode for Subscript | full_partial_test.py:67:38:67:58 | ControlFlowNode for Tuple |
| full_partial_test.py:67:38:67:58 | ControlFlowNode for Tuple | full_partial_test.py:68:18:68:20 | ControlFlowNode for url |
| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:71:18:71:29 | ControlFlowNode for Attribute |
| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:71:18:71:29 | ControlFlowNode for Attribute |
| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:72:17:72:23 | ControlFlowNode for request |
| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:72:17:72:28 | ControlFlowNode for Attribute |
| full_partial_test.py:71:18:71:29 | ControlFlowNode for Attribute | full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript |
| full_partial_test.py:71:18:71:29 | ControlFlowNode for Attribute | full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript |
| full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript | full_partial_test.py:76:18:76:20 | ControlFlowNode for url |
| full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript | full_partial_test.py:76:18:76:20 | ControlFlowNode for url |
| full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript | full_partial_test.py:79:18:79:20 | ControlFlowNode for url |
| full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript | full_partial_test.py:79:18:79:20 | ControlFlowNode for url |
| full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript | full_partial_test.py:82:18:82:20 | ControlFlowNode for url |
| full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript | full_partial_test.py:82:18:82:20 | ControlFlowNode for url |
| full_partial_test.py:72:17:72:23 | ControlFlowNode for request | full_partial_test.py:72:17:72:28 | ControlFlowNode for Attribute |
| full_partial_test.py:72:17:72:28 | ControlFlowNode for Attribute | full_partial_test.py:72:17:72:41 | ControlFlowNode for Subscript |
| full_partial_test.py:72:17:72:41 | ControlFlowNode for Subscript | full_partial_test.py:82:18:82:20 | ControlFlowNode for url |
| full_partial_test.py:86:18:86:24 | ControlFlowNode for request | full_partial_test.py:86:18:86:29 | ControlFlowNode for Attribute |
| full_partial_test.py:86:18:86:29 | ControlFlowNode for Attribute | full_partial_test.py:86:18:86:48 | ControlFlowNode for Subscript |
| full_partial_test.py:86:18:86:48 | ControlFlowNode for Subscript | full_partial_test.py:89:18:89:20 | ControlFlowNode for url |
| full_partial_test.py:92:18:92:24 | ControlFlowNode for request | full_partial_test.py:92:18:92:29 | ControlFlowNode for Attribute |
| full_partial_test.py:92:18:92:29 | ControlFlowNode for Attribute | full_partial_test.py:92:18:92:48 | ControlFlowNode for Subscript |
| full_partial_test.py:92:18:92:48 | ControlFlowNode for Subscript | full_partial_test.py:95:18:95:20 | ControlFlowNode for url |
| full_partial_test.py:98:18:98:24 | ControlFlowNode for request | full_partial_test.py:98:18:98:29 | ControlFlowNode for Attribute |
| full_partial_test.py:98:18:98:29 | ControlFlowNode for Attribute | full_partial_test.py:98:18:98:48 | ControlFlowNode for Subscript |
| full_partial_test.py:98:18:98:48 | ControlFlowNode for Subscript | full_partial_test.py:101:18:101:20 | ControlFlowNode for url |
| full_partial_test.py:104:18:104:24 | ControlFlowNode for request | full_partial_test.py:104:18:104:29 | ControlFlowNode for Attribute |
| full_partial_test.py:104:18:104:29 | ControlFlowNode for Attribute | full_partial_test.py:104:18:104:48 | ControlFlowNode for Subscript |
| full_partial_test.py:104:18:104:48 | ControlFlowNode for Subscript | full_partial_test.py:107:18:107:20 | ControlFlowNode for url |
| full_partial_test.py:110:18:110:24 | ControlFlowNode for request | full_partial_test.py:110:18:110:29 | ControlFlowNode for Attribute |
| full_partial_test.py:110:18:110:29 | ControlFlowNode for Attribute | full_partial_test.py:110:18:110:48 | ControlFlowNode for Subscript |
| full_partial_test.py:110:18:110:48 | ControlFlowNode for Subscript | full_partial_test.py:116:18:116:20 | ControlFlowNode for url |
| full_partial_test.py:119:18:119:24 | ControlFlowNode for request | full_partial_test.py:119:18:119:29 | ControlFlowNode for Attribute |
| full_partial_test.py:119:18:119:29 | ControlFlowNode for Attribute | full_partial_test.py:119:18:119:48 | ControlFlowNode for Subscript |
| full_partial_test.py:119:18:119:48 | ControlFlowNode for Subscript | full_partial_test.py:122:18:122:20 | ControlFlowNode for url |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:25 | ControlFlowNode for request |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:25 | ControlFlowNode for request |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:11:18:11:24 | ControlFlowNode for request |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript |
| test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:11:18:11:24 | ControlFlowNode for request |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript |
| test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:11:18:11:24 | ControlFlowNode for request | test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute |
| test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute | test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript |
| test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | test_http_client.py:33:25:33:28 | ControlFlowNode for path |
| test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | test_http_client.py:37:25:37:28 | ControlFlowNode for path |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute |
| test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript |
| test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript |
| test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | test_requests.py:8:18:8:27 | ControlFlowNode for user_input |
| test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | test_requests.py:8:18:8:27 | ControlFlowNode for user_input |
nodes
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:7:18:7:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:8:17:8:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:8:17:8:41 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
| full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
| full_partial_test.py:13:18:13:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:13:18:13:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:19:18:19:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:19:18:19:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:23:18:23:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:23:18:23:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:37:18:37:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:37:18:37:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:37:18:37:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:38:17:38:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:38:17:38:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:38:17:38:41 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:42:18:42:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:42:18:42:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:45:18:45:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:45:18:45:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:48:18:48:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:48:18:48:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:51:18:51:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:51:18:51:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:54:18:54:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:54:18:54:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:57:18:57:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:57:18:57:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:57:18:57:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:57:18:57:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:58:17:58:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:58:17:58:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:58:17:58:41 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:62:18:62:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:62:18:62:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:65:18:65:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:65:18:65:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:67:38:67:58 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
| full_partial_test.py:68:18:68:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:71:18:71:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:71:18:71:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:71:18:71:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:72:17:72:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:72:17:72:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:72:17:72:41 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:76:18:76:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:76:18:76:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:79:18:79:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:79:18:79:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:82:18:82:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:82:18:82:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:86:18:86:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:86:18:86:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:86:18:86:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:89:18:89:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:92:18:92:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:92:18:92:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:92:18:92:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:95:18:95:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:98:18:98:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:98:18:98:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:98:18:98:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:101:18:101:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:104:18:104:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:104:18:104:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:104:18:104:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:107:18:107:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:110:18:110:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:110:18:110:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:110:18:110:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:116:18:116:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:119:18:119:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:119:18:119:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| full_partial_test.py:119:18:119:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| full_partial_test.py:122:18:122:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:9:19:9:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:10:19:10:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:11:18:11:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:33:25:33:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| test_http_client.py:37:25:37:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
| test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
subpaths
#select
| full_partial_test.py:68:5:68:21 | ControlFlowNode for Attribute() | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:68:18:68:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:68:5:68:21 | ControlFlowNode for Attribute() | full_partial_test.py:58:17:58:23 | ControlFlowNode for request | full_partial_test.py:68:18:68:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:58:17:58:23 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:89:5:89:21 | ControlFlowNode for Attribute() | full_partial_test.py:86:18:86:24 | ControlFlowNode for request | full_partial_test.py:89:18:89:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:86:18:86:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:95:5:95:21 | ControlFlowNode for Attribute() | full_partial_test.py:92:18:92:24 | ControlFlowNode for request | full_partial_test.py:95:18:95:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:92:18:92:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:101:5:101:21 | ControlFlowNode for Attribute() | full_partial_test.py:98:18:98:24 | ControlFlowNode for request | full_partial_test.py:101:18:101:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:98:18:98:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:107:5:107:21 | ControlFlowNode for Attribute() | full_partial_test.py:104:18:104:24 | ControlFlowNode for request | full_partial_test.py:107:18:107:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:104:18:104:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:116:5:116:21 | ControlFlowNode for Attribute() | full_partial_test.py:110:18:110:24 | ControlFlowNode for request | full_partial_test.py:116:18:116:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:110:18:110:24 | ControlFlowNode for request | a user-provided value |
| full_partial_test.py:122:5:122:21 | ControlFlowNode for Attribute() | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | full_partial_test.py:122:18:122:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:22:5:22:31 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | Part of the URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:26:5:26:31 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | Part of the URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:29:5:29:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | Part of the URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:29:5:29:36 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | Part of the URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:33:5:33:29 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:33:25:33:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:33:5:33:29 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:33:25:33:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:33:5:33:29 | ControlFlowNode for Attribute() | test_http_client.py:11:18:11:24 | ControlFlowNode for request | test_http_client.py:33:25:33:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:11:18:11:24 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:37:5:37:29 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:37:25:37:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:37:5:37:29 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:37:25:37:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value |
| test_http_client.py:37:5:37:29 | ControlFlowNode for Attribute() | test_http_client.py:11:18:11:24 | ControlFlowNode for request | test_http_client.py:37:25:37:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:11:18:11:24 | ControlFlowNode for request | a user-provided value |

View File

@@ -1 +0,0 @@
Security/CWE-918/PartialServerSideRequestForgery.ql

View File

@@ -1,122 +0,0 @@
from flask import request
import requests
def full_ssrf():
user_input = request.args['untrusted_input']
query_val = request.args['query_val']
requests.get(user_input) # NOT OK -- user has full control
url = "https://" + user_input
requests.get(url) # NOT OK -- user has full control
# although the path `/foo` is added here, this can be circumvented such that the
# final URL is `https://evil.com/#/foo" -- since the fragment (#) is not sent to the
# server.
url = "https://" + user_input + "/foo"
requests.get(url) # NOT OK -- user has full control
# this might seem like a dummy test, but it serves to check how our sanitizers work.
url = "https://" + user_input + "/foo?key=" + query_val
requests.get(url) # NOT OK -- user has full control
# taint-steps are added as `fromNode -> toNode`, but when adding a sanitizer it's
# currently only possible to so on either `fromNode` or `toNode` (either all edges in
# and out, or just the edges in or out). The sanitizers for full URL control is applied
# on the `fromNode`, since for `"https://{}/{}".format(user_input1, user_input2)` there
# is still a valid taint-step for `user_input1` -- if we made `toNode` a sanitizer that
# would also remove this flow that we actually want. When coupled with use-use flow,
# this means that later uses of a sanitized value will no longer be tainted, so
# `requests.get(user_input2)` would no longer give an alert. To overcome this problem,
# we split these tests into multiple functions, so we do not get this use-use flow, and
# therefore know we are able to see where the sanitizers are applied.
def full_ssrf_format():
user_input = request.args['untrusted_input']
query_val = request.args['query_val']
# using .format
url = "https://{}".format(user_input)
requests.get(url) # NOT OK -- user has full control
url = "https://{}/foo".format(user_input)
requests.get(url) # NOT OK -- user has full control
url = "https://{}/foo?key={}".format(user_input, query_val)
requests.get(url) # NOT OK -- user has full control
url = "https://{x}".format(x=user_input)
requests.get(url) # NOT OK -- user has full control
url = "https://{1}".format(0, user_input)
requests.get(url) # NOT OK -- user has full control
def full_ssrf_percent_format():
user_input = request.args['untrusted_input']
query_val = request.args['query_val']
# using %-formatting
url = "https://%s" % user_input
requests.get(url) # NOT OK -- user has full control
url = "https://%s/foo" % user_input
requests.get(url) # NOT OK -- user has full control
url = "https://%s/foo/key=%s" % (user_input, query_val)
requests.get(url) # NOT OK -- user has full control
def full_ssrf_f_strings():
user_input = request.args['untrusted_input']
query_val = request.args['query_val']
# using f-strings
url = f"https://{user_input}"
requests.get(url) # NOT OK -- user has full control
url = f"https://{user_input}/foo"
requests.get(url) # NOT OK -- user has full control
url = f"https://{user_input}/foo?key={query_val}"
requests.get(url) # NOT OK -- user has full control
def partial_ssrf_1():
user_input = request.args['untrusted_input']
url = "https://example.com/foo?" + user_input
requests.get(url) # NOT OK -- user controls query parameters
def partial_ssrf_2():
user_input = request.args['untrusted_input']
url = "https://example.com/" + user_input
requests.get(url) # NOT OK -- user controls path
def partial_ssrf_3():
user_input = request.args['untrusted_input']
url = "https://example.com/" + user_input
requests.get(url) # NOT OK -- user controls path
def partial_ssrf_4():
user_input = request.args['untrusted_input']
url = "https://example.com/foo#{}".format(user_input)
requests.get(url) # NOT OK -- user contollred fragment
def partial_ssrf_5():
user_input = request.args['untrusted_input']
# this is probably the least interesting one, since it's only the fragment that is
# controlled
url = "https://example.com/foo#%s" % user_input
requests.get(url) # NOT OK -- user contollred fragment
def partial_ssrf_6():
user_input = request.args['untrusted_input']
url = f"https://example.com/foo#{user_input}"
requests.get(url) # NOT OK -- user only controlled fragment

View File

@@ -1 +0,0 @@
semmle-extractor-options: --lang=3 --max-import-depth=1

View File

@@ -1,37 +0,0 @@
from flask import Flask, request
from http.client import HTTPConnection
app = Flask(__name__)
@app.route("/ssrf_test") # $ routeSetup="/ssrf_test"
def ssrf_test():
unsafe_host = request.args["host"]
unsafe_path = request.args["path"]
user_input = request.args['untrusted_input']
conn = HTTPConnection(unsafe_host)
conn.request("GET", unsafe_path) # NOT OK -- user has full control
# Full SSRF variant, where there is ALSO made a request with fixed URL on the same
# connection later on. This should not change anything on the overall SSRF alerts.
conn = HTTPConnection(unsafe_host)
conn.request("GET", unsafe_path) # NOT OK -- user has full control
# partial SSRF on SAME connection
conn.request("GET", "/foo") # NOT OK -- user has control of host
# the rest are partial SSRF
conn = HTTPConnection(unsafe_host)
conn.request("GET", "/foo") # NOT OK -- user controlled domain
conn = HTTPConnection("example.com")
conn.request("GET", unsafe_path) # NOT OK -- user controlled path
path = "foo?" + user_input
conn = HTTPConnection("example.com")
conn.request("GET", path) # NOT OK -- user controlled query parameters
path = "foo#" + user_input
conn = HTTPConnection("example.com")
conn.request("GET", path) # NOT OK -- user controlled fragment

View File

@@ -1,11 +0,0 @@
from flask import request
import requests
def ssrf_test():
user_input = request.args['untrusted_input']
requests.get(user_input) # NOT OK -- user has full control
# since `requests`` always uses complete URLs, it's not interesting to test more of
# the framework directly. See `full_partial_test.py` for different ways to do SSRF.

BIN
ql/Cargo.lock generated

Binary file not shown.

View File

@@ -1,6 +1,5 @@
[workspace]
members = [
"autobuilder",
"extractor",
"generator",
"node-types",

View File

@@ -1,9 +0,0 @@
[package]
name = "ql-autobuilder"
version = "0.1.0"
authors = ["GitHub"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@@ -1,43 +0,0 @@
use std::env;
use std::path::PathBuf;
use std::process::Command;
fn main() -> std::io::Result<()> {
let dist = env::var("CODEQL_DIST").expect("CODEQL_DIST not set");
let db = env::var("CODEQL_EXTRACTOR_QL_WIP_DATABASE")
.expect("CODEQL_EXTRACTOR_QL_WIP_DATABASE not set");
let codeql = if env::consts::OS == "windows" {
"codeql.exe"
} else {
"codeql"
};
let codeql: PathBuf = [&dist, codeql].iter().collect();
let mut cmd = Command::new(codeql);
cmd.arg("database")
.arg("index-files")
.arg("--size-limit=5m")
.arg("--language=ql")
.arg("--working-dir=.")
.arg(db);
let mut has_include_dir = false; // TODO: This is a horrible hack, wait for the post-merge discussion in https://github.com/github/codeql/pull/7444 to be resolved
for line in env::var("LGTM_INDEX_FILTERS")
.unwrap_or_default()
.split('\n')
{
if let Some(stripped) = line.strip_prefix("include:") {
cmd.arg("--include").arg(stripped);
has_include_dir = true;
} else if let Some(stripped) = line.strip_prefix("exclude:") {
cmd.arg("--exclude").arg(stripped);
}
}
if !has_include_dir {
cmd.arg("--include-extension=.ql")
.arg("--include-extension=.qll")
.arg("--include-extension=.dbscheme")
.arg("--include=**/qlpack.yml");
}
let exit = &cmd.spawn()?.wait()?;
std::process::exit(exit.code().unwrap_or(1))
}

View File

@@ -11,4 +11,3 @@ cp codeql-extractor.yml, ql\src\ql.dbscheme, ql\src\ql.dbscheme.stats extractor-
cp -Recurse tools extractor-pack
mkdir extractor-pack\tools\win64 | Out-Null
cp target\release\ql-extractor.exe extractor-pack\tools\win64\extractor.exe
cp target\release\ql-autobuilder.exe extractor-pack\tools\win64\autobuilder.exe

View File

@@ -20,4 +20,3 @@ mkdir -p extractor-pack
cp -r codeql-extractor.yml tools ql/src/ql.dbscheme ql/src/ql.dbscheme.stats extractor-pack/
mkdir -p extractor-pack/tools/${platform}
cp target/release/ql-extractor extractor-pack/tools/${platform}/extractor
cp target/release/ql-autobuilder extractor-pack/tools/${platform}/autobuilder

View File

@@ -13,7 +13,7 @@ tree-sitter = "0.19"
tree-sitter-ql = { git = "https://github.com/tausbn/tree-sitter-ql.git", rev = "36bdc0eae196f9833182ce3f8932be63534121b3" }
clap = "2.33"
tracing = "0.1"
tracing-subscriber = { version = "0.3.3", features = ["env-filter"] }
tracing-subscriber = { version = "0.2", features = ["env-filter"] }
rayon = "1.5.0"
num_cpus = "1.13.0"
regex = "1.4.3"

View File

@@ -127,15 +127,6 @@ fn main() -> std::io::Result<()> {
lines
.par_iter()
.try_for_each(|line| {
// only consider files that end with .ql/.qll/.dbscheme/qlpack.yml
// TODO: This is a bad fix, wait for the post-merge discussion in https://github.com/github/codeql/pull/7444 to be resolved
if !line.ends_with(".ql")
&& !line.ends_with(".qll")
&& !line.ends_with(".dbscheme")
&& !line.ends_with("qlpack.yml")
{
return Ok(());
}
let path = PathBuf::from(line).canonicalize()?;
let src_archive_file = path_for(&src_archive_dir, &path, "");
let source = std::fs::read(&path)?;

View File

@@ -10,5 +10,5 @@ edition = "2018"
clap = "2.33"
node-types = { path = "../node-types" }
tracing = "0.1"
tracing-subscriber = { version = "0.3.3", features = ["env-filter"] }
tracing-subscriber = { version = "0.2", features = ["env-filter"] }
tree-sitter-ql = { git = "https://github.com/tausbn/tree-sitter-ql.git", rev = "36bdc0eae196f9833182ce3f8932be63534121b3" }

View File

@@ -8,4 +8,4 @@ edition = "2018"
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_json = "1.0"

View File

@@ -58,9 +58,9 @@ class AstNode extends TAstNode {
*/
cached
AstNode getAChild(string pred) {
pred = directMember("getAnAnnotation") and result = this.getAnAnnotation()
pred = directMember("getAnAnnotation") and result = getAnAnnotation()
or
pred = directMember("getQLDoc") and result = this.getQLDoc()
pred = directMember("getQLDoc") and result = getQLDoc()
}
/**
@@ -606,7 +606,7 @@ class FieldDecl extends TFieldDecl, AstNode {
/** Holds if this field is annotated as overriding another field. */
predicate isOverride() { this.hasAnnotation("override") }
string getName() { result = this.getVarDecl().getName() }
string getName() { result = getVarDecl().getName() }
override QLDoc getQLDoc() { result = any(Class c).getQLDocFor(this) }
}
@@ -673,7 +673,7 @@ class Module extends TModule, ModuleDeclaration {
override string getAPrimaryQlClass() { result = "Module" }
override string getName() { result = mod.getName().getChild().getValue() }
override string getName() { result = mod.getName().(QL::ModuleName).getChild().getValue() }
/**
* Gets a member of the module.
@@ -699,7 +699,7 @@ class Module extends TModule, ModuleDeclaration {
}
/**
* A member of a module.
* Something that can be member of a module.
*/
class ModuleMember extends TModuleMember, AstNode {
/** Holds if this member is declared as `private`. */
@@ -771,7 +771,7 @@ class Class extends TClass, TypeDeclaration, ModuleDeclaration {
/**
* Gets a field in this class.
*/
FieldDecl getAField() { result = this.getMember(_) }
FieldDecl getAField() { result = getMember(_) }
/**
* Gets a super-type referenced in the `extends` part of the class declaration.
@@ -814,7 +814,7 @@ class Class extends TClass, TypeDeclaration, ModuleDeclaration {
}
/** Holds if this class is abstract. */
predicate isAbstract() { this.hasAnnotation("abstract") }
predicate isAbstract() { hasAnnotation("abstract") }
}
/**

View File

@@ -105,7 +105,7 @@ private predicate resolveQualifiedName(Import imp, ContainerOrModule m, int i) {
(
exists(Container c, Container parent |
// should ideally look at `qlpack.yml` files
parent = pragma[only_bind_out](imp.getLocation()).getFile().getParentContainer+() and
parent = imp.getLocation().getFile().getParentContainer+() and
exists(YAML::QLPack pack |
pack.getFile().getParentContainer() = parent and
c.getParentContainer() = pack.getADependency*().getFile().getParentContainer()
@@ -122,8 +122,7 @@ private predicate resolveQualifiedName(Import imp, ContainerOrModule m, int i) {
definesModule(container, q, m, _) and
(
exists(container.(Folder_).getFolder().getFile("qlpack.yml")) or
container.(Folder_).getFolder() =
pragma[only_bind_out](imp.getLocation()).getFile().getParentContainer() or
container.(Folder_).getFolder() = imp.getLocation().getFile().getParentContainer() or
not container instanceof Folder_
)
)
@@ -195,7 +194,7 @@ private module Cached {
not m = TFile(any(File f | f.getExtension() = "ql")) and
not exists(me.getQualifier()) and
exists(ContainerOrModule enclosing, string name | resolveModuleExprHelper(me, enclosing, name) |
definesModule(enclosing, name, m, _)
definesModule(enclosing.getEnclosing*(), name, m, _)
)
or
exists(FileOrModule mid |
@@ -206,7 +205,7 @@ private module Cached {
pragma[noinline]
private predicate resolveModuleExprHelper(ModuleExpr me, ContainerOrModule enclosing, string name) {
enclosing = getEnclosingModule(me).getEnclosing*() and
enclosing = getEnclosingModule(me) and
name = me.getName()
}
}

View File

@@ -17,7 +17,9 @@ import codeql.IDEContextual
*/
external string selectedSourceFile();
// Overrides the configuration to print only nodes in the selected source file.
/**
* Overrides the configuration to print only nodes in the selected source file.
*/
class Cfg extends PrintAstConfiguration {
override predicate shouldPrintNode(AstNode n) {
super.shouldPrintNode(n) and

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,7 @@ where
pred.getParent().getName() = className and
pred.getName() = "getAPrimaryQlClass" and
constant = pred.getBody().(ComparisonFormula).getRightOperand() and
constant.getValue() = constantName and
constant.(String).getValue() = constantName and
// might be "Foo::classname", detect by matching with a regexp
not constantName.regexpMatch(".*\\b" + className + "$") and
// ignore constants with "?" in them

View File

@@ -19,31 +19,12 @@ private predicate getAnOverridingParameter(
parameter = pred.getParameter(index)
}
pragma[noinline]
private predicate getAnOverridingParameterWithDifferentNames(
ClassPredicate pred, ClassPredicate sup, VarDecl parameter, int index
) {
from ClassPredicate pred, ClassPredicate sup, VarDecl parameter, int index
where
getAnOverridingParameter(pred, sup, parameter, index) and
sup.getParameter(index).getName() != pred.getParameter(index).getName() and
exists(int other | other != index |
sup.getParameter(other).getName() = pred.getParameter(index).getName()
)
}
pragma[noinline]
private predicate getAnOverridingParameterWithDifferentNames2(
ClassPredicate pred, ClassPredicate sup, VarDecl parameter, int index, string supName,
string predName
) {
getAnOverridingParameterWithDifferentNames(pred, sup, parameter, index) and
supName = pragma[only_bind_out](pragma[only_bind_out](sup).getParameter(index)).getName() and
predName = pragma[only_bind_out](pragma[only_bind_out](pred).getParameter(index)).getName()
}
from
ClassPredicate pred, ClassPredicate sup, VarDecl parameter, int index, string supName,
string predName
where
getAnOverridingParameterWithDifferentNames2(pred, sup, parameter, index, supName, predName) and
supName != predName
select parameter, predName + " was $@ in the super class.", sup.getParameter(index),
"named " + supName
select parameter, pred.getParameter(index).getName() + " was $@ in the super class.",
sup.getParameter(index), "named " + sup.getParameter(index).getName()

View File

@@ -14,7 +14,7 @@ predicate non_us_word(string wrong, string right) {
exists(string s |
wrong = s.splitAt("/", 0) and
right = s.splitAt("/", 1) and
s = ["colour/color", "authorise/authorize", "analyse/analyze", "behaviour/behavior"]
s = ["colour/color", "authorise/authorize", "analyse/analyze"]
)
}

View File

@@ -1,5 +1,12 @@
@echo off
type NUL && "%CODEQL_EXTRACTOR_QL_ROOT%\tools\%CODEQL_PLATFORM%\autobuilder"
type NUL && "%CODEQL_DIST%\codeql.exe" database index-files ^
--include-extension=.ql ^
--include-extension=.qll ^
--include-extension=.dbscheme ^
--include=**/qlpack.yml ^
--size-limit=5m ^
--language=ql ^
"%CODEQL_EXTRACTOR_QL_WIP_DATABASE%"
exit /b %ERRORLEVEL%

View File

@@ -1,4 +1,13 @@
#!/bin/sh
exec "${CODEQL_EXTRACTOR_QL_ROOT}/tools/${CODEQL_PLATFORM}/autobuilder"
set -eu
exec "${CODEQL_DIST}/codeql" database index-files \
--include-extension=.ql \
--include-extension=.qll \
--include-extension=.dbscheme \
--include=**/qlpack.yml \
--size-limit=5m \
--language=ql \
--working-dir=.\
"$CODEQL_EXTRACTOR_QL_WIP_DATABASE"

View File

@@ -644,32 +644,3 @@ module Path {
abstract class Range extends DataFlow::Node { }
}
}
/**
* A data-flow node that logs data.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `Logging::Range` instead.
*/
class Logging extends DataFlow::Node {
Logging::Range range;
Logging() { this = range }
/** Gets an input that is logged. */
DataFlow::Node getAnInput() { result = range.getAnInput() }
}
/** Provides a class for modeling new logging mechanisms. */
module Logging {
/**
* A data-flow node that logs data.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `Logging` instead.
*/
abstract class Range extends DataFlow::Node {
/** Gets an input that is logged. */
abstract DataFlow::Node getAnInput();
}
}

View File

@@ -23,7 +23,7 @@ private newtype TCompletion =
TRetryCompletion() or
TRaiseCompletion() or // TODO: Add exception type?
TExitCompletion() or
TNestedCompletion(TCompletion inner, TCompletion outer, int nestLevel) {
TNestedCompletion(Completion inner, Completion outer, int nestLevel) {
inner = TBreakCompletion() and
outer instanceof NonNestedNormalCompletion and
nestLevel = 0
@@ -37,7 +37,7 @@ private newtype TCompletion =
}
pragma[noinline]
private predicate nestedEnsureCompletion(TCompletion outer, int nestLevel) {
private predicate nestedEnsureCompletion(Completion outer, int nestLevel) {
(
outer = TReturnCompletion()
or

View File

@@ -15,23 +15,11 @@ module Consistency {
class ConsistencyConfiguration extends TConsistencyConfiguration {
string toString() { none() }
/** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */
predicate uniqueEnclosingCallableExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */
predicate uniqueNodeLocationExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `missingLocation`. */
predicate missingLocationExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `postWithInFlow`. */
predicate postWithInFlowExclude(Node n) { none() }
/** Holds if `n` should be excluded from the consistency test `argHasPostUpdate`. */
predicate argHasPostUpdateExclude(ArgumentNode n) { none() }
/** Holds if `n` should be excluded from the consistency test `reverseRead`. */
predicate reverseReadExclude(Node n) { none() }
}
private class RelevantNode extends Node {
@@ -58,7 +46,6 @@ module Consistency {
n instanceof RelevantNode and
c = count(nodeGetEnclosingCallable(n)) and
c != 1 and
not any(ConsistencyConfiguration conf).uniqueEnclosingCallableExclude(n) and
msg = "Node should have one enclosing callable but has " + c + "."
)
}
@@ -79,7 +66,6 @@ module Consistency {
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
) and
c != 1 and
not any(ConsistencyConfiguration conf).uniqueNodeLocationExclude(n) and
msg = "Node should have one location but has " + c + "."
)
}
@@ -90,8 +76,7 @@ module Consistency {
strictcount(Node n |
not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
) and
not any(ConsistencyConfiguration conf).missingLocationExclude(n)
)
) and
msg = "Nodes without location: " + c
)
@@ -187,7 +172,6 @@ module Consistency {
query predicate reverseRead(Node n, string msg) {
exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and
not any(ConsistencyConfiguration conf).reverseReadExclude(n) and
msg = "Origin of readStep is missing a PostUpdateNode."
}

View File

@@ -3,8 +3,6 @@ private import codeql.ruby.Concepts
private import codeql.ruby.DataFlow
private import codeql.ruby.ApiGraphs
private import codeql.ruby.dataflow.FlowSummary
private import codeql.ruby.dataflow.internal.DataFlowDispatch
private import codeql.ruby.CFG
/**
* The `Kernel` module is included by the `Object` class, so its methods are available
@@ -349,103 +347,3 @@ class RegexpEscapeSummary extends SummarizedCallable {
preservesValue = false
}
}
/** A reference to a `Logger` instance */
private DataFlow::Node loggerInstance() {
result = API::getTopLevelMember("Logger").getAnInstantiation()
or
exists(DataFlow::Node inst |
inst = loggerInstance() and
inst.(DataFlow::LocalSourceNode).flowsTo(result)
)
or
// Assume that a variable assigned as a `Logger` instance is always a
// `Logger` instance. This covers class and instance variables where we can't
// necessarily trace a dataflow path from assignment to use.
exists(Variable v, Assignment a |
a.getLeftOperand().getAVariable() = v and
a.getRightOperand() = loggerInstance().asExpr().getExpr() and
result.asExpr().getExpr().(VariableReadAccess).getVariable() = v
)
}
/**
* A call to a `Logger` instance method that causes a message to be logged.
*/
abstract class LoggerLoggingCall extends Logging::Range, DataFlow::CallNode {
LoggerLoggingCall() { this.getReceiver() = loggerInstance() }
}
/**
* A call to `Logger#add` or its alias `Logger#log`.
*/
private class LoggerAddCall extends LoggerLoggingCall {
LoggerAddCall() { this.getMethodName() = ["add", "log"] }
override DataFlow::Node getAnInput() {
// Both the message and the progname are form part of the log output:
// Logger#add(severity, message) / Logger#add(severity, message, progname)
result = this.getArgument(1)
or
result = this.getArgument(2)
or
// a return value from the block in Logger#add(severity) <block> or in
// Logger#add(severity, nil, progname) <block>
(
this.getNumberOfArguments() = 1
or
// TODO: this could track the value of the `message` argument to make
// this check more accurate
this.getArgument(1).asExpr().getExpr() instanceof NilLiteral
) and
exprNodeReturnedFrom(result, this.getBlock().asExpr().getExpr())
}
}
/**
* A call to `Logger#<<`.
*/
private class LoggerPushCall extends LoggerLoggingCall {
LoggerPushCall() { this.getMethodName() = "<<" }
override DataFlow::Node getAnInput() {
// Logger#<<(msg)
result = this.getArgument(0)
}
}
/**
* A call to a `Logger` method that logs at a preset severity level.
*
* Specifically, these methods are `debug`, `error`, `fatal`, `info`,
* `unknown`, and `warn`.
*/
private class LoggerInfoStyleCall extends LoggerLoggingCall {
LoggerInfoStyleCall() {
this.getMethodName() = ["debug", "error", "fatal", "info", "unknown", "warn"]
}
override DataFlow::Node getAnInput() {
// `msg` from `Logger#info(msg)`,
// or `progname` from `Logger#info(progname) <block>`
result = this.getArgument(0)
or
// a return value from the block in `Logger#info(progname) <block>`
exprNodeReturnedFrom(result, this.getBlock().asExpr().getExpr())
}
}
/**
* A call to `Logger#progname=`. This sets a default progname.
* This call does not log anything directly, but the assigned value can appear
* in future log messages that do not specify a `progname` argument.
*/
private class LoggerSetPrognameCall extends LoggerLoggingCall {
LoggerSetPrognameCall() { this.getMethodName() = "progname=" }
override DataFlow::Node getAnInput() {
exists(CfgNodes::ExprNodes::AssignExprCfgNode a | this.getArgument(0).asExpr() = a |
result.asExpr() = a.getRhs()
)
}
}

Some files were not shown because too many files have changed in this diff Show More