mirror of
https://github.com/github/codeql.git
synced 2026-06-10 23:41:09 +02:00
Compare commits
3 Commits
copilot/ad
...
yoff/pytho
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b473e3763 | ||
|
|
a13dfaa44f | ||
|
|
ac5fa629ef |
208
.github/workflows/go-version-update.yml
vendored
208
.github/workflows/go-version-update.yml
vendored
@@ -1,208 +0,0 @@
|
||||
name: Update Go version
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 3 * * 1" # Run weekly on Mondays at 3 AM UTC (1 = Monday)
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
update-go-version:
|
||||
name: Check and update Go version
|
||||
if: github.repository == 'github/codeql'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Git
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
- name: Fetch latest Go version
|
||||
id: fetch-version
|
||||
run: |
|
||||
LATEST_GO_VERSION=$(curl -s https://go.dev/dl/?mode=json | jq -r '.[0].version')
|
||||
|
||||
if [ -z "$LATEST_GO_VERSION" ] || [ "$LATEST_GO_VERSION" = "null" ]; then
|
||||
echo "Error: Failed to fetch latest Go version from go.dev"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Latest Go version from go.dev: $LATEST_GO_VERSION"
|
||||
echo "version=$LATEST_GO_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
# Extract version numbers (e.g., go1.26.0 -> 1.26.0)
|
||||
LATEST_VERSION_NUM=$(echo $LATEST_GO_VERSION | sed 's/^go//')
|
||||
echo "version_num=$LATEST_VERSION_NUM" >> $GITHUB_OUTPUT
|
||||
|
||||
# Extract major.minor version (e.g., 1.26.0 -> 1.26)
|
||||
LATEST_MAJOR_MINOR=$(echo $LATEST_VERSION_NUM | sed -E 's/^([0-9]+\.[0-9]+).*/\1/')
|
||||
echo "major_minor=$LATEST_MAJOR_MINOR" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Check current Go version
|
||||
id: current-version
|
||||
run: |
|
||||
CURRENT_VERSION=$(sed -n 's/.*go_sdk\.download(version = \"\([^\"]*\)\".*/\1/p' MODULE.bazel)
|
||||
|
||||
if [ -z "$CURRENT_VERSION" ]; then
|
||||
echo "Error: Could not extract Go version from MODULE.bazel"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Current Go version in MODULE.bazel: $CURRENT_VERSION"
|
||||
echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
# Extract major.minor version
|
||||
CURRENT_MAJOR_MINOR=$(echo $CURRENT_VERSION | sed -E 's/^([0-9]+\.[0-9]+).*/\1/')
|
||||
echo "major_minor=$CURRENT_MAJOR_MINOR" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Compare versions
|
||||
id: compare
|
||||
run: |
|
||||
LATEST="${{ steps.fetch-version.outputs.version_num }}"
|
||||
CURRENT="${{ steps.current-version.outputs.version }}"
|
||||
|
||||
echo "Latest: $LATEST"
|
||||
echo "Current: $CURRENT"
|
||||
|
||||
if [ "$LATEST" = "$CURRENT" ]; then
|
||||
echo "Go version is up to date"
|
||||
echo "needs_update=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Go version needs update from $CURRENT to $LATEST"
|
||||
echo "needs_update=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Update Go version in files
|
||||
if: steps.compare.outputs.needs_update == 'true'
|
||||
run: |
|
||||
LATEST_VERSION_NUM="${{ steps.fetch-version.outputs.version_num }}"
|
||||
LATEST_MAJOR_MINOR="${{ steps.fetch-version.outputs.major_minor }}"
|
||||
CURRENT_VERSION="${{ steps.current-version.outputs.version }}"
|
||||
CURRENT_MAJOR_MINOR="${{ steps.current-version.outputs.major_minor }}"
|
||||
|
||||
echo "Updating from $CURRENT_VERSION to $LATEST_VERSION_NUM"
|
||||
|
||||
# Escape dots in current version strings for use in sed patterns
|
||||
CURRENT_VERSION_ESCAPED=$(echo "$CURRENT_VERSION" | sed 's/\./\\./g')
|
||||
CURRENT_MAJOR_MINOR_ESCAPED=$(echo "$CURRENT_MAJOR_MINOR" | sed 's/\./\\./g')
|
||||
|
||||
# Update MODULE.bazel
|
||||
sed -i "s/go_sdk\.download(version = \"$CURRENT_VERSION_ESCAPED\")/go_sdk.download(version = \"$LATEST_VERSION_NUM\")/" MODULE.bazel
|
||||
if ! grep -q "go_sdk.download(version = \"$LATEST_VERSION_NUM\")" MODULE.bazel; then
|
||||
echo "Error: Failed to update MODULE.bazel"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Update go/extractor/go.mod
|
||||
if ! sed -i "s/^go $CURRENT_MAJOR_MINOR_ESCAPED\$/go $LATEST_MAJOR_MINOR/" go/extractor/go.mod; then
|
||||
echo "Warning: Failed to update go directive in go.mod"
|
||||
fi
|
||||
if ! sed -i "s/^toolchain go$CURRENT_VERSION_ESCAPED\$/toolchain go$LATEST_VERSION_NUM/" go/extractor/go.mod; then
|
||||
echo "Warning: Failed to update toolchain in go.mod"
|
||||
fi
|
||||
|
||||
# Update go/extractor/autobuilder/build-environment.go
|
||||
if ! sed -i "s/var maxGoVersion = util\.NewSemVer(\"$CURRENT_MAJOR_MINOR_ESCAPED\")/var maxGoVersion = util.NewSemVer(\"$LATEST_MAJOR_MINOR\")/" go/extractor/autobuilder/build-environment.go; then
|
||||
echo "Warning: Failed to update build-environment.go"
|
||||
fi
|
||||
|
||||
# Update go/actions/test/action.yml
|
||||
if ! sed -i "s/default: \"~$CURRENT_VERSION_ESCAPED\"/default: \"~$LATEST_VERSION_NUM\"/" go/actions/test/action.yml; then
|
||||
echo "Warning: Failed to update action.yml"
|
||||
fi
|
||||
|
||||
# Show what changed
|
||||
git diff
|
||||
|
||||
- name: Check for changes
|
||||
id: check-changes
|
||||
if: steps.compare.outputs.needs_update == 'true'
|
||||
run: |
|
||||
if git diff --quiet; then
|
||||
echo "No changes detected"
|
||||
echo "has_changes=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Changes detected"
|
||||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Check for existing PR
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
id: check-pr
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
BRANCH_NAME="workflow/go-version-update"
|
||||
PR_NUMBER=$(gh pr list --head "$BRANCH_NAME" --state open --json number --jq '.[0].number')
|
||||
|
||||
if [ -n "$PR_NUMBER" ]; then
|
||||
echo "Existing PR found: #$PR_NUMBER"
|
||||
echo "pr_exists=true" >> $GITHUB_OUTPUT
|
||||
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "No existing PR found"
|
||||
echo "pr_exists=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Commit and push changes
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
run: |
|
||||
BRANCH_NAME="workflow/go-version-update"
|
||||
LATEST_VERSION_NUM="${{ steps.fetch-version.outputs.version_num }}"
|
||||
LATEST_MAJOR_MINOR="${{ steps.fetch-version.outputs.major_minor }}"
|
||||
|
||||
# Create or switch to branch
|
||||
git checkout -B "$BRANCH_NAME"
|
||||
|
||||
# Stage and commit changes
|
||||
git add MODULE.bazel go/extractor/go.mod go/extractor/autobuilder/build-environment.go go/actions/test/action.yml
|
||||
git commit -m "Go: Update to $LATEST_VERSION_NUM"
|
||||
|
||||
# Push changes
|
||||
git push --force-with-lease origin "$BRANCH_NAME"
|
||||
|
||||
- name: Create or update PR
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
BRANCH_NAME="workflow/go-version-update"
|
||||
LATEST_VERSION_NUM="${{ steps.fetch-version.outputs.version_num }}"
|
||||
CURRENT_VERSION="${{ steps.current-version.outputs.version }}"
|
||||
|
||||
PR_TITLE="Go: Update to $LATEST_VERSION_NUM"
|
||||
|
||||
PR_BODY=$(cat <<EOF
|
||||
This PR updates Go from $CURRENT_VERSION to $LATEST_VERSION_NUM.
|
||||
|
||||
Updated files:
|
||||
- \`MODULE.bazel\` - go_sdk.download version
|
||||
- \`go/extractor/go.mod\` - go directive and toolchain
|
||||
- \`go/extractor/autobuilder/build-environment.go\` - maxGoVersion (only if MAJOR.MINOR changes)
|
||||
- \`go/actions/test/action.yml\` - default go-test-version
|
||||
|
||||
This PR was automatically created by the [Go version update workflow](https://github.com/${{ github.repository }}/blob/main/.github/workflows/go-version-update.yml).
|
||||
EOF
|
||||
)
|
||||
|
||||
if [ "${{ steps.check-pr.outputs.pr_exists }}" = "true" ]; then
|
||||
echo "Updating existing PR #${{ steps.check-pr.outputs.pr_number }}"
|
||||
gh pr edit "${{ steps.check-pr.outputs.pr_number }}" --title "$PR_TITLE" --body "$PR_BODY"
|
||||
else
|
||||
echo "Creating new PR"
|
||||
gh pr create \
|
||||
--title "$PR_TITLE" \
|
||||
--body "$PR_BODY" \
|
||||
--base main \
|
||||
--head "$BRANCH_NAME" \
|
||||
--label "Go"
|
||||
fi
|
||||
@@ -273,7 +273,7 @@ use_repo(
|
||||
)
|
||||
|
||||
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
|
||||
go_sdk.download(version = "1.26.4")
|
||||
go_sdk.download(version = "1.26.0")
|
||||
|
||||
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
|
||||
go_deps.from_file(go_mod = "//go/extractor:go.mod")
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll"
|
||||
],
|
||||
"Bound Java/C#": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/Bound.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/Bound.qll"
|
||||
],
|
||||
"ModulusAnalysis Java/C#": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/ModulusAnalysis.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/ModulusAnalysis.qll"
|
||||
|
||||
@@ -9,7 +9,6 @@ dependencies:
|
||||
codeql/controlflow: ${workspace}
|
||||
codeql/dataflow: ${workspace}
|
||||
codeql/mad: ${workspace}
|
||||
codeql/rangeanalysis: ${workspace}
|
||||
codeql/ssa: ${workspace}
|
||||
codeql/threat-models: ${workspace}
|
||||
codeql/tutorial: ${workspace}
|
||||
|
||||
@@ -4,31 +4,67 @@
|
||||
overlay[local?]
|
||||
module;
|
||||
|
||||
private import csharp as CS
|
||||
private import semmle.code.csharp.dataflow.SSA::Ssa
|
||||
private import semmle.code.csharp.dataflow.internal.rangeanalysis.ConstantUtils as CU
|
||||
private import semmle.code.csharp.dataflow.internal.rangeanalysis.RangeUtils as RU
|
||||
private import semmle.code.csharp.dataflow.internal.rangeanalysis.SsaUtils as SU
|
||||
private import codeql.rangeanalysis.Bound as SharedBound
|
||||
private import internal.rangeanalysis.BoundSpecific
|
||||
|
||||
/** Provides C#-specific definitions for bounds. */
|
||||
private module BoundDefs implements SharedBound::BoundDefinitions<CS::Location> {
|
||||
class Type = CS::Type;
|
||||
private newtype TBound =
|
||||
TBoundZero() or
|
||||
TBoundSsa(SsaVariable v) { v.getSourceVariable().getType() instanceof IntegralType } or
|
||||
TBoundExpr(Expr e) {
|
||||
interestingExprBound(e) and
|
||||
not exists(SsaVariable v | e = v.getAUse())
|
||||
}
|
||||
|
||||
class SsaVariable = SU::SsaVariable;
|
||||
/**
|
||||
* A bound that may be inferred for an expression plus/minus an integer delta.
|
||||
*/
|
||||
abstract class Bound extends TBound {
|
||||
/** Gets a textual representation of this bound. */
|
||||
abstract string toString();
|
||||
|
||||
class SsaSourceVariable = SourceVariable;
|
||||
/** Gets an expression that equals this bound plus `delta`. */
|
||||
abstract Expr getExpr(int delta);
|
||||
|
||||
class Expr = CS::ControlFlowNodes::ExprNode;
|
||||
/** Gets an expression that equals this bound. */
|
||||
Expr getExpr() { result = this.getExpr(0) }
|
||||
|
||||
class IntegralType = CS::IntegralType;
|
||||
|
||||
class ConstantIntegerExpr = CU::ConstantIntegerExpr;
|
||||
|
||||
/** Holds if `e` is a bound expression and it is not an SSA variable read. */
|
||||
predicate interestingExprBound(Expr e) { CU::systemArrayLengthAccess(e.getExpr()) }
|
||||
/** Gets the location of this bound. */
|
||||
abstract Location getLocation();
|
||||
}
|
||||
|
||||
module BoundImpl = SharedBound::Bound<CS::Location, BoundDefs>;
|
||||
/**
|
||||
* The bound that corresponds to the integer 0. This is used to represent all
|
||||
* integer bounds as bounds are always accompanied by an added integer delta.
|
||||
*/
|
||||
class ZeroBound extends Bound, TBoundZero {
|
||||
override string toString() { result = "0" }
|
||||
|
||||
import BoundImpl
|
||||
override Expr getExpr(int delta) { result.(ConstantIntegerExpr).getIntValue() = delta }
|
||||
|
||||
override Location getLocation() { result.hasLocationInfo("", 0, 0, 0, 0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bound corresponding to the value of an SSA variable.
|
||||
*/
|
||||
class SsaBound extends Bound, TBoundSsa {
|
||||
/** Gets the SSA variable that equals this bound. */
|
||||
SsaVariable getSsa() { this = TBoundSsa(result) }
|
||||
|
||||
override string toString() { result = this.getSsa().toString() }
|
||||
|
||||
override Expr getExpr(int delta) { result = this.getSsa().getAUse() and delta = 0 }
|
||||
|
||||
override Location getLocation() { result = this.getSsa().getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bound that corresponds to the value of a specific expression that might be
|
||||
* interesting, but isn't otherwise represented by the value of an SSA variable.
|
||||
*/
|
||||
class ExprBound extends Bound, TBoundExpr {
|
||||
override string toString() { result = this.getExpr().toString() }
|
||||
|
||||
override Expr getExpr(int delta) { this = TBoundExpr(result) and delta = 0 }
|
||||
|
||||
override Location getLocation() { result = this.getExpr().getLocation() }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Provides C#-specific definitions for bounds.
|
||||
*/
|
||||
|
||||
private import csharp as CS
|
||||
private import semmle.code.csharp.dataflow.SSA::Ssa as Ssa
|
||||
private import semmle.code.csharp.dataflow.internal.rangeanalysis.ConstantUtils as CU
|
||||
private import semmle.code.csharp.dataflow.internal.rangeanalysis.RangeUtils as RU
|
||||
private import semmle.code.csharp.dataflow.internal.rangeanalysis.SsaUtils as SU
|
||||
|
||||
class SsaVariable = SU::SsaVariable;
|
||||
|
||||
class Expr = CS::ControlFlowNodes::ExprNode;
|
||||
|
||||
class Location = CS::Location;
|
||||
|
||||
class IntegralType = CS::IntegralType;
|
||||
|
||||
class ConstantIntegerExpr = CU::ConstantIntegerExpr;
|
||||
|
||||
/** Holds if `e` is a bound expression and it is not an SSA variable read. */
|
||||
predicate interestingExprBound(Expr e) { CU::systemArrayLengthAccess(e.getExpr()) }
|
||||
@@ -1,22 +0,0 @@
|
||||
using System.Net.Http;
|
||||
using System.Net.Security;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
public class CertificateValidation
|
||||
{
|
||||
public void Bad()
|
||||
{
|
||||
var handler = new HttpClientHandler();
|
||||
// BAD: the callback always returns true, so every certificate is trusted.
|
||||
handler.ServerCertificateCustomValidationCallback =
|
||||
(request, certificate, chain, errors) => true;
|
||||
}
|
||||
|
||||
public void Good()
|
||||
{
|
||||
var handler = new HttpClientHandler();
|
||||
// GOOD: the certificate is only trusted when there are no validation errors.
|
||||
handler.ServerCertificateCustomValidationCallback =
|
||||
(request, certificate, chain, errors) => errors == SslPolicyErrors.None;
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
A TLS/SSL certificate validation callback that always returns <code>true</code> trusts every certificate,
|
||||
regardless of any validation errors that were detected. This allows an attacker to perform a machine-in-the-middle
|
||||
attack against the application, therefore breaking any security that Transport Layer Security (TLS) provides.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
An attack might look like this:
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<li>The vulnerable program connects to <code>https://example.com</code>.</li>
|
||||
<li>The attacker intercepts this connection and presents a valid, self-signed certificate for <code>https://example.com</code>.</li>
|
||||
<li>The vulnerable program calls the certificate validation callback to check whether it should trust the certificate.</li>
|
||||
<li>The callback ignores the <code>SslPolicyErrors</code> argument and returns <code>true</code>.</li>
|
||||
<li>The vulnerable program accepts the certificate and proceeds with the connection, since the callback indicated that the certificate is trusted.</li>
|
||||
<li>The attacker can now read the data the program sends to <code>https://example.com</code> and/or alter its replies while the program thinks the connection is secure.</li>
|
||||
</ol>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Do not use a certificate validation callback that unconditionally returns <code>true</code>.
|
||||
Either rely on the default certificate validation, or implement a callback that inspects the
|
||||
<code>SslPolicyErrors</code> argument and only trusts a specific, known certificate (for example, when
|
||||
using a self-signed certificate that has been explicitly pinned).
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
In the first (bad) example, the callback always returns <code>true</code> and therefore trusts any certificate,
|
||||
which allows an attacker to perform a machine-in-the-middle attack. In the second (good) example, the callback
|
||||
returns <code>true</code> only when there are no validation errors.
|
||||
</p>
|
||||
<sample src="AcceptAnyCertificate.cs" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Microsoft Learn:
|
||||
<a href="https://learn.microsoft.com/en-us/dotnet/api/system.net.security.remotecertificatevalidationcallback">RemoteCertificateValidationCallback Delegate</a>.</li>
|
||||
<li>Microsoft Learn:
|
||||
<a href="https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca5359">CA5359: Do not disable certificate validation</a>.</li>
|
||||
<li>OWASP:
|
||||
<a href="https://owasp.org/www-community/attacks/Manipulator-in-the-middle_attack">Manipulator-in-the-middle attack</a>.</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -1,101 +0,0 @@
|
||||
/**
|
||||
* @name Accepting any TLS certificate during validation
|
||||
* @description A certificate validation callback that always accepts any certificate
|
||||
* allows an attacker to perform a machine-in-the-middle attack.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 7.5
|
||||
* @precision high
|
||||
* @id cs/accept-any-certificate
|
||||
* @tags security
|
||||
* external/cwe/cwe-295
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.dataflow.DataFlow::DataFlow
|
||||
import AcceptAnyCertificate::PathGraph
|
||||
|
||||
/**
|
||||
* Holds if `c` always returns `true` and never returns `false`, i.e. it accepts
|
||||
* every input it is given.
|
||||
*/
|
||||
predicate alwaysReturnsTrue(Callable c) {
|
||||
c.getReturnType() instanceof BoolType and
|
||||
// There is at least one returned value, and every returned value is the
|
||||
// constant `true`.
|
||||
forex(Expr ret | c.canReturn(ret) | ret.getValue() = "true")
|
||||
}
|
||||
|
||||
/**
|
||||
* A delegate type used as a TLS/SSL certificate validation callback. Such a
|
||||
* delegate returns a `bool` (whether the certificate is trusted) and takes a
|
||||
* `System.Net.Security.SslPolicyErrors` parameter describing any validation
|
||||
* errors that were found. This covers `RemoteCertificateValidationCallback` as
|
||||
* well as the `Func<..., SslPolicyErrors, bool>` callbacks used by, for example,
|
||||
* `HttpClientHandler.ServerCertificateCustomValidationCallback`.
|
||||
*/
|
||||
class CertificateValidationCallbackType extends DelegateType {
|
||||
CertificateValidationCallbackType() {
|
||||
this.getReturnType() instanceof BoolType and
|
||||
this.getAParameter().getType().hasFullyQualifiedName("System.Net.Security", "SslPolicyErrors")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a callable that always accepts any certificate, referenced by the
|
||||
* delegate-producing expression `e`.
|
||||
*/
|
||||
Callable getAcceptingCallable(Expr e) {
|
||||
// A lambda or anonymous method, e.g. `(sender, cert, chain, errors) => true`.
|
||||
result = e and
|
||||
alwaysReturnsTrue(e)
|
||||
or
|
||||
// A method group, e.g. `AcceptAllCertificates`, possibly wrapped in an
|
||||
// (implicit or explicit) delegate creation.
|
||||
result = e.(DelegateCreation).getArgument().(CallableAccess).getTarget() and
|
||||
alwaysReturnsTrue(result)
|
||||
or
|
||||
result = e.(CallableAccess).getTarget() and
|
||||
alwaysReturnsTrue(result)
|
||||
}
|
||||
|
||||
module AcceptAnyCertificateConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(getAcceptingCallable(source.asExpr()))
|
||||
or
|
||||
// `HttpClientHandler.DangerousAcceptAnyServerCertificateValidator` is a
|
||||
// built-in callback that accepts every certificate.
|
||||
source
|
||||
.asExpr()
|
||||
.(PropertyAccess)
|
||||
.getTarget()
|
||||
.hasName("DangerousAcceptAnyServerCertificateValidator")
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// The value assigned to a property, field or local of certificate
|
||||
// validation callback type.
|
||||
exists(Assignable a |
|
||||
a.getType() instanceof CertificateValidationCallbackType and
|
||||
sink.asExpr() = a.getAnAssignedValue()
|
||||
)
|
||||
or
|
||||
// The value passed as a certificate validation callback argument, e.g. to
|
||||
// the `SslStream` constructor.
|
||||
exists(Call call, Parameter p |
|
||||
p = call.getTarget().getAParameter() and
|
||||
p.getType() instanceof CertificateValidationCallbackType and
|
||||
sink.asExpr() = call.getArgumentForParameter(p)
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
}
|
||||
|
||||
module AcceptAnyCertificate = DataFlow::Global<AcceptAnyCertificateConfig>;
|
||||
|
||||
from AcceptAnyCertificate::PathNode source, AcceptAnyCertificate::PathNode sink
|
||||
where AcceptAnyCertificate::flowPath(source, sink)
|
||||
select sink.getNode(), source, sink,
|
||||
"This TLS certificate validation $@, which trusts any certificate.", source.getNode(),
|
||||
"uses a callback"
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* Added a new query, `cs/accept-any-certificate`, to detect TLS/SSL certificate validation callbacks that always accept any certificate (CWE-295).
|
||||
@@ -1,24 +0,0 @@
|
||||
edges
|
||||
| Test.cs:64:45:64:52 | access to local variable callback : (...) => ... | Test.cs:67:48:67:55 | access to local variable callback | provenance | |
|
||||
| Test.cs:65:13:65:56 | (...) => ... : (...) => ... | Test.cs:64:45:64:52 | access to local variable callback : (...) => ... | provenance | |
|
||||
nodes
|
||||
| Test.cs:14:13:14:57 | (...) => ... | semmle.label | (...) => ... |
|
||||
| Test.cs:22:13:25:13 | (...) => ... | semmle.label | (...) => ... |
|
||||
| Test.cs:33:13:33:74 | access to property DangerousAcceptAnyServerCertificateValidator | semmle.label | access to property DangerousAcceptAnyServerCertificateValidator |
|
||||
| Test.cs:40:13:40:56 | (...) => ... | semmle.label | (...) => ... |
|
||||
| Test.cs:52:67:52:75 | delegate creation of type RemoteCertificateValidationCallback | semmle.label | delegate creation of type RemoteCertificateValidationCallback |
|
||||
| Test.cs:59:13:59:56 | (...) => ... | semmle.label | (...) => ... |
|
||||
| Test.cs:64:45:64:52 | access to local variable callback : (...) => ... | semmle.label | access to local variable callback : (...) => ... |
|
||||
| Test.cs:65:13:65:56 | (...) => ... | semmle.label | (...) => ... |
|
||||
| Test.cs:65:13:65:56 | (...) => ... : (...) => ... | semmle.label | (...) => ... : (...) => ... |
|
||||
| Test.cs:67:48:67:55 | access to local variable callback | semmle.label | access to local variable callback |
|
||||
subpaths
|
||||
#select
|
||||
| Test.cs:14:13:14:57 | (...) => ... | Test.cs:14:13:14:57 | (...) => ... | Test.cs:14:13:14:57 | (...) => ... | This TLS certificate validation $@, which trusts any certificate. | Test.cs:14:13:14:57 | (...) => ... | uses a callback |
|
||||
| Test.cs:22:13:25:13 | (...) => ... | Test.cs:22:13:25:13 | (...) => ... | Test.cs:22:13:25:13 | (...) => ... | This TLS certificate validation $@, which trusts any certificate. | Test.cs:22:13:25:13 | (...) => ... | uses a callback |
|
||||
| Test.cs:33:13:33:74 | access to property DangerousAcceptAnyServerCertificateValidator | Test.cs:33:13:33:74 | access to property DangerousAcceptAnyServerCertificateValidator | Test.cs:33:13:33:74 | access to property DangerousAcceptAnyServerCertificateValidator | This TLS certificate validation $@, which trusts any certificate. | Test.cs:33:13:33:74 | access to property DangerousAcceptAnyServerCertificateValidator | uses a callback |
|
||||
| Test.cs:40:13:40:56 | (...) => ... | Test.cs:40:13:40:56 | (...) => ... | Test.cs:40:13:40:56 | (...) => ... | This TLS certificate validation $@, which trusts any certificate. | Test.cs:40:13:40:56 | (...) => ... | uses a callback |
|
||||
| Test.cs:52:67:52:75 | delegate creation of type RemoteCertificateValidationCallback | Test.cs:52:67:52:75 | delegate creation of type RemoteCertificateValidationCallback | Test.cs:52:67:52:75 | delegate creation of type RemoteCertificateValidationCallback | This TLS certificate validation $@, which trusts any certificate. | Test.cs:52:67:52:75 | delegate creation of type RemoteCertificateValidationCallback | uses a callback |
|
||||
| Test.cs:59:13:59:56 | (...) => ... | Test.cs:59:13:59:56 | (...) => ... | Test.cs:59:13:59:56 | (...) => ... | This TLS certificate validation $@, which trusts any certificate. | Test.cs:59:13:59:56 | (...) => ... | uses a callback |
|
||||
| Test.cs:65:13:65:56 | (...) => ... | Test.cs:65:13:65:56 | (...) => ... | Test.cs:65:13:65:56 | (...) => ... | This TLS certificate validation $@, which trusts any certificate. | Test.cs:65:13:65:56 | (...) => ... | uses a callback |
|
||||
| Test.cs:67:48:67:55 | access to local variable callback | Test.cs:65:13:65:56 | (...) => ... : (...) => ... | Test.cs:67:48:67:55 | access to local variable callback | This TLS certificate validation $@, which trusts any certificate. | Test.cs:65:13:65:56 | (...) => ... | uses a callback |
|
||||
@@ -1 +0,0 @@
|
||||
Security Features/CWE-295/AcceptAnyCertificate.ql
|
||||
@@ -1,89 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Security;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
public class CertificateValidationTests
|
||||
{
|
||||
public void HttpClientHandlerBad()
|
||||
{
|
||||
var handler = new HttpClientHandler();
|
||||
// BAD: always trusts any certificate.
|
||||
handler.ServerCertificateCustomValidationCallback =
|
||||
(request, certificate, chain, errors) => true;
|
||||
}
|
||||
|
||||
public void HttpClientHandlerBlockBodyBad()
|
||||
{
|
||||
var handler = new HttpClientHandler();
|
||||
// BAD: always trusts any certificate.
|
||||
handler.ServerCertificateCustomValidationCallback =
|
||||
(request, certificate, chain, errors) =>
|
||||
{
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
public void HttpClientHandlerDangerousBad()
|
||||
{
|
||||
var handler = new HttpClientHandler();
|
||||
// BAD: built-in callback that accepts any certificate.
|
||||
handler.ServerCertificateCustomValidationCallback =
|
||||
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
|
||||
}
|
||||
|
||||
public void ServicePointManagerBad()
|
||||
{
|
||||
// BAD: always trusts any certificate.
|
||||
ServicePointManager.ServerCertificateValidationCallback =
|
||||
(sender, certificate, chain, errors) => true;
|
||||
}
|
||||
|
||||
private static bool AcceptAll(object sender, X509Certificate certificate, X509Chain chain,
|
||||
SslPolicyErrors errors)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void MethodGroupBad()
|
||||
{
|
||||
// BAD: the referenced method always returns true.
|
||||
ServicePointManager.ServerCertificateValidationCallback = AcceptAll;
|
||||
}
|
||||
|
||||
public void SslStreamBad(Stream stream)
|
||||
{
|
||||
// BAD: the validation callback always returns true.
|
||||
var ssl = new SslStream(stream, false,
|
||||
(sender, certificate, chain, errors) => true);
|
||||
}
|
||||
|
||||
public void IndirectBad(Stream stream)
|
||||
{
|
||||
RemoteCertificateValidationCallback callback =
|
||||
(sender, certificate, chain, errors) => true;
|
||||
// BAD: the callback flowing here always returns true.
|
||||
var ssl = new SslStream(stream, false, callback);
|
||||
}
|
||||
|
||||
public void HttpClientHandlerGood()
|
||||
{
|
||||
var handler = new HttpClientHandler();
|
||||
// GOOD: the certificate is only trusted when there are no validation errors.
|
||||
handler.ServerCertificateCustomValidationCallback =
|
||||
(request, certificate, chain, errors) => errors == SslPolicyErrors.None;
|
||||
}
|
||||
|
||||
private static bool Validate(object sender, X509Certificate certificate, X509Chain chain,
|
||||
SslPolicyErrors errors)
|
||||
{
|
||||
return errors == SslPolicyErrors.None;
|
||||
}
|
||||
|
||||
public void MethodGroupGood()
|
||||
{
|
||||
// GOOD: the referenced method performs real validation.
|
||||
ServicePointManager.ServerCertificateValidationCallback = Validate;
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
semmle-extractor-options: /nostdlib /noconfig
|
||||
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj
|
||||
@@ -1,139 +0,0 @@
|
||||
.. _codeql-cli-2.25.6:
|
||||
|
||||
==========================
|
||||
CodeQL 2.25.6 (2026-06-04)
|
||||
==========================
|
||||
|
||||
.. contents:: Contents
|
||||
:depth: 2
|
||||
:local:
|
||||
:backlinks: none
|
||||
|
||||
This is an overview of changes in the CodeQL CLI and relevant CodeQL query and library packs. For additional updates on changes to the CodeQL code scanning experience, check out the `code scanning section on the GitHub blog <https://github.blog/tag/code-scanning/>`__, `relevant GitHub Changelog updates <https://github.blog/changelog/label/application-security/>`__, `changes in the CodeQL extension for Visual Studio Code <https://marketplace.visualstudio.com/items/GitHub.vscode-codeql/changelog>`__, and the `CodeQL Action changelog <https://github.com/github/codeql-action/blob/main/CHANGELOG.md>`__.
|
||||
|
||||
Security Coverage
|
||||
-----------------
|
||||
|
||||
CodeQL 2.25.6 runs a total of 496 security queries when configured with the Default suite (covering 169 CWE). The Extended suite enables an additional 131 queries (covering 32 more CWE).
|
||||
|
||||
CodeQL CLI
|
||||
----------
|
||||
|
||||
Improvements
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* When the :code:`git` executable is available, CodeQL can now obtain configuration and queries from SHA-256 Git repositories, and infer Git metadata about them.
|
||||
|
||||
Miscellaneous
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
* The build of Eclipse Temurin OpenJDK that is used to run the CodeQL CLI has been updated to version 21.0.11.
|
||||
|
||||
Query Packs
|
||||
-----------
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* Adjusted (minor) help file descriptions for queries: :code:`actions/untrusted-checkout/critical`, :code:`actions/untrusted-checkout/high`, :code:`actions/untrusted-checkout/medium`. Clarified wording on a minor point, added one more listed resource and added one more recommendation for things to check.
|
||||
|
||||
Major Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* Adjusted :code:`actions/untrusted-checkout/critical` to align more with other untrusted resource queries, where the alert location is the location where the artifact is obtained from (the checkout point). This aligns with the other 2 related queries. This will cause the same alerts to re-open for closed alerts of this query.
|
||||
|
||||
Minor Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* Altered the alert message for clarity for queries: :code:`actions/untrusted-checkout/critical`, :code:`actions/untrusted-checkout/high`.
|
||||
* The :code:`actions/unpinned-tag` query now recognizes 64-character SHA-256 commit hashes as properly pinned references, in addition to 40-character SHA-1 hashes.
|
||||
|
||||
Query Metadata Changes
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* Reversed adjustment of the name of :code:`actions/untrusted-checkout/high`, but kept the portion of the previous change for the word "trusted" to "privileged". Added a missing "a" to phrasing in :code:`actions/untrusted-checkout/high` and :code:`actions/untrusted-checkout/medium`.
|
||||
|
||||
Language Libraries
|
||||
------------------
|
||||
|
||||
Major Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Swift
|
||||
"""""
|
||||
|
||||
* Upgraded to allow analysis of Swift 6.3.2.
|
||||
|
||||
Minor Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* Added flow source models for :code:`scanf_s` and related functions.
|
||||
* Added a :code:`Call` column to :code:`LocalFlowSourceFunction::hasLocalFlowSource` and :code:`RemoteFlowSourceFunction::hasRemoteFlowSource`. The old predicates without a :code:`Call` column continue to be supported.
|
||||
|
||||
C#
|
||||
""
|
||||
|
||||
* Full support for C# 14 / .NET 10. All new language features are now supported by the extractor. The QL library and data flow analysis now support the new C# 14 language constructs and include generated Models as Data (MaD) models for the .NET 10 runtime.
|
||||
* C# 14: Added support for user-defined instance increment/decrement operators.
|
||||
|
||||
Java/Kotlin
|
||||
"""""""""""
|
||||
|
||||
* Added LLM-generated source and sink models for :code:`org.apache.avro`.
|
||||
|
||||
JavaScript/TypeScript
|
||||
"""""""""""""""""""""
|
||||
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example :code:`js/clear-text-logging`) may find more correct results and fewer false positive results after these changes.
|
||||
|
||||
Python
|
||||
""""""
|
||||
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example :code:`py/clear-text-logging-sensitive-data`) may find more correct results and fewer false positive results after these changes.
|
||||
|
||||
Swift
|
||||
"""""
|
||||
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example :code:`swift/cleartext-logging`) may find more correct results and fewer false positive results after these changes.
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, including regexes like :code:`^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a SHA-1 or SHA-256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
||||
|
||||
Rust
|
||||
""""
|
||||
|
||||
* The sensitive data heuristics used to identify code that handles passwords and private data have been improved. Most of the changes permit more variations of established patterns, thereby finding more sensitive data. Queries that use the sensitive data library (for example :code:`rust/cleartext-logging`) may find more correct results and fewer false positive results after these changes.
|
||||
|
||||
Deprecated APIs
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* The :code:`UsingAliasTypedefType` class has been deprecated. Use :code:`TypeAliasType` instead.
|
||||
|
||||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* Added a :code:`getOriginalTemplate` predicate to :code:`TemplateClass`, :code:`TemplateFunction`, :code:`TemplateVariable`, and :code:`AliasTemplateType`, which yields the class member template the template was generated from. The predicates only have results for templates that are members of class template instantiations.
|
||||
* Added :code:`AliasTemplateType` and :code:`AliasTemplateInstantiationType` classes, representing C++ alias templates and their instantiations.
|
||||
@@ -11,7 +11,6 @@ A list of queries for each suite and language `is available here <https://docs.g
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
codeql-cli-2.25.6
|
||||
codeql-cli-2.25.5
|
||||
codeql-cli-2.25.4
|
||||
codeql-cli-2.25.3
|
||||
|
||||
@@ -4,7 +4,7 @@ inputs:
|
||||
go-test-version:
|
||||
description: Which Go version to use for running the tests
|
||||
required: false
|
||||
default: "~1.26.4"
|
||||
default: "~1.26.0"
|
||||
run-code-checks:
|
||||
description: Whether to run formatting, code and qhelp generation checks
|
||||
required: false
|
||||
|
||||
@@ -2,14 +2,14 @@ module github.com/github/codeql-go/extractor
|
||||
|
||||
go 1.26
|
||||
|
||||
toolchain go1.26.4
|
||||
toolchain go1.26.0
|
||||
|
||||
// when updating this, run
|
||||
// bazel run @rules_go//go -- mod tidy
|
||||
// when adding or removing dependencies, run
|
||||
// bazel mod tidy
|
||||
require (
|
||||
golang.org/x/mod v0.37.0
|
||||
golang.org/x/mod v0.36.0
|
||||
golang.org/x/tools v0.45.0
|
||||
)
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
|
||||
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
|
||||
golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4=
|
||||
golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8=
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* More logging functions are now recognized as not returning or panicking.
|
||||
@@ -413,13 +413,17 @@ private class ExternalLoggerCall extends LoggerCall::Range, DataFlow::CallNode {
|
||||
}
|
||||
}
|
||||
|
||||
private class HeuristicLoggerFunction extends Method {
|
||||
string logFunctionPrefix;
|
||||
|
||||
HeuristicLoggerFunction() {
|
||||
exists(string tp, string name |
|
||||
this.hasQualifiedName(_, tp, name) and
|
||||
this.getReceiverBaseType().getUnderlyingType() instanceof InterfaceType
|
||||
/**
|
||||
* A call to an interface that looks like a logger. It is common to use a
|
||||
* locally-defined interface for logging to make it easy to changing logging
|
||||
* library.
|
||||
*/
|
||||
private class HeuristicLoggerCall extends LoggerCall::Range, DataFlow::CallNode {
|
||||
HeuristicLoggerCall() {
|
||||
exists(Method m, string tp, string logFunctionPrefix, string name |
|
||||
m = this.getTarget() and
|
||||
m.hasQualifiedName(_, tp, name) and
|
||||
m.getReceiverBaseType().getUnderlyingType() instanceof InterfaceType
|
||||
|
|
||||
tp.regexpMatch(".*[lL]ogger") and
|
||||
logFunctionPrefix =
|
||||
@@ -431,19 +435,6 @@ private class HeuristicLoggerFunction extends Method {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate mayReturnNormally() { logFunctionPrefix != "Fatal" }
|
||||
|
||||
override predicate mustPanic() { logFunctionPrefix = "Panic" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to an interface that looks like a logger. It is common to use a
|
||||
* locally-defined interface for logging to make it easy to change logging
|
||||
* library.
|
||||
*/
|
||||
private class HeuristicLoggerCall extends LoggerCall::Range, DataFlow::CallNode {
|
||||
HeuristicLoggerCall() { this.getTarget() instanceof HeuristicLoggerFunction }
|
||||
|
||||
override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() }
|
||||
}
|
||||
|
||||
|
||||
@@ -12,37 +12,17 @@ import go
|
||||
* forks.
|
||||
*/
|
||||
module Glog {
|
||||
/** Gets a package name for `glog` or `klog` (which is a fork). */
|
||||
string packagePath() {
|
||||
result =
|
||||
package([
|
||||
"github.com/golang/glog", "gopkg.in/glog", "k8s.io/klog", "github.com/barakmich/glog"
|
||||
], "")
|
||||
}
|
||||
|
||||
private class GlogFunction extends Function {
|
||||
int firstPrintedArg;
|
||||
string format;
|
||||
string level;
|
||||
|
||||
GlogFunction() {
|
||||
exists(string pkg, string context, int nContextArgs, string depth, int nDepthArgs, string fn |
|
||||
pkg = packagePath() and
|
||||
exists(string pkg, string fn, string level |
|
||||
pkg = package(["github.com/golang/glog", "gopkg.in/glog", "k8s.io/klog"], "") and
|
||||
level = ["Error", "Exit", "Fatal", "Info", "Warning"] and
|
||||
(
|
||||
context = "" and nContextArgs = 0
|
||||
fn = level + ["", "f", "ln"] and firstPrintedArg = 0
|
||||
or
|
||||
context = "Context" and nContextArgs = 1
|
||||
) and
|
||||
(
|
||||
depth = "" and nDepthArgs = 0
|
||||
or
|
||||
depth = "Depth" and nDepthArgs = 1
|
||||
) and
|
||||
format = ["", "f", "ln"] and
|
||||
(
|
||||
fn = level + context + depth + format and
|
||||
firstPrintedArg = nContextArgs + nDepthArgs
|
||||
fn = level + "Depth" and firstPrintedArg = 1
|
||||
)
|
||||
|
|
||||
this.hasQualifiedName(pkg, fn)
|
||||
@@ -55,15 +35,10 @@ module Glog {
|
||||
* Gets the index of the first argument that may be output, including a format string if one is present.
|
||||
*/
|
||||
int getFirstPrintedArg() { result = firstPrintedArg }
|
||||
|
||||
/** Holds if this function takes a format string. */
|
||||
predicate formatter() { format = "f" }
|
||||
|
||||
override predicate mayReturnNormally() { level != "Fatal" and level != "Exit" }
|
||||
}
|
||||
|
||||
private class StringFormatter extends StringOps::Formatting::Range instanceof GlogFunction {
|
||||
StringFormatter() { this.formatter() }
|
||||
StringFormatter() { this.getName().matches("%f") }
|
||||
|
||||
override int getFormatStringIndex() { result = super.getFirstPrintedArg() }
|
||||
}
|
||||
|
||||
@@ -28,12 +28,6 @@ module Logrus {
|
||||
this.(Method).hasQualifiedName(packagePath(), ["Entry", "Logger"], name)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate mayReturnNormally() {
|
||||
not exists(string level, string suffix | level = ["Fatal", "Panic"] |
|
||||
this.getName() = level + suffix
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class StringFormatters extends StringOps::Formatting::Range instanceof LogFunction {
|
||||
|
||||
@@ -47,7 +47,7 @@ module Zap {
|
||||
}
|
||||
|
||||
/** A Zap logging function which always panics. */
|
||||
private class FatalLogMethod extends ZapFunction {
|
||||
private class FatalLogMethod extends Method {
|
||||
FatalLogMethod() {
|
||||
this.hasQualifiedName(packagePath(), "Logger", "Fatal")
|
||||
or
|
||||
@@ -58,7 +58,7 @@ module Zap {
|
||||
}
|
||||
|
||||
/** A Zap logging function which always panics. */
|
||||
private class MustPanicLogMethod extends ZapFunction {
|
||||
private class MustPanicLogMethod extends Method {
|
||||
MustPanicLogMethod() {
|
||||
this.hasQualifiedName(packagePath(), "Logger", "Panic")
|
||||
or
|
||||
|
||||
@@ -29,37 +29,18 @@ module Log {
|
||||
}
|
||||
|
||||
private class LogFormatter extends StringOps::Formatting::Range instanceof LogFunction {
|
||||
LogFormatter() { this.getName() = ["Fatalf", "Panicf", "Printf", "Panic", "Panicf", "Panicln"] }
|
||||
LogFormatter() { this.getName() = ["Fatalf", "Panicf", "Printf"] }
|
||||
|
||||
override int getFormatStringIndex() { result = 0 }
|
||||
}
|
||||
|
||||
/** A fatal log function, which calls `os.Exit`. */
|
||||
private class FatalLogFunction extends Function {
|
||||
FatalLogFunction() {
|
||||
exists(string fn | fn = ["Fatal", "Fatalf", "Fatalln"] |
|
||||
this.hasQualifiedName("log", fn)
|
||||
or
|
||||
this.(Method).hasQualifiedName("log", "Logger", fn)
|
||||
)
|
||||
}
|
||||
FatalLogFunction() { this.hasQualifiedName("log", ["Fatal", "Fatalf", "Fatalln"]) }
|
||||
|
||||
override predicate mayReturnNormally() { none() }
|
||||
}
|
||||
|
||||
/** A log function which must panic. */
|
||||
private class PanicLogFunction extends Function {
|
||||
PanicLogFunction() {
|
||||
exists(string fn | fn = ["Panic", "Panicf", "Panicln"] |
|
||||
this.hasQualifiedName("log", fn)
|
||||
or
|
||||
this.(Method).hasQualifiedName("log", "Logger", fn)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate mustPanic() { any() }
|
||||
}
|
||||
|
||||
// These models are not implemented using Models-as-Data because they represent reverse flow.
|
||||
private class FunctionModels extends TaintTracking::FunctionModel {
|
||||
FunctionInput inp;
|
||||
@@ -82,6 +63,30 @@ module Log {
|
||||
FunctionOutput outp;
|
||||
|
||||
MethodModels() {
|
||||
// signature: func (*Logger) Fatal(v ...interface{})
|
||||
this.hasQualifiedName("log", "Logger", "Fatal") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger) Fatalf(format string, v ...interface{})
|
||||
this.hasQualifiedName("log", "Logger", "Fatalf") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger) Fatalln(v ...interface{})
|
||||
this.hasQualifiedName("log", "Logger", "Fatalln") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger) Panic(v ...interface{})
|
||||
this.hasQualifiedName("log", "Logger", "Panic") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger) Panicf(format string, v ...interface{})
|
||||
this.hasQualifiedName("log", "Logger", "Panicf") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger) Panicln(v ...interface{})
|
||||
this.hasQualifiedName("log", "Logger", "Panicln") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger) Print(v ...interface{})
|
||||
this.hasQualifiedName("log", "Logger", "Print") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
|
||||
@@ -1,181 +1,54 @@
|
||||
//go:generate depstubber -vendor github.com/golang/glog Level,Verbose Error,ErrorContext,ErrorContextDepth,ErrorContextDepthf,ErrorContextf,ErrorDepth,ErrorDepthf,Errorf,Errorln,Exit,ExitContext,ExitContextDepth,ExitContextDepthf,ExitContextf,ExitDepth,ExitDepthf,Exitf,Exitln,Fatal,FatalContext,FatalContextDepth,FatalContextDepthf,FatalContextf,FatalDepth,FatalDepthf,Fatalf,Fatalln,Info,InfoContext,InfoContextDepth,InfoContextDepthf,InfoContextf,InfoDepth,InfoDepthf,Infof,Infoln,V,VDepth,Warning,WarningContext,WarningContextDepth,WarningContextDepthf,WarningContextf,WarningDepth,WarningDepthf,Warningf,Warningln
|
||||
//go:generate depstubber -vendor k8s.io/klog Level,Verbose Error,ErrorDepth,Errorf,Errorln,Exit,ExitDepth,Exitf,Exitln,Fatal,FatalDepth,Fatalf,Fatalln,Info,InfoDepth,Infof,Infoln,V,Warning,WarningDepth,Warningf,Warningln
|
||||
//go:generate depstubber -vendor github.com/golang/glog "" Error,ErrorDepth,Errorf,Errorln,Exit,ExitDepth,Exitf,Exitln,Fatal,FatalDepth,Fatalf,Fatalln,Info,InfoDepth,Infof,Infoln,Warning,WarningDepth,Warningf,Warningln
|
||||
//go:generate depstubber -vendor k8s.io/klog "" Error,ErrorDepth,Errorf,Errorln,Exit,ExitDepth,Exitf,Exitln,Fatal,FatalDepth,Fatalf,Fatalln,Info,InfoDepth,Infof,Infoln,Warning,WarningDepth,Warningf,Warningln
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
func glogTest(selector int) {
|
||||
ctx := context.Background()
|
||||
|
||||
glog.Error(text) // $ logger=text
|
||||
glog.ErrorContext(ctx, text) // $ logger=text
|
||||
glog.ErrorContextDepth(ctx, 0, text) // $ logger=text
|
||||
glog.ErrorContextDepthf(ctx, 0, fmt, text) // $ logger=fmt logger=text
|
||||
glog.ErrorContextf(ctx, fmt, text) // $ logger=fmt logger=text
|
||||
glog.ErrorDepth(0, text) // $ logger=text
|
||||
glog.ErrorDepthf(0, fmt, text) // $ logger=fmt logger=text
|
||||
glog.Errorf(fmt, text) // $ logger=fmt logger=text
|
||||
glog.Errorln(text) // $ logger=text
|
||||
if selector == 1 {
|
||||
glog.Exit(text) // $ logger=text
|
||||
}
|
||||
if selector == 2 {
|
||||
glog.ExitContext(ctx, text) // $ logger=text
|
||||
}
|
||||
if selector == 3 {
|
||||
glog.ExitContextDepth(ctx, 0, text) // $ logger=text
|
||||
}
|
||||
if selector == 4 {
|
||||
glog.ExitContextDepthf(ctx, 0, fmt, text) // $ logger=fmt logger=text
|
||||
}
|
||||
if selector == 5 {
|
||||
glog.ExitContextf(ctx, fmt, text) // $ logger=fmt logger=text
|
||||
}
|
||||
if selector == 6 {
|
||||
glog.ExitDepth(0, text) // $ logger=text
|
||||
}
|
||||
if selector == 7 {
|
||||
glog.ExitDepthf(0, fmt, text) // $ logger=fmt logger=text
|
||||
}
|
||||
if selector == 8 {
|
||||
glog.Exitf(fmt, text) // $ logger=fmt logger=text
|
||||
}
|
||||
if selector == 9 {
|
||||
glog.Exitln(text) // $ logger=text
|
||||
}
|
||||
if selector == 10 {
|
||||
glog.Fatal(text) // $ logger=text
|
||||
}
|
||||
if selector == 11 {
|
||||
glog.FatalContext(ctx, text) // $ logger=text
|
||||
}
|
||||
if selector == 12 {
|
||||
glog.FatalContextDepth(ctx, 0, text) // $ logger=text
|
||||
}
|
||||
if selector == 13 {
|
||||
glog.FatalContextDepthf(ctx, 0, fmt, text) // $ logger=fmt logger=text
|
||||
}
|
||||
if selector == 14 {
|
||||
glog.FatalContextf(ctx, fmt, text) // $ logger=fmt logger=text
|
||||
}
|
||||
if selector == 15 {
|
||||
glog.FatalDepth(0, text) // $ logger=text
|
||||
}
|
||||
if selector == 16 {
|
||||
glog.FatalDepthf(0, fmt, text) // $ logger=fmt logger=text
|
||||
}
|
||||
if selector == 17 {
|
||||
glog.Fatalf(fmt, text) // $ logger=fmt logger=text
|
||||
}
|
||||
if selector == 18 {
|
||||
glog.Fatalln(text) // $ logger=text
|
||||
}
|
||||
glog.Info(text) // $ logger=text
|
||||
glog.InfoContext(ctx, text) // $ logger=text
|
||||
glog.InfoContextDepth(ctx, 0, text) // $ logger=text
|
||||
glog.InfoContextDepthf(ctx, 0, fmt, text) // $ logger=fmt logger=text
|
||||
glog.InfoContextf(ctx, fmt, text) // $ logger=fmt logger=text
|
||||
glog.InfoDepth(0, text) // $ logger=text
|
||||
glog.InfoDepthf(0, fmt, text) // $ logger=fmt logger=text
|
||||
glog.Infof(fmt, text) // $ logger=fmt logger=text
|
||||
glog.Infoln(text) // $ logger=text
|
||||
glog.Warning(text) // $ logger=text
|
||||
glog.WarningContext(ctx, text) // $ logger=text
|
||||
glog.WarningContextDepth(ctx, 0, text) // $ logger=text
|
||||
glog.WarningContextDepthf(ctx, 0, fmt, text) // $ logger=fmt logger=text
|
||||
glog.WarningContextf(ctx, fmt, text) // $ logger=fmt logger=text
|
||||
glog.WarningDepth(0, text) // $ logger=text
|
||||
glog.WarningDepthf(0, fmt, text) // $ logger=fmt logger=text
|
||||
glog.Warningf(fmt, text) // $ logger=fmt logger=text
|
||||
glog.Warningln(text) // $ logger=text
|
||||
|
||||
glog.V(0).Info(text) // $ logger=text
|
||||
glog.V(0).InfoContext(ctx, text) // $ logger=text
|
||||
glog.V(0).InfoContextDepth(ctx, 0, text) // $ logger=text
|
||||
glog.V(0).InfoContextDepthf(ctx, 0, fmt, text) // $ logger=fmt logger=text
|
||||
glog.V(0).InfoContextf(ctx, fmt, text) // $ logger=fmt logger=text
|
||||
glog.V(0).InfoDepth(0, text) // $ logger=text
|
||||
glog.V(0).InfoDepthf(0, fmt, text) // $ logger=fmt logger=text
|
||||
glog.V(0).Infof(fmt, text) // $ logger=fmt logger=text
|
||||
glog.V(0).Infoln(text) // $ logger=text
|
||||
glog.VDepth(0, 0).Info(text) // $ logger=text
|
||||
func glogTest() {
|
||||
glog.Error(text) // $ logger=text
|
||||
glog.ErrorDepth(0, text) // $ logger=text
|
||||
glog.Errorf(fmt, text) // $ logger=fmt logger=text
|
||||
glog.Errorln(text) // $ logger=text
|
||||
glog.Exit(text) // $ logger=text
|
||||
glog.ExitDepth(0, text) // $ logger=text
|
||||
glog.Exitf(fmt, text) // $ logger=fmt logger=text
|
||||
glog.Exitln(text) // $ logger=text
|
||||
glog.Fatal(text) // $ logger=text
|
||||
glog.FatalDepth(0, text) // $ logger=text
|
||||
glog.Fatalf(fmt, text) // $ logger=fmt logger=text
|
||||
glog.Fatalln(text) // $ logger=text
|
||||
glog.Info(text) // $ logger=text
|
||||
glog.InfoDepth(0, text) // $ logger=text
|
||||
glog.Infof(fmt, text) // $ logger=fmt logger=text
|
||||
glog.Infoln(text) // $ logger=text
|
||||
glog.Warning(text) // $ logger=text
|
||||
glog.WarningDepth(0, text) // $ logger=text
|
||||
glog.Warningf(fmt, text) // $ logger=fmt logger=text
|
||||
glog.Warningln(text) // $ logger=text
|
||||
|
||||
// components corresponding to the format specifier "%T" are not considered vulnerable
|
||||
glog.ErrorContextDepthf(ctx, 0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.ErrorContextf(ctx, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.ErrorDepthf(0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.Errorf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
if selector == 19 {
|
||||
glog.ExitContextDepthf(ctx, 0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
}
|
||||
if selector == 20 {
|
||||
glog.ExitContextf(ctx, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
}
|
||||
if selector == 21 {
|
||||
glog.ExitDepthf(0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
}
|
||||
if selector == 22 {
|
||||
glog.Exitf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
}
|
||||
if selector == 23 {
|
||||
glog.FatalContextDepthf(ctx, 0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
}
|
||||
if selector == 24 {
|
||||
glog.FatalContextf(ctx, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
}
|
||||
if selector == 25 {
|
||||
glog.FatalDepthf(0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
}
|
||||
if selector == 26 {
|
||||
glog.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
}
|
||||
glog.InfoContextDepthf(ctx, 0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.InfoContextf(ctx, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.InfoDepthf(0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.Infof("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.WarningContextDepthf(ctx, 0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.WarningContextf(ctx, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.WarningDepthf(0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.Warningf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.V(0).InfoContextDepthf(ctx, 0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.V(0).InfoContextf(ctx, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.V(0).InfoDepthf(0, "%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.V(0).Infof("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.Errorf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.Exitf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.Infof("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
glog.Warningf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
|
||||
klog.Error(text) // $ logger=text
|
||||
klog.ErrorDepth(0, text) // $ logger=text
|
||||
klog.Errorf(fmt, text) // $ logger=fmt logger=text
|
||||
klog.Errorln(text) // $ logger=text
|
||||
if selector == 27 {
|
||||
klog.Exit(text) // $ logger=text
|
||||
}
|
||||
if selector == 28 {
|
||||
klog.ExitDepth(0, text) // $ logger=text
|
||||
}
|
||||
if selector == 29 {
|
||||
klog.Exitf(fmt, text) // $ logger=fmt logger=text
|
||||
}
|
||||
if selector == 30 {
|
||||
klog.Exitln(text) // $ logger=text
|
||||
}
|
||||
if selector == 31 {
|
||||
klog.Fatal(text) // $ logger=text
|
||||
}
|
||||
if selector == 32 {
|
||||
klog.FatalDepth(0, text) // $ logger=text
|
||||
}
|
||||
if selector == 33 {
|
||||
klog.Fatalf(fmt, text) // $ logger=fmt logger=text
|
||||
}
|
||||
if selector == 34 {
|
||||
klog.Fatalln(text) // $ logger=text
|
||||
}
|
||||
klog.Error(text) // $ logger=text
|
||||
klog.ErrorDepth(0, text) // $ logger=text
|
||||
klog.Errorf(fmt, text) // $ logger=fmt logger=text
|
||||
klog.Errorln(text) // $ logger=text
|
||||
klog.Exit(text) // $ logger=text
|
||||
klog.ExitDepth(0, text) // $ logger=text
|
||||
klog.Exitf(fmt, text) // $ logger=fmt logger=text
|
||||
klog.Exitln(text) // $ logger=text
|
||||
klog.Fatal(text) // $ logger=text
|
||||
klog.FatalDepth(0, text) // $ logger=text
|
||||
klog.Fatalf(fmt, text) // $ logger=fmt logger=text
|
||||
klog.Fatalln(text) // $ logger=text
|
||||
klog.Info(text) // $ logger=text
|
||||
klog.InfoDepth(0, text) // $ logger=text
|
||||
klog.Infof(fmt, text) // $ logger=fmt logger=text
|
||||
@@ -184,19 +57,11 @@ func glogTest(selector int) {
|
||||
klog.WarningDepth(0, text) // $ logger=text
|
||||
klog.Warningf(fmt, text) // $ logger=fmt logger=text
|
||||
klog.Warningln(text) // $ logger=text
|
||||
klog.V(0).Info(text) // $ logger=text
|
||||
klog.V(0).Infof(fmt, text) // $ logger=fmt logger=text
|
||||
klog.V(0).Infoln(text) // $ logger=text
|
||||
|
||||
// components corresponding to the format specifier "%T" are not considered vulnerable
|
||||
klog.Errorf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
if selector == 35 {
|
||||
klog.Exitf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
}
|
||||
if selector == 36 {
|
||||
klog.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
}
|
||||
klog.Infof("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
klog.Warningf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
klog.V(0).Infof("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
klog.Errorf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
klog.Exitf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
klog.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
klog.Infof("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
klog.Warningf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ module codeql-go-tests/concepts/loggercall
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/golang/glog v1.2.5
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
|
||||
github.com/sirupsen/logrus v1.7.0
|
||||
k8s.io/klog v1.0.0
|
||||
)
|
||||
|
||||
@@ -6,6 +6,5 @@ const text = "test"
|
||||
var v []byte
|
||||
|
||||
func main() {
|
||||
glogTest(len(v))
|
||||
stdlib()
|
||||
}
|
||||
|
||||
@@ -2,125 +2,47 @@
|
||||
// This is a simple stub for github.com/golang/glog, strictly for use in testing.
|
||||
|
||||
// See the LICENSE file for information about the licensing of the original library.
|
||||
// Source: github.com/golang/glog (exports: Level,Verbose; functions: Error,ErrorContext,ErrorContextDepth,ErrorContextDepthf,ErrorContextf,ErrorDepth,ErrorDepthf,Errorf,Errorln,Exit,ExitContext,ExitContextDepth,ExitContextDepthf,ExitContextf,ExitDepth,ExitDepthf,Exitf,Exitln,Fatal,FatalContext,FatalContextDepth,FatalContextDepthf,FatalContextf,FatalDepth,FatalDepthf,Fatalf,Fatalln,Info,InfoContext,InfoContextDepth,InfoContextDepthf,InfoContextf,InfoDepth,InfoDepthf,Infof,Infoln,V,VDepth,Warning,WarningContext,WarningContextDepth,WarningContextDepthf,WarningContextf,WarningDepth,WarningDepthf,Warningf,Warningln)
|
||||
// Source: github.com/golang/glog (exports: ; functions: Error,ErrorDepth,Errorf,Errorln,Exit,ExitDepth,Exitf,Exitln,Fatal,FatalDepth,Fatalf,Fatalln,Info,InfoDepth,Infof,Infoln,Warning,WarningDepth,Warningf,Warningln)
|
||||
|
||||
// Package glog is a stub of github.com/golang/glog, generated by depstubber.
|
||||
package glog
|
||||
|
||||
import "context"
|
||||
|
||||
type Level int32
|
||||
|
||||
type Verbose bool
|
||||
|
||||
func Error(_ ...interface{}) {}
|
||||
|
||||
func ErrorContext(_ context.Context, _ ...interface{}) {}
|
||||
|
||||
func ErrorContextDepth(_ context.Context, _ int, _ ...interface{}) {}
|
||||
|
||||
func ErrorContextDepthf(_ context.Context, _ int, _ string, _ ...interface{}) {}
|
||||
|
||||
func ErrorContextf(_ context.Context, _ string, _ ...interface{}) {}
|
||||
|
||||
func ErrorDepth(_ int, _ ...interface{}) {}
|
||||
|
||||
func ErrorDepthf(_ int, _ string, _ ...interface{}) {}
|
||||
|
||||
func Errorf(_ string, _ ...interface{}) {}
|
||||
|
||||
func Errorln(_ ...interface{}) {}
|
||||
|
||||
func Exit(_ ...interface{}) {}
|
||||
|
||||
func ExitContext(_ context.Context, _ ...interface{}) {}
|
||||
|
||||
func ExitContextDepth(_ context.Context, _ int, _ ...interface{}) {}
|
||||
|
||||
func ExitContextDepthf(_ context.Context, _ int, _ string, _ ...interface{}) {}
|
||||
|
||||
func ExitContextf(_ context.Context, _ string, _ ...interface{}) {}
|
||||
|
||||
func ExitDepth(_ int, _ ...interface{}) {}
|
||||
|
||||
func ExitDepthf(_ int, _ string, _ ...interface{}) {}
|
||||
|
||||
func Exitf(_ string, _ ...interface{}) {}
|
||||
|
||||
func Exitln(_ ...interface{}) {}
|
||||
|
||||
func Fatal(_ ...interface{}) {}
|
||||
|
||||
func FatalContext(_ context.Context, _ ...interface{}) {}
|
||||
|
||||
func FatalContextDepth(_ context.Context, _ int, _ ...interface{}) {}
|
||||
|
||||
func FatalContextDepthf(_ context.Context, _ int, _ string, _ ...interface{}) {}
|
||||
|
||||
func FatalContextf(_ context.Context, _ string, _ ...interface{}) {}
|
||||
|
||||
func FatalDepth(_ int, _ ...interface{}) {}
|
||||
|
||||
func FatalDepthf(_ int, _ string, _ ...interface{}) {}
|
||||
|
||||
func Fatalf(_ string, _ ...interface{}) {}
|
||||
|
||||
func Fatalln(_ ...interface{}) {}
|
||||
|
||||
func Info(_ ...interface{}) {}
|
||||
|
||||
func InfoContext(_ context.Context, _ ...interface{}) {}
|
||||
|
||||
func InfoContextDepth(_ context.Context, _ int, _ ...interface{}) {}
|
||||
|
||||
func InfoContextDepthf(_ context.Context, _ int, _ string, _ ...interface{}) {}
|
||||
|
||||
func InfoContextf(_ context.Context, _ string, _ ...interface{}) {}
|
||||
|
||||
func InfoDepth(_ int, _ ...interface{}) {}
|
||||
|
||||
func InfoDepthf(_ int, _ string, _ ...interface{}) {}
|
||||
|
||||
func Infof(_ string, _ ...interface{}) {}
|
||||
|
||||
func Infoln(_ ...interface{}) {}
|
||||
|
||||
func V(_ Level) Verbose { return false }
|
||||
|
||||
func VDepth(_ int, _ Level) Verbose { return false }
|
||||
|
||||
func Warning(_ ...interface{}) {}
|
||||
|
||||
func WarningContext(_ context.Context, _ ...interface{}) {}
|
||||
|
||||
func WarningContextDepth(_ context.Context, _ int, _ ...interface{}) {}
|
||||
|
||||
func WarningContextDepthf(_ context.Context, _ int, _ string, _ ...interface{}) {}
|
||||
|
||||
func WarningContextf(_ context.Context, _ string, _ ...interface{}) {}
|
||||
|
||||
func WarningDepth(_ int, _ ...interface{}) {}
|
||||
|
||||
func WarningDepthf(_ int, _ string, _ ...interface{}) {}
|
||||
|
||||
func Warningf(_ string, _ ...interface{}) {}
|
||||
|
||||
func Warningln(_ ...interface{}) {}
|
||||
|
||||
func (_ Verbose) Info(_ ...interface{}) {}
|
||||
|
||||
func (_ Verbose) InfoContext(_ context.Context, _ ...interface{}) {}
|
||||
|
||||
func (_ Verbose) InfoContextDepth(_ context.Context, _ int, _ ...interface{}) {}
|
||||
|
||||
func (_ Verbose) InfoContextDepthf(_ context.Context, _ int, _ string, _ ...interface{}) {}
|
||||
|
||||
func (_ Verbose) InfoContextf(_ context.Context, _ string, _ ...interface{}) {}
|
||||
|
||||
func (_ Verbose) InfoDepth(_ int, _ ...interface{}) {}
|
||||
|
||||
func (_ Verbose) InfoDepthf(_ int, _ string, _ ...interface{}) {}
|
||||
|
||||
func (_ Verbose) Infof(_ string, _ ...interface{}) {}
|
||||
|
||||
func (_ Verbose) Infoln(_ ...interface{}) {}
|
||||
|
||||
14
go/ql/test/library-tests/semmle/go/concepts/LoggerCall/vendor/k8s.io/klog/stub.go
generated
vendored
14
go/ql/test/library-tests/semmle/go/concepts/LoggerCall/vendor/k8s.io/klog/stub.go
generated
vendored
@@ -2,15 +2,11 @@
|
||||
// This is a simple stub for k8s.io/klog, strictly for use in testing.
|
||||
|
||||
// See the LICENSE file for information about the licensing of the original library.
|
||||
// Source: k8s.io/klog (exports: Level,Verbose; functions: Error,ErrorDepth,Errorf,Errorln,Exit,ExitDepth,Exitf,Exitln,Fatal,FatalDepth,Fatalf,Fatalln,Info,InfoDepth,Infof,Infoln,V,Warning,WarningDepth,Warningf,Warningln)
|
||||
// Source: k8s.io/klog (exports: ; functions: Error,ErrorDepth,Errorf,Errorln,Exit,ExitDepth,Exitf,Exitln,Fatal,FatalDepth,Fatalf,Fatalln,Info,InfoDepth,Infof,Infoln,Warning,WarningDepth,Warningf,Warningln)
|
||||
|
||||
// Package klog is a stub of k8s.io/klog, generated by depstubber.
|
||||
package klog
|
||||
|
||||
type Level int32
|
||||
|
||||
type Verbose bool
|
||||
|
||||
func Error(_ ...interface{}) {}
|
||||
|
||||
func ErrorDepth(_ int, _ ...interface{}) {}
|
||||
@@ -43,8 +39,6 @@ func Infof(_ string, _ ...interface{}) {}
|
||||
|
||||
func Infoln(_ ...interface{}) {}
|
||||
|
||||
func V(_ Level) Verbose { return false }
|
||||
|
||||
func Warning(_ ...interface{}) {}
|
||||
|
||||
func WarningDepth(_ int, _ ...interface{}) {}
|
||||
@@ -52,9 +46,3 @@ func WarningDepth(_ int, _ ...interface{}) {}
|
||||
func Warningf(_ string, _ ...interface{}) {}
|
||||
|
||||
func Warningln(_ ...interface{}) {}
|
||||
|
||||
func (_ Verbose) Info(_ ...interface{}) {}
|
||||
|
||||
func (_ Verbose) Infof(_ string, _ ...interface{}) {}
|
||||
|
||||
func (_ Verbose) Infoln(_ ...interface{}) {}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# github.com/golang/glog v1.2.5
|
||||
# github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
|
||||
## explicit
|
||||
github.com/golang/glog
|
||||
# github.com/sirupsen/logrus v1.7.0
|
||||
|
||||
@@ -1,21 +1,11 @@
|
||||
| file://:0:0:0:0 | Exit | os.Exit |
|
||||
| file://:0:0:0:0 | Fatal | log.Fatal |
|
||||
| file://:0:0:0:0 | Fatal | log.Logger.Fatal |
|
||||
| file://:0:0:0:0 | Fatalf | log.Fatalf |
|
||||
| file://:0:0:0:0 | Fatalf | log.Logger.Fatalf |
|
||||
| file://:0:0:0:0 | Fatalln | log.Fatalln |
|
||||
| file://:0:0:0:0 | Fatalln | log.Logger.Fatalln |
|
||||
| file://:0:0:0:0 | Panic | log.Logger.Panic |
|
||||
| file://:0:0:0:0 | Panic | log.Panic |
|
||||
| file://:0:0:0:0 | Panicf | log.Logger.Panicf |
|
||||
| file://:0:0:0:0 | Panicf | log.Panicf |
|
||||
| file://:0:0:0:0 | Panicln | log.Logger.Panicln |
|
||||
| file://:0:0:0:0 | Panicln | log.Panicln |
|
||||
| file://:0:0:0:0 | panic | panic |
|
||||
| noretfunctions.go:8:6:8:12 | isNoRet | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.isNoRet |
|
||||
| noretfunctions.go:20:6:20:22 | noRetUsesLogFatal | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.noRetUsesLogFatal |
|
||||
| noretfunctions.go:24:6:24:23 | noRetUsesLogFatalf | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.noRetUsesLogFatalf |
|
||||
| stmts7.go:10:6:10:15 | canRecover | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.canRecover |
|
||||
| stmts.go:10:6:10:10 | test5 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.test5 |
|
||||
| stmts.go:46:6:46:10 | test6 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.test6 |
|
||||
| stmts.go:112:6:112:10 | test9 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.test9 |
|
||||
| file://:0:0:0:0 | Exit | package os |
|
||||
| file://:0:0:0:0 | Fatal | package log |
|
||||
| file://:0:0:0:0 | Fatalf | package log |
|
||||
| file://:0:0:0:0 | Fatalln | package log |
|
||||
| noretfunctions.go:8:6:8:12 | isNoRet | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph |
|
||||
| noretfunctions.go:20:6:20:22 | noRetUsesLogFatal | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph |
|
||||
| noretfunctions.go:24:6:24:23 | noRetUsesLogFatalf | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph |
|
||||
| stmts7.go:10:6:10:15 | canRecover | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph |
|
||||
| stmts.go:10:6:10:10 | test5 | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph |
|
||||
| stmts.go:46:6:46:10 | test6 | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph |
|
||||
| stmts.go:112:6:112:10 | test9 | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph |
|
||||
|
||||
@@ -2,4 +2,4 @@ import go
|
||||
|
||||
from Function f
|
||||
where not f.mayReturnNormally()
|
||||
select f, f.getQualifiedName()
|
||||
select f, f.getPackage()
|
||||
|
||||
@@ -9,9 +9,9 @@ import semmle.go.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||
import utils.test.InlineFlowTest
|
||||
|
||||
module Config implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") }
|
||||
predicate isSource(DataFlow::Node src) { sourceNode(src, "qltest") }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") }
|
||||
predicate isSink(DataFlow::Node src) { sinkNode(src, "qltest") }
|
||||
}
|
||||
|
||||
import ValueFlowTest<Config>
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
reverseRead
|
||||
| main.go:23:3:23:5 | out | Origin of readStep is missing a PostUpdateNode. |
|
||||
@@ -4,7 +4,7 @@ func source() string {
|
||||
return "untrusted data"
|
||||
}
|
||||
|
||||
func sink(any) {
|
||||
func sink(string) {
|
||||
}
|
||||
|
||||
type A struct {
|
||||
@@ -19,10 +19,6 @@ func functionWithVarArgsParameter(s ...string) string {
|
||||
return s[1]
|
||||
}
|
||||
|
||||
func functionWithVarArgsOutParameter(in string, out ...*string) {
|
||||
*out[0] = in
|
||||
}
|
||||
|
||||
func functionWithSliceOfStructsParameter(s []A) string {
|
||||
return s[1].f
|
||||
}
|
||||
@@ -42,12 +38,6 @@ func main() {
|
||||
sink(functionWithVarArgsParameter(sSlice...)) // $ hasValueFlow="call to functionWithVarArgsParameter"
|
||||
sink(functionWithVarArgsParameter(s0, s1)) // $ hasValueFlow="call to functionWithVarArgsParameter"
|
||||
|
||||
var out1 *string
|
||||
var out2 *string
|
||||
functionWithVarArgsOutParameter(source(), out1, out2)
|
||||
sink(out1) // $ MISSING: hasValueFlow="out1"
|
||||
sink(out2) // $ MISSING: hasValueFlow="out2"
|
||||
|
||||
sliceOfStructs := []A{{f: source()}}
|
||||
sink(sliceOfStructs[0].f) // $ hasValueFlow="selection of f"
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
invalidModelRow
|
||||
testFailures
|
||||
@@ -1,21 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/go-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ["github.com/nonexistent/test", "", False, "FunctionWithParameter", "", "", "Argument[0]", "ReturnValue", "value", "manual"]
|
||||
- ["github.com/nonexistent/test", "", False, "FunctionWithSliceParameter", "", "", "Argument[0].ArrayElement", "ReturnValue", "value", "manual"]
|
||||
- ["github.com/nonexistent/test", "", False, "FunctionWithVarArgsParameter", "", "", "Argument[0].ArrayElement", "ReturnValue", "value", "manual"]
|
||||
- ["github.com/nonexistent/test", "", False, "FunctionWithVarArgsOutParameter", "", "", "Argument[0]", "Argument[1].ArrayElement", "value", "manual"]
|
||||
- ["github.com/nonexistent/test", "", False, "FunctionWithSliceOfStructsParameter", "", "", "Argument[0].ArrayElement.Field[github.com/nonexistent/test.A.Field]", "ReturnValue", "value", "manual"]
|
||||
- ["github.com/nonexistent/test", "", False, "FunctionWithVarArgsOfStructsParameter", "", "", "Argument[0].ArrayElement.Field[github.com/nonexistent/test.A.Field]", "ReturnValue", "value", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/go-all
|
||||
extensible: sourceModel
|
||||
data:
|
||||
- ["github.com/nonexistent/test", "", False, "VariadicSource", "", "", "Argument[0]", "qltest", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/go-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["github.com/nonexistent/test", "", False, "VariadicSink", "", "", "Argument[0]", "qltest", "manual"]
|
||||
@@ -1,22 +0,0 @@
|
||||
import go
|
||||
import semmle.go.dataflow.ExternalFlow
|
||||
import ModelValidation
|
||||
import utils.test.InlineFlowTest
|
||||
|
||||
module Config implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
sourceNode(source, "qltest")
|
||||
or
|
||||
exists(Function fn | fn.hasQualifiedName(_, ["source", "taint"]) |
|
||||
source = fn.getACall().getResult()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
sinkNode(sink, "qltest")
|
||||
or
|
||||
exists(Function fn | fn.hasQualifiedName(_, "sink") | sink = fn.getACall().getAnArgument())
|
||||
}
|
||||
}
|
||||
|
||||
import FlowTest<Config, Config>
|
||||
@@ -1,5 +0,0 @@
|
||||
module semmle.go.Packages
|
||||
|
||||
go 1.25
|
||||
|
||||
require github.com/nonexistent/test v0.0.0-20200203000000-0000000000000
|
||||
@@ -1,56 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/nonexistent/test"
|
||||
)
|
||||
|
||||
func source() string {
|
||||
return "untrusted data"
|
||||
}
|
||||
|
||||
func sink(any) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
s := source()
|
||||
sink(test.FunctionWithParameter(s)) // $ hasValueFlow="call to FunctionWithParameter"
|
||||
|
||||
stringSlice := []string{source()}
|
||||
sink(stringSlice[0]) // $ hasValueFlow="index expression"
|
||||
|
||||
s0 := ""
|
||||
s1 := source()
|
||||
sSlice := []string{s0, s1}
|
||||
sink(test.FunctionWithParameter(sSlice[1])) // $ hasValueFlow="call to FunctionWithParameter"
|
||||
sink(test.FunctionWithSliceParameter(sSlice)) // $ hasValueFlow="call to FunctionWithSliceParameter"
|
||||
sink(test.FunctionWithVarArgsParameter(sSlice...)) // $ hasValueFlow="call to FunctionWithVarArgsParameter"
|
||||
sink(test.FunctionWithVarArgsParameter(s0, s1)) // $ hasValueFlow="call to FunctionWithVarArgsParameter"
|
||||
|
||||
var out1 *string
|
||||
var out2 *string
|
||||
test.FunctionWithVarArgsOutParameter(source(), out1, out2)
|
||||
sink(out1) // $ MISSING: hasValueFlow="out1"
|
||||
sink(out2) // $ MISSING: hasValueFlow="out2"
|
||||
|
||||
sliceOfStructs := []test.A{{Field: source()}}
|
||||
sink(sliceOfStructs[0].Field) // $ hasValueFlow="selection of Field"
|
||||
|
||||
a0 := test.A{Field: ""}
|
||||
a1 := test.A{Field: source()}
|
||||
aSlice := []test.A{a0, a1}
|
||||
sink(test.FunctionWithSliceOfStructsParameter(aSlice)) // $ hasValueFlow="call to FunctionWithSliceOfStructsParameter"
|
||||
sink(test.FunctionWithVarArgsOfStructsParameter(aSlice...)) // $ hasValueFlow="call to FunctionWithVarArgsOfStructsParameter"
|
||||
sink(test.FunctionWithVarArgsOfStructsParameter(a0, a1)) // $ hasValueFlow="call to FunctionWithVarArgsOfStructsParameter"
|
||||
|
||||
var variadicSource string
|
||||
test.VariadicSource(&variadicSource)
|
||||
sink(variadicSource) // $ MISSING: hasTaintFlow="variadicSource"
|
||||
sink(&variadicSource) // $ MISSING: hasTaintFlow="&..."
|
||||
|
||||
var variadicSourcePtr *string
|
||||
test.VariadicSource(variadicSourcePtr)
|
||||
sink(variadicSourcePtr) // $ MISSING: hasTaintFlow="variadicSourcePtr"
|
||||
sink(*variadicSourcePtr) // $ MISSING: hasTaintFlow="star expression"
|
||||
|
||||
test.VariadicSink(source()) // $ hasTaintFlow="[]type{args}"
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package test
|
||||
|
||||
type A struct {
|
||||
Field string
|
||||
}
|
||||
|
||||
func FunctionWithParameter(s string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func FunctionWithSliceParameter(s []string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func FunctionWithVarArgsParameter(s ...string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func FunctionWithVarArgsOutParameter(in string, out ...*string) {
|
||||
}
|
||||
|
||||
func FunctionWithSliceOfStructsParameter(s []A) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func FunctionWithVarArgsOfStructsParameter(s ...A) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func VariadicSource(s ...*string) {}
|
||||
|
||||
func VariadicSink(s ...string) {}
|
||||
@@ -1,3 +0,0 @@
|
||||
# github.com/nonexistent/test v0.0.0-20200203000000-0000000000000
|
||||
## explicit
|
||||
github.com/nonexistent/test
|
||||
@@ -20,9 +20,6 @@ class SummaryModelTest extends DataFlow::FunctionModel {
|
||||
this.hasQualifiedName("github.com/nonexistent/test", "FunctionWithVarArgsParameter") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
or
|
||||
this.hasQualifiedName("github.com/nonexistent/test", "FunctionWithVarArgsOutParameter") and
|
||||
(inp.isParameter(0) and outp.isParameter(any(int i | i >= 1)))
|
||||
or
|
||||
this.hasQualifiedName("github.com/nonexistent/test", "FunctionWithSliceOfStructsParameter") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module semmle.go.Packages
|
||||
|
||||
go 1.25
|
||||
go 1.17
|
||||
|
||||
require github.com/nonexistent/test v0.0.0-20200203000000-0000000000000
|
||||
|
||||
@@ -8,7 +8,7 @@ func source() string {
|
||||
return "untrusted data"
|
||||
}
|
||||
|
||||
func sink(any) {
|
||||
func sink(string) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -21,17 +21,10 @@ func main() {
|
||||
s0 := ""
|
||||
s1 := source()
|
||||
sSlice := []string{s0, s1}
|
||||
sink(test.FunctionWithParameter(sSlice[1])) // $ hasValueFlow="call to FunctionWithParameter"
|
||||
sink(test.FunctionWithSliceParameter(sSlice)) // $ hasTaintFlow="call to FunctionWithSliceParameter" MISSING: hasValueFlow="call to FunctionWithSliceParameter"
|
||||
sink(test.FunctionWithVarArgsParameter(sSlice...)) // $ hasTaintFlow="call to FunctionWithVarArgsParameter" MISSING: hasValueFlow="call to FunctionWithVarArgsParameter"
|
||||
randomFunctionWithMoreThanOneParameter(1, 2, 3, 4, 5) // This is needed to make the next line pass, because we need to have seen a call to a function with at least 2 parameters for ParameterInput to exist with index 1.
|
||||
sink(test.FunctionWithVarArgsParameter(s0, s1)) // $ hasValueFlow="call to FunctionWithVarArgsParameter"
|
||||
|
||||
var out1 *string
|
||||
var out2 *string
|
||||
test.FunctionWithVarArgsOutParameter(source(), out1, out2)
|
||||
sink(out1) // $ hasValueFlow="out1"
|
||||
sink(out2) // $ hasValueFlow="out2"
|
||||
sink(test.FunctionWithParameter(sSlice[1])) // $ hasValueFlow="call to FunctionWithParameter"
|
||||
sink(test.FunctionWithSliceParameter(sSlice)) // $ hasTaintFlow="call to FunctionWithSliceParameter" MISSING: hasValueFlow="call to FunctionWithSliceParameter"
|
||||
sink(test.FunctionWithVarArgsParameter(sSlice...)) // $ hasTaintFlow="call to FunctionWithVarArgsParameter" MISSING: hasValueFlow="call to FunctionWithVarArgsParameter"
|
||||
sink(test.FunctionWithVarArgsParameter(s0, s1)) // $ MISSING: hasValueFlow="call to FunctionWithVarArgsParameter"
|
||||
|
||||
sliceOfStructs := []test.A{{Field: source()}}
|
||||
sink(sliceOfStructs[0].Field) // $ hasValueFlow="selection of Field"
|
||||
@@ -44,6 +37,3 @@ func main() {
|
||||
sink(test.FunctionWithVarArgsOfStructsParameter(aSlice...)) // $ MISSING: hasValueFlow="call to FunctionWithVarArgsOfStructsParameter"
|
||||
sink(test.FunctionWithVarArgsOfStructsParameter(a0, a1)) // $ MISSING: hasValueFlow="call to FunctionWithVarArgsOfStructsParameter"
|
||||
}
|
||||
|
||||
func randomFunctionWithMoreThanOneParameter(i1, i2, i3, i4, i5 int) {
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -16,9 +16,6 @@ func FunctionWithVarArgsParameter(s ...string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func FunctionWithVarArgsOutParameter(in string, out ...*string) {
|
||||
}
|
||||
|
||||
func FunctionWithSliceOfStructsParameter(s []A) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -15,6 +15,62 @@ func TaintStepTest_LogNew_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
return intoWriter414
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerFatal_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromInterface518 := sourceCQL.(interface{})
|
||||
var intoLogger650 log.Logger
|
||||
intoLogger650.Fatal(fromInterface518)
|
||||
return intoLogger650
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerFatalf_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromString784 := sourceCQL.(string)
|
||||
var intoLogger957 log.Logger
|
||||
intoLogger957.Fatalf(fromString784, nil)
|
||||
return intoLogger957
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerFatalf_B0I1O0(sourceCQL interface{}) interface{} {
|
||||
fromInterface520 := sourceCQL.(interface{})
|
||||
var intoLogger443 log.Logger
|
||||
intoLogger443.Fatalf("", fromInterface520)
|
||||
return intoLogger443
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerFatalln_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromInterface127 := sourceCQL.(interface{})
|
||||
var intoLogger483 log.Logger
|
||||
intoLogger483.Fatalln(fromInterface127)
|
||||
return intoLogger483
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerPanic_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromInterface989 := sourceCQL.(interface{})
|
||||
var intoLogger982 log.Logger
|
||||
intoLogger982.Panic(fromInterface989)
|
||||
return intoLogger982
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerPanicf_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromString417 := sourceCQL.(string)
|
||||
var intoLogger584 log.Logger
|
||||
intoLogger584.Panicf(fromString417, nil)
|
||||
return intoLogger584
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerPanicf_B0I1O0(sourceCQL interface{}) interface{} {
|
||||
fromInterface991 := sourceCQL.(interface{})
|
||||
var intoLogger881 log.Logger
|
||||
intoLogger881.Panicf("", fromInterface991)
|
||||
return intoLogger881
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerPanicln_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromInterface186 := sourceCQL.(interface{})
|
||||
var intoLogger284 log.Logger
|
||||
intoLogger284.Panicln(fromInterface186)
|
||||
return intoLogger284
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerPrint_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromInterface908 := sourceCQL.(interface{})
|
||||
var intoLogger137 log.Logger
|
||||
@@ -69,6 +125,46 @@ func RunAllTaints_Log() {
|
||||
out := TaintStepTest_LogNew_B0I0O0(source)
|
||||
sink(0, out)
|
||||
}
|
||||
{
|
||||
source := newSource(1)
|
||||
out := TaintStepTest_LogLoggerFatal_B0I0O0(source)
|
||||
sink(1, out)
|
||||
}
|
||||
{
|
||||
source := newSource(2)
|
||||
out := TaintStepTest_LogLoggerFatalf_B0I0O0(source)
|
||||
sink(2, out)
|
||||
}
|
||||
{
|
||||
source := newSource(3)
|
||||
out := TaintStepTest_LogLoggerFatalf_B0I1O0(source)
|
||||
sink(3, out)
|
||||
}
|
||||
{
|
||||
source := newSource(4)
|
||||
out := TaintStepTest_LogLoggerFatalln_B0I0O0(source)
|
||||
sink(4, out)
|
||||
}
|
||||
{
|
||||
source := newSource(5)
|
||||
out := TaintStepTest_LogLoggerPanic_B0I0O0(source)
|
||||
sink(5, out)
|
||||
}
|
||||
{
|
||||
source := newSource(6)
|
||||
out := TaintStepTest_LogLoggerPanicf_B0I0O0(source)
|
||||
sink(6, out)
|
||||
}
|
||||
{
|
||||
source := newSource(7)
|
||||
out := TaintStepTest_LogLoggerPanicf_B0I1O0(source)
|
||||
sink(7, out)
|
||||
}
|
||||
{
|
||||
source := newSource(8)
|
||||
out := TaintStepTest_LogLoggerPanicln_B0I0O0(source)
|
||||
sink(8, out)
|
||||
}
|
||||
{
|
||||
source := newSource(9)
|
||||
out := TaintStepTest_LogLoggerPrint_B0I0O0(source)
|
||||
|
||||
@@ -3,9 +3,9 @@ reverseRead
|
||||
| LogInjection.go:33:14:33:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| LogInjection.go:34:18:34:20 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| LogInjection.go:35:14:35:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| LogInjection.go:551:14:551:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| LogInjection.go:559:14:559:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| LogInjection.go:567:14:567:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| LogInjection.go:602:14:602:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| LogInjection.go:603:14:603:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| LogInjection.go:828:12:828:14 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| LogInjection.go:447:14:447:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| LogInjection.go:455:14:455:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| LogInjection.go:463:14:463:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| LogInjection.go:498:14:498:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| LogInjection.go:499:14:499:16 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
| LogInjection.go:724:12:724:14 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
|
||||
|
||||
@@ -49,22 +49,22 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
log.Printf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password"
|
||||
log.Println("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
|
||||
|
||||
if testFlag == "1" {
|
||||
if testFlag == "true" {
|
||||
log.Fatal("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
|
||||
}
|
||||
if testFlag == "2" {
|
||||
if testFlag == "true" {
|
||||
log.Fatalf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password"
|
||||
}
|
||||
if testFlag == "3" {
|
||||
if testFlag == "true" {
|
||||
log.Fatalln("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
|
||||
}
|
||||
if testFlag == "4" {
|
||||
if testFlag == "true" {
|
||||
log.Panic("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
|
||||
}
|
||||
if testFlag == "5" {
|
||||
if testFlag == "true" {
|
||||
log.Panicf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password"
|
||||
}
|
||||
if testFlag == "6" {
|
||||
if testFlag == "true" {
|
||||
log.Panicln("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
|
||||
}
|
||||
|
||||
@@ -72,24 +72,12 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
logger.Print("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
|
||||
logger.Printf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password"
|
||||
logger.Println("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
|
||||
if testFlag == "7" {
|
||||
logger.Fatal("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
|
||||
}
|
||||
if testFlag == "8" {
|
||||
logger.Fatalf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password"
|
||||
}
|
||||
if testFlag == "9" {
|
||||
logger.Fatalln("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
|
||||
}
|
||||
if testFlag == "10" {
|
||||
logger.Panic("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
|
||||
}
|
||||
if testFlag == "11" {
|
||||
logger.Panicf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password"
|
||||
}
|
||||
if testFlag == "12" {
|
||||
logger.Panicln("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
|
||||
}
|
||||
logger.Fatal("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
|
||||
logger.Fatalf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password"
|
||||
logger.Fatalln("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
|
||||
logger.Panic("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
|
||||
logger.Panicf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password"
|
||||
logger.Panicln("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
|
||||
}
|
||||
// k8s.io/klog
|
||||
{
|
||||
@@ -103,24 +91,12 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
klog.Error(username) // $ hasTaintFlow="username"
|
||||
klog.Errorf(username) // $ hasTaintFlow="username"
|
||||
klog.Errorln(username) // $ hasTaintFlow="username"
|
||||
if testFlag == "77" {
|
||||
klog.Fatal(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "78" {
|
||||
klog.Fatalf(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "79" {
|
||||
klog.Fatalln(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "80" {
|
||||
klog.Exit(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "81" {
|
||||
klog.Exitf(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "82" {
|
||||
klog.Exitln(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
klog.Fatal(username) // $ hasTaintFlow="username"
|
||||
klog.Fatalf(username) // $ hasTaintFlow="username"
|
||||
klog.Fatalln(username) // $ hasTaintFlow="username"
|
||||
klog.Exit(username) // $ hasTaintFlow="username"
|
||||
klog.Exitf(username) // $ hasTaintFlow="username"
|
||||
klog.Exitln(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
// astaxie/beego
|
||||
{
|
||||
@@ -185,30 +161,14 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
glog.ErrorDepth(0, username) // $ hasTaintFlow="username"
|
||||
glog.Errorf(username) // $ hasTaintFlow="username"
|
||||
glog.Errorln(username) // $ hasTaintFlow="username"
|
||||
if testFlag == "83" {
|
||||
glog.Fatal(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "84" {
|
||||
glog.FatalDepth(0, username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "85" {
|
||||
glog.Fatalf(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "86" {
|
||||
glog.Fatalln(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "87" {
|
||||
glog.Exit(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "88" {
|
||||
glog.ExitDepth(0, username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "89" {
|
||||
glog.Exitf(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "90" {
|
||||
glog.Exitln(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
glog.Fatal(username) // $ hasTaintFlow="username"
|
||||
glog.FatalDepth(0, username) // $ hasTaintFlow="username"
|
||||
glog.Fatalf(username) // $ hasTaintFlow="username"
|
||||
glog.Fatalln(username) // $ hasTaintFlow="username"
|
||||
glog.Exit(username) // $ hasTaintFlow="username"
|
||||
glog.ExitDepth(0, username) // $ hasTaintFlow="username"
|
||||
glog.Exitf(username) // $ hasTaintFlow="username"
|
||||
glog.Exitln(username) // $ hasTaintFlow="username"
|
||||
|
||||
}
|
||||
// sirupsen/logrus
|
||||
@@ -219,42 +179,26 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
logger := logrus.New()
|
||||
entry := logrus.NewEntry(logger)
|
||||
|
||||
logrus.Debug(username) // $ hasTaintFlow="username"
|
||||
logrus.Debugf(username, "") // $ hasTaintFlow="username"
|
||||
logrus.Debugf("", username) // $ hasTaintFlow="username"
|
||||
logrus.Debugln(username) // $ hasTaintFlow="username"
|
||||
logrus.Error(username) // $ hasTaintFlow="username"
|
||||
logrus.Errorf(username, "") // $ hasTaintFlow="username"
|
||||
logrus.Errorf("", username) // $ hasTaintFlow="username"
|
||||
logrus.Errorln(username) // $ hasTaintFlow="username"
|
||||
if testFlag == "13" {
|
||||
logrus.Fatal(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "14" {
|
||||
logrus.Fatalf(username, "") // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "15" {
|
||||
logrus.Fatalf("", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "16" {
|
||||
logrus.Fatalln(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
logrus.Info(username) // $ hasTaintFlow="username"
|
||||
logrus.Infof(username, "") // $ hasTaintFlow="username"
|
||||
logrus.Infof("", username) // $ hasTaintFlow="username"
|
||||
logrus.Infoln(username) // $ hasTaintFlow="username"
|
||||
if testFlag == "17" {
|
||||
logrus.Panic(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "18" {
|
||||
logrus.Panicf(username, "") // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "19" {
|
||||
logrus.Panicf("", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "20" {
|
||||
logrus.Panicln(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
logrus.Debug(username) // $ hasTaintFlow="username"
|
||||
logrus.Debugf(username, "") // $ hasTaintFlow="username"
|
||||
logrus.Debugf("", username) // $ hasTaintFlow="username"
|
||||
logrus.Debugln(username) // $ hasTaintFlow="username"
|
||||
logrus.Error(username) // $ hasTaintFlow="username"
|
||||
logrus.Errorf(username, "") // $ hasTaintFlow="username"
|
||||
logrus.Errorf("", username) // $ hasTaintFlow="username"
|
||||
logrus.Errorln(username) // $ hasTaintFlow="username"
|
||||
logrus.Fatal(username) // $ hasTaintFlow="username"
|
||||
logrus.Fatalf(username, "") // $ hasTaintFlow="username"
|
||||
logrus.Fatalf("", username) // $ hasTaintFlow="username"
|
||||
logrus.Fatalln(username) // $ hasTaintFlow="username"
|
||||
logrus.Info(username) // $ hasTaintFlow="username"
|
||||
logrus.Infof(username, "") // $ hasTaintFlow="username"
|
||||
logrus.Infof("", username) // $ hasTaintFlow="username"
|
||||
logrus.Infoln(username) // $ hasTaintFlow="username"
|
||||
logrus.Panic(username) // $ hasTaintFlow="username"
|
||||
logrus.Panicf(username, "") // $ hasTaintFlow="username"
|
||||
logrus.Panicf("", username) // $ hasTaintFlow="username"
|
||||
logrus.Panicln(username) // $ hasTaintFlow="username"
|
||||
logrus.Print(username) // $ hasTaintFlow="username"
|
||||
logrus.Printf(username, "") // $ hasTaintFlow="username"
|
||||
logrus.Printf("", username) // $ hasTaintFlow="username"
|
||||
@@ -276,46 +220,30 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
logrus.WithField("", username) // $ hasTaintFlow="username"
|
||||
logrus.WithFields(fields) // $ hasTaintFlow="fields"
|
||||
|
||||
entry.Debug(username) // $ hasTaintFlow="username"
|
||||
entry.Debugf(username, "") // $ hasTaintFlow="username"
|
||||
entry.Debugf("", username) // $ hasTaintFlow="username"
|
||||
entry.Debugln(username) // $ hasTaintFlow="username"
|
||||
entry.Error(username) // $ hasTaintFlow="username"
|
||||
entry.Errorf(username, "") // $ hasTaintFlow="username"
|
||||
entry.Errorf("", username) // $ hasTaintFlow="username"
|
||||
entry.Errorln(username) // $ hasTaintFlow="username"
|
||||
if testFlag == "21" {
|
||||
entry.Fatal(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "22" {
|
||||
entry.Fatalf(username, "") // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "23" {
|
||||
entry.Fatalf("", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "24" {
|
||||
entry.Fatalln(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
entry.Info(username) // $ hasTaintFlow="username"
|
||||
entry.Infof(username, "") // $ hasTaintFlow="username"
|
||||
entry.Infof("", username) // $ hasTaintFlow="username"
|
||||
entry.Infoln(username) // $ hasTaintFlow="username"
|
||||
entry.Log(0, username) // $ hasTaintFlow="username"
|
||||
entry.Logf(0, username, "") // $ hasTaintFlow="username"
|
||||
entry.Logf(0, "", username) // $ hasTaintFlow="username"
|
||||
entry.Logln(0, username) // $ hasTaintFlow="username"
|
||||
if testFlag == "25" {
|
||||
entry.Panic(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "26" {
|
||||
entry.Panicf(username, "") // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "27" {
|
||||
entry.Panicf("", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "28" {
|
||||
entry.Panicln(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
entry.Debug(username) // $ hasTaintFlow="username"
|
||||
entry.Debugf(username, "") // $ hasTaintFlow="username"
|
||||
entry.Debugf("", username) // $ hasTaintFlow="username"
|
||||
entry.Debugln(username) // $ hasTaintFlow="username"
|
||||
entry.Error(username) // $ hasTaintFlow="username"
|
||||
entry.Errorf(username, "") // $ hasTaintFlow="username"
|
||||
entry.Errorf("", username) // $ hasTaintFlow="username"
|
||||
entry.Errorln(username) // $ hasTaintFlow="username"
|
||||
entry.Fatal(username) // $ hasTaintFlow="username"
|
||||
entry.Fatalf(username, "") // $ hasTaintFlow="username"
|
||||
entry.Fatalf("", username) // $ hasTaintFlow="username"
|
||||
entry.Fatalln(username) // $ hasTaintFlow="username"
|
||||
entry.Info(username) // $ hasTaintFlow="username"
|
||||
entry.Infof(username, "") // $ hasTaintFlow="username"
|
||||
entry.Infof("", username) // $ hasTaintFlow="username"
|
||||
entry.Infoln(username) // $ hasTaintFlow="username"
|
||||
entry.Log(0, username) // $ hasTaintFlow="username"
|
||||
entry.Logf(0, username, "") // $ hasTaintFlow="username"
|
||||
entry.Logf(0, "", username) // $ hasTaintFlow="username"
|
||||
entry.Logln(0, username) // $ hasTaintFlow="username"
|
||||
entry.Panic(username) // $ hasTaintFlow="username"
|
||||
entry.Panicf(username, "") // $ hasTaintFlow="username"
|
||||
entry.Panicf("", username) // $ hasTaintFlow="username"
|
||||
entry.Panicln(username) // $ hasTaintFlow="username"
|
||||
entry.Print(username) // $ hasTaintFlow="username"
|
||||
entry.Printf(username, "") // $ hasTaintFlow="username"
|
||||
entry.Printf("", username) // $ hasTaintFlow="username"
|
||||
@@ -337,46 +265,30 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
entry.WithField("", username) // $ hasTaintFlow="username"
|
||||
entry.WithFields(fields) // $ hasTaintFlow="fields"
|
||||
|
||||
logger.Debug(username) // $ hasTaintFlow="username"
|
||||
logger.Debugf(username, "") // $ hasTaintFlow="username"
|
||||
logger.Debugf("", username) // $ hasTaintFlow="username"
|
||||
logger.Debugln(username) // $ hasTaintFlow="username"
|
||||
logger.Error(username) // $ hasTaintFlow="username"
|
||||
logger.Errorf(username, "") // $ hasTaintFlow="username"
|
||||
logger.Errorf("", username) // $ hasTaintFlow="username"
|
||||
logger.Errorln(username) // $ hasTaintFlow="username"
|
||||
if testFlag == "29" {
|
||||
logger.Fatal(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "30" {
|
||||
logger.Fatalf(username, "") // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "31" {
|
||||
logger.Fatalf("", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "32" {
|
||||
logger.Fatalln(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
logger.Info(username) // $ hasTaintFlow="username"
|
||||
logger.Infof(username, "") // $ hasTaintFlow="username"
|
||||
logger.Infof("", username) // $ hasTaintFlow="username"
|
||||
logger.Infoln(username) // $ hasTaintFlow="username"
|
||||
logger.Log(0, username) // $ hasTaintFlow="username"
|
||||
logger.Logf(0, username, "") // $ hasTaintFlow="username"
|
||||
logger.Logf(0, "", username) // $ hasTaintFlow="username"
|
||||
logger.Logln(0, username) // $ hasTaintFlow="username"
|
||||
if testFlag == "33" {
|
||||
logger.Panic(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "34" {
|
||||
logger.Panicf(username, "") // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "35" {
|
||||
logger.Panicf("", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "36" {
|
||||
logger.Panicln(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
logger.Debug(username) // $ hasTaintFlow="username"
|
||||
logger.Debugf(username, "") // $ hasTaintFlow="username"
|
||||
logger.Debugf("", username) // $ hasTaintFlow="username"
|
||||
logger.Debugln(username) // $ hasTaintFlow="username"
|
||||
logger.Error(username) // $ hasTaintFlow="username"
|
||||
logger.Errorf(username, "") // $ hasTaintFlow="username"
|
||||
logger.Errorf("", username) // $ hasTaintFlow="username"
|
||||
logger.Errorln(username) // $ hasTaintFlow="username"
|
||||
logger.Fatal(username) // $ hasTaintFlow="username"
|
||||
logger.Fatalf(username, "") // $ hasTaintFlow="username"
|
||||
logger.Fatalf("", username) // $ hasTaintFlow="username"
|
||||
logger.Fatalln(username) // $ hasTaintFlow="username"
|
||||
logger.Info(username) // $ hasTaintFlow="username"
|
||||
logger.Infof(username, "") // $ hasTaintFlow="username"
|
||||
logger.Infof("", username) // $ hasTaintFlow="username"
|
||||
logger.Infoln(username) // $ hasTaintFlow="username"
|
||||
logger.Log(0, username) // $ hasTaintFlow="username"
|
||||
logger.Logf(0, username, "") // $ hasTaintFlow="username"
|
||||
logger.Logf(0, "", username) // $ hasTaintFlow="username"
|
||||
logger.Logln(0, username) // $ hasTaintFlow="username"
|
||||
logger.Panic(username) // $ hasTaintFlow="username"
|
||||
logger.Panicf(username, "") // $ hasTaintFlow="username"
|
||||
logger.Panicf("", username) // $ hasTaintFlow="username"
|
||||
logger.Panicln(username) // $ hasTaintFlow="username"
|
||||
logger.Print(username) // $ hasTaintFlow="username"
|
||||
logger.Printf(username, "") // $ hasTaintFlow="username"
|
||||
logger.Printf("", username) // $ hasTaintFlow="username"
|
||||
@@ -399,42 +311,26 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
logger.WithFields(fields) // $ hasTaintFlow="fields"
|
||||
|
||||
var fieldlogger logrus.FieldLogger = entry
|
||||
fieldlogger.Debug(username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Debugf(username, "") // $ hasTaintFlow="username"
|
||||
fieldlogger.Debugf("", username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Debugln(username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Error(username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Errorf(username, "") // $ hasTaintFlow="username"
|
||||
fieldlogger.Errorf("", username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Errorln(username) // $ hasTaintFlow="username"
|
||||
if testFlag == "37" {
|
||||
fieldlogger.Fatal(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "38" {
|
||||
fieldlogger.Fatalf(username, "") // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "39" {
|
||||
fieldlogger.Fatalf("", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "40" {
|
||||
fieldlogger.Fatalln(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
fieldlogger.Info(username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Infof(username, "") // $ hasTaintFlow="username"
|
||||
fieldlogger.Infof("", username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Infoln(username) // $ hasTaintFlow="username"
|
||||
if testFlag == "41" {
|
||||
fieldlogger.Panic(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "42" {
|
||||
fieldlogger.Panicf(username, "") // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "43" {
|
||||
fieldlogger.Panicf("", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "44" {
|
||||
fieldlogger.Panicln(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
fieldlogger.Debug(username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Debugf(username, "") // $ hasTaintFlow="username"
|
||||
fieldlogger.Debugf("", username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Debugln(username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Error(username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Errorf(username, "") // $ hasTaintFlow="username"
|
||||
fieldlogger.Errorf("", username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Errorln(username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Fatal(username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Fatalf(username, "") // $ hasTaintFlow="username"
|
||||
fieldlogger.Fatalf("", username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Fatalln(username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Info(username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Infof(username, "") // $ hasTaintFlow="username"
|
||||
fieldlogger.Infof("", username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Infoln(username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Panic(username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Panicf(username, "") // $ hasTaintFlow="username"
|
||||
fieldlogger.Panicf("", username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Panicln(username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Print(username) // $ hasTaintFlow="username"
|
||||
fieldlogger.Printf(username, "") // $ hasTaintFlow="username"
|
||||
fieldlogger.Printf("", username) // $ hasTaintFlow="username"
|
||||
@@ -470,11 +366,11 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
logger.DPanic(username) // $ hasTaintFlow="username"
|
||||
logger.Debug(username) // $ hasTaintFlow="username"
|
||||
logger.Error(username) // $ hasTaintFlow="username"
|
||||
if testFlag == "45" {
|
||||
if testFlag == " true" {
|
||||
logger.Fatal(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
logger.Info(username) // $ hasTaintFlow="username"
|
||||
if testFlag == "46" {
|
||||
if testFlag == " true" {
|
||||
logger.Panic(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
logger.Warn(username) // $ hasTaintFlow="username"
|
||||
@@ -486,33 +382,33 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
sLogger.DPanic(username) // $ hasTaintFlow="username"
|
||||
sLogger.Debug(username) // $ hasTaintFlow="username"
|
||||
sLogger.Error(username) // $ hasTaintFlow="username"
|
||||
if testFlag == "47" {
|
||||
if testFlag == " true" {
|
||||
sLogger.Fatal(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
sLogger.Info(username) // $ hasTaintFlow="username"
|
||||
if testFlag == "48" {
|
||||
if testFlag == " true" {
|
||||
sLogger.Panic(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
sLogger.Warn(username) // $ hasTaintFlow="username"
|
||||
sLogger.DPanicf(username) // $ hasTaintFlow="username"
|
||||
sLogger.Debugf(username) // $ hasTaintFlow="username"
|
||||
sLogger.Errorf(username) // $ hasTaintFlow="username"
|
||||
if testFlag == "49" {
|
||||
if testFlag == " true" {
|
||||
sLogger.Fatalf(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
sLogger.Infof(username) // $ hasTaintFlow="username"
|
||||
if testFlag == "50" {
|
||||
if testFlag == " true" {
|
||||
sLogger.Panicf(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
sLogger.Warnf(username) // $ hasTaintFlow="username"
|
||||
sLogger.DPanicw(username) // $ hasTaintFlow="username"
|
||||
sLogger.Debugw(username) // $ hasTaintFlow="username"
|
||||
sLogger.Errorw(username) // $ hasTaintFlow="username"
|
||||
if testFlag == "51" {
|
||||
if testFlag == " true" {
|
||||
sLogger.Fatalw(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
sLogger.Infow(username) // $ hasTaintFlow="username"
|
||||
if testFlag == "52" {
|
||||
if testFlag == " true" {
|
||||
sLogger.Panicw(username) // $ hasTaintFlow="username"
|
||||
}
|
||||
sLogger.Warnw(username) // $ hasTaintFlow="username"
|
||||
@@ -619,10 +515,10 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
verbose.Infof("user %q logged in.\n", username)
|
||||
klog.Infof("user %q logged in.\n", username)
|
||||
klog.Errorf("user %q logged in.\n", username)
|
||||
if testFlag == "53" {
|
||||
if testFlag == " true" {
|
||||
klog.Fatalf("user %q logged in.\n", username)
|
||||
}
|
||||
if testFlag == "54" {
|
||||
if testFlag == " true" {
|
||||
klog.Exitf("user %q logged in.\n", username)
|
||||
}
|
||||
}
|
||||
@@ -638,10 +534,10 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
|
||||
glog.Infof("user %q logged in.\n", username)
|
||||
glog.Errorf("user %q logged in.\n", username)
|
||||
if testFlag == "55" {
|
||||
if testFlag == " true" {
|
||||
glog.Fatalf("user %q logged in.\n", username)
|
||||
}
|
||||
if testFlag == "56" {
|
||||
if testFlag == " true" {
|
||||
glog.Exitf("user %q logged in.\n", username)
|
||||
}
|
||||
}
|
||||
@@ -649,11 +545,11 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
{
|
||||
logrus.Debugf("user %q logged in.\n", username)
|
||||
logrus.Errorf("user %q logged in.\n", username)
|
||||
if testFlag == "57" {
|
||||
if testFlag == " true" {
|
||||
logrus.Fatalf("user %q logged in.\n", username)
|
||||
}
|
||||
logrus.Infof("user %q logged in.\n", username)
|
||||
if testFlag == "58" {
|
||||
if testFlag == " true" {
|
||||
logrus.Panicf("user %q logged in.\n", username)
|
||||
}
|
||||
logrus.Printf("user %q logged in.\n", username)
|
||||
@@ -665,12 +561,12 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
entry := logrus.WithFields(fields)
|
||||
entry.Debugf("user %q logged in.\n", username)
|
||||
entry.Errorf("user %q logged in.\n", username)
|
||||
if testFlag == "59" {
|
||||
if testFlag == " true" {
|
||||
entry.Fatalf("user %q logged in.\n", username)
|
||||
}
|
||||
entry.Infof("user %q logged in.\n", username)
|
||||
entry.Logf(0, "user %q logged in.\n", username)
|
||||
if testFlag == "60" {
|
||||
if testFlag == " true" {
|
||||
entry.Panicf("user %q logged in.\n", username)
|
||||
}
|
||||
entry.Printf("user %q logged in.\n", username)
|
||||
@@ -681,12 +577,12 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
logger := entry.Logger
|
||||
logger.Debugf("user %q logged in.\n", username)
|
||||
logger.Errorf("user %q logged in.\n", username)
|
||||
if testFlag == "61" {
|
||||
if testFlag == " true" {
|
||||
logger.Fatalf("user %q logged in.\n", username)
|
||||
}
|
||||
logger.Infof("user %q logged in.\n", username)
|
||||
logger.Logf(0, "user %q logged in.\n", username)
|
||||
if testFlag == "62" {
|
||||
if testFlag == " true" {
|
||||
logger.Panicf("user %q logged in.\n", username)
|
||||
}
|
||||
logger.Printf("user %q logged in.\n", username)
|
||||
@@ -707,11 +603,11 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
sLogger.DPanicf("user %q logged in.\n", username)
|
||||
sLogger.Debugf("user %q logged in.\n", username)
|
||||
sLogger.Errorf("user %q logged in.\n", username)
|
||||
if testFlag == "63" {
|
||||
if testFlag == " true" {
|
||||
sLogger.Fatalf("user %q logged in.\n", username)
|
||||
}
|
||||
sLogger.Infof("user %q logged in.\n", username)
|
||||
if testFlag == "64" {
|
||||
if testFlag == " true" {
|
||||
sLogger.Panicf("user %q logged in.\n", username)
|
||||
}
|
||||
sLogger.Warnf("user %q logged in.\n", username)
|
||||
@@ -724,10 +620,10 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
verbose.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
klog.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
klog.Errorf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
if testFlag == "65" {
|
||||
if testFlag == " true" {
|
||||
klog.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "66" {
|
||||
if testFlag == " true" {
|
||||
klog.Exitf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
}
|
||||
@@ -743,10 +639,10 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
|
||||
glog.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
glog.Errorf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
if testFlag == "67" {
|
||||
if testFlag == " true" {
|
||||
glog.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
if testFlag == "68" {
|
||||
if testFlag == " true" {
|
||||
glog.Exitf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
}
|
||||
@@ -754,11 +650,11 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
{
|
||||
logrus.Debugf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
logrus.Errorf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
if testFlag == "69" {
|
||||
if testFlag == " true" {
|
||||
logrus.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
logrus.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
if testFlag == "70" {
|
||||
if testFlag == " true" {
|
||||
logrus.Panicf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
logrus.Printf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
@@ -770,12 +666,12 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
entry := logrus.WithFields(fields)
|
||||
entry.Debugf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
entry.Errorf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
if testFlag == "71" {
|
||||
if testFlag == " true" {
|
||||
entry.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
entry.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
entry.Logf(0, "user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
if testFlag == "72" {
|
||||
if testFlag == " true" {
|
||||
entry.Panicf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
entry.Printf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
@@ -786,12 +682,12 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
logger := entry.Logger
|
||||
logger.Debugf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
logger.Errorf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
if testFlag == "73" {
|
||||
if testFlag == " true" {
|
||||
logger.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
logger.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
logger.Logf(0, "user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
if testFlag == "74" {
|
||||
if testFlag == " true" {
|
||||
logger.Panicf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
logger.Printf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
@@ -812,11 +708,11 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
|
||||
sLogger.DPanicf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
sLogger.Debugf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
sLogger.Errorf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
if testFlag == "75" {
|
||||
if testFlag == " true" {
|
||||
sLogger.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
sLogger.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
if testFlag == "76" {
|
||||
if testFlag == " true" {
|
||||
sLogger.Panicf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
}
|
||||
sLogger.Warnf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
|
||||
|
||||
@@ -37,22 +37,22 @@
|
||||
| passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | $@ flows to a logging call. | passwords.go:26:14:26:23 | selection of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | $@ flows to a logging call. | passwords.go:27:14:27:26 | call to getPassword | Sensitive data returned by a call to getPassword |
|
||||
| passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | $@ flows to a logging call. | passwords.go:28:14:28:28 | call to getPassword | Sensitive data returned by a call to getPassword |
|
||||
| passwords.go:33:13:33:20 | password | passwords.go:21:2:21:9 | definition of password | passwords.go:33:13:33:20 | password | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:36:14:36:35 | ...+... | passwords.go:21:2:21:9 | definition of password | passwords.go:36:14:36:35 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:41:14:41:17 | obj1 | passwords.go:39:13:39:13 | x | passwords.go:41:14:41:17 | obj1 | $@ flows to a logging call. | passwords.go:39:13:39:13 | x | Sensitive data returned by an access to password |
|
||||
| passwords.go:46:14:46:17 | obj2 | passwords.go:21:2:21:9 | definition of password | passwords.go:46:14:46:17 | obj2 | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:53:14:53:27 | fixed_password | passwords.go:52:2:52:15 | definition of fixed_password | passwords.go:53:14:53:27 | fixed_password | $@ flows to a logging call. | passwords.go:52:2:52:15 | definition of fixed_password | Sensitive data returned by an access to fixed_password |
|
||||
| passwords.go:91:14:91:26 | utilityObject | passwords.go:89:16:89:36 | call to make | passwords.go:91:14:91:26 | utilityObject | $@ flows to a logging call. | passwords.go:89:16:89:36 | call to make | Sensitive data returned by an access to passwordSet |
|
||||
| passwords.go:94:23:94:28 | secret | passwords.go:21:2:21:9 | definition of password | passwords.go:94:23:94:28 | secret | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:104:15:104:40 | ...+... | passwords.go:21:2:21:9 | definition of password | passwords.go:104:15:104:40 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:110:16:110:41 | ...+... | passwords.go:21:2:21:9 | definition of password | passwords.go:110:16:110:41 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:115:15:115:40 | ...+... | passwords.go:21:2:21:9 | definition of password | passwords.go:115:15:115:40 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:119:14:119:45 | ...+... | passwords.go:118:6:118:14 | definition of password1 | passwords.go:119:14:119:45 | ...+... | $@ flows to a logging call. | passwords.go:118:6:118:14 | definition of password1 | Sensitive data returned by an access to password1 |
|
||||
| passwords.go:129:14:129:19 | config | passwords.go:21:2:21:9 | definition of password | passwords.go:129:14:129:19 | config | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:129:14:129:19 | config | passwords.go:123:13:123:14 | x3 | passwords.go:129:14:129:19 | config | $@ flows to a logging call. | passwords.go:123:13:123:14 | x3 | Sensitive data returned by an access to password |
|
||||
| passwords.go:129:14:129:19 | config | passwords.go:126:13:126:25 | call to getPassword | passwords.go:129:14:129:19 | config | $@ flows to a logging call. | passwords.go:126:13:126:25 | call to getPassword | Sensitive data returned by a call to getPassword |
|
||||
| passwords.go:130:14:130:21 | selection of x | passwords.go:21:2:21:9 | definition of password | passwords.go:130:14:130:21 | selection of x | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:131:14:131:21 | selection of y | passwords.go:126:13:126:25 | call to getPassword | passwords.go:131:14:131:21 | selection of y | $@ flows to a logging call. | passwords.go:126:13:126:25 | call to getPassword | Sensitive data returned by a call to getPassword |
|
||||
| passwords.go:32:12:32:19 | password | passwords.go:21:2:21:9 | definition of password | passwords.go:32:12:32:19 | password | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:34:14:34:35 | ...+... | passwords.go:21:2:21:9 | definition of password | passwords.go:34:14:34:35 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:39:14:39:17 | obj1 | passwords.go:37:13:37:13 | x | passwords.go:39:14:39:17 | obj1 | $@ flows to a logging call. | passwords.go:37:13:37:13 | x | Sensitive data returned by an access to password |
|
||||
| passwords.go:44:14:44:17 | obj2 | passwords.go:21:2:21:9 | definition of password | passwords.go:44:14:44:17 | obj2 | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:51:14:51:27 | fixed_password | passwords.go:50:2:50:15 | definition of fixed_password | passwords.go:51:14:51:27 | fixed_password | $@ flows to a logging call. | passwords.go:50:2:50:15 | definition of fixed_password | Sensitive data returned by an access to fixed_password |
|
||||
| passwords.go:89:14:89:26 | utilityObject | passwords.go:87:16:87:36 | call to make | passwords.go:89:14:89:26 | utilityObject | $@ flows to a logging call. | passwords.go:87:16:87:36 | call to make | Sensitive data returned by an access to passwordSet |
|
||||
| passwords.go:92:23:92:28 | secret | passwords.go:21:2:21:9 | definition of password | passwords.go:92:23:92:28 | secret | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:102:15:102:40 | ...+... | passwords.go:21:2:21:9 | definition of password | passwords.go:102:15:102:40 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:108:16:108:41 | ...+... | passwords.go:21:2:21:9 | definition of password | passwords.go:108:16:108:41 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:113:15:113:40 | ...+... | passwords.go:21:2:21:9 | definition of password | passwords.go:113:15:113:40 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:117:14:117:45 | ...+... | passwords.go:116:6:116:14 | definition of password1 | passwords.go:117:14:117:45 | ...+... | $@ flows to a logging call. | passwords.go:116:6:116:14 | definition of password1 | Sensitive data returned by an access to password1 |
|
||||
| passwords.go:127:14:127:19 | config | passwords.go:21:2:21:9 | definition of password | passwords.go:127:14:127:19 | config | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:127:14:127:19 | config | passwords.go:121:13:121:14 | x3 | passwords.go:127:14:127:19 | config | $@ flows to a logging call. | passwords.go:121:13:121:14 | x3 | Sensitive data returned by an access to password |
|
||||
| passwords.go:127:14:127:19 | config | passwords.go:124:13:124:25 | call to getPassword | passwords.go:127:14:127:19 | config | $@ flows to a logging call. | passwords.go:124:13:124:25 | call to getPassword | Sensitive data returned by a call to getPassword |
|
||||
| passwords.go:128:14:128:21 | selection of x | passwords.go:21:2:21:9 | definition of password | passwords.go:128:14:128:21 | selection of x | $@ flows to a logging call. | passwords.go:21:2:21:9 | definition of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:129:14:129:21 | selection of y | passwords.go:124:13:124:25 | call to getPassword | passwords.go:129:14:129:21 | selection of y | $@ flows to a logging call. | passwords.go:124:13:124:25 | call to getPassword | Sensitive data returned by a call to getPassword |
|
||||
| protobuf.go:14:14:14:35 | call to GetDescription | protobuf.go:9:2:9:9 | definition of password | protobuf.go:14:14:14:35 | call to GetDescription | $@ flows to a logging call. | protobuf.go:9:2:9:9 | definition of password | Sensitive data returned by an access to password |
|
||||
edges
|
||||
| klog.go:21:3:26:3 | range statement[1] | klog.go:22:27:22:33 | headers | provenance | |
|
||||
@@ -82,15 +82,95 @@ edges
|
||||
| main.go:53:11:53:18 | password | main.go:54:12:54:19 | password | provenance | |
|
||||
| main.go:53:11:53:18 | password | main.go:54:12:54:19 | password | provenance | |
|
||||
| main.go:54:12:54:19 | password | main.go:56:11:56:18 | password | provenance | |
|
||||
| main.go:54:12:54:19 | password | main.go:56:11:56:18 | password | provenance | |
|
||||
| main.go:54:12:54:19 | password | main.go:59:18:59:25 | password | provenance | |
|
||||
| main.go:54:12:54:19 | password | main.go:59:18:59:25 | password | provenance | |
|
||||
| main.go:54:12:54:19 | password | main.go:62:12:62:19 | password | provenance | |
|
||||
| main.go:54:12:54:19 | password | main.go:62:12:62:19 | password | provenance | Sink:MaD:7 |
|
||||
| main.go:54:12:54:19 | password | main.go:65:13:65:20 | password | provenance | |
|
||||
| main.go:54:12:54:19 | password | main.go:65:13:65:20 | password | provenance | |
|
||||
| main.go:54:12:54:19 | password | main.go:68:11:68:18 | password | provenance | |
|
||||
| main.go:54:12:54:19 | password | main.go:68:11:68:18 | password | provenance | |
|
||||
| main.go:54:12:54:19 | password | main.go:71:18:71:25 | password | provenance | |
|
||||
| main.go:54:12:54:19 | password | main.go:71:18:71:25 | password | provenance | |
|
||||
| main.go:54:12:54:19 | password | main.go:74:12:74:19 | password | provenance | |
|
||||
| main.go:54:12:54:19 | password | main.go:74:12:74:19 | password | provenance | Sink:MaD:9 |
|
||||
| main.go:54:12:54:19 | password | main.go:77:13:77:20 | password | provenance | |
|
||||
| main.go:54:12:54:19 | password | main.go:77:13:77:20 | password | provenance | |
|
||||
| main.go:54:12:54:19 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 |
|
||||
| main.go:54:12:54:19 | password | main.go:80:17:80:24 | password | provenance | |
|
||||
| main.go:56:11:56:18 | password | main.go:59:18:59:25 | password | provenance | |
|
||||
| main.go:56:11:56:18 | password | main.go:59:18:59:25 | password | provenance | |
|
||||
| main.go:56:11:56:18 | password | main.go:62:12:62:19 | password | provenance | |
|
||||
| main.go:56:11:56:18 | password | main.go:62:12:62:19 | password | provenance | Sink:MaD:7 |
|
||||
| main.go:56:11:56:18 | password | main.go:65:13:65:20 | password | provenance | |
|
||||
| main.go:56:11:56:18 | password | main.go:65:13:65:20 | password | provenance | |
|
||||
| main.go:56:11:56:18 | password | main.go:68:11:68:18 | password | provenance | |
|
||||
| main.go:56:11:56:18 | password | main.go:68:11:68:18 | password | provenance | |
|
||||
| main.go:56:11:56:18 | password | main.go:71:18:71:25 | password | provenance | |
|
||||
| main.go:56:11:56:18 | password | main.go:71:18:71:25 | password | provenance | |
|
||||
| main.go:56:11:56:18 | password | main.go:74:12:74:19 | password | provenance | |
|
||||
| main.go:56:11:56:18 | password | main.go:74:12:74:19 | password | provenance | Sink:MaD:9 |
|
||||
| main.go:56:11:56:18 | password | main.go:77:13:77:20 | password | provenance | |
|
||||
| main.go:56:11:56:18 | password | main.go:77:13:77:20 | password | provenance | |
|
||||
| main.go:56:11:56:18 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 |
|
||||
| main.go:56:11:56:18 | password | main.go:80:17:80:24 | password | provenance | |
|
||||
| main.go:59:18:59:25 | password | main.go:62:12:62:19 | password | provenance | |
|
||||
| main.go:59:18:59:25 | password | main.go:62:12:62:19 | password | provenance | Sink:MaD:7 |
|
||||
| main.go:59:18:59:25 | password | main.go:65:13:65:20 | password | provenance | |
|
||||
| main.go:59:18:59:25 | password | main.go:65:13:65:20 | password | provenance | |
|
||||
| main.go:59:18:59:25 | password | main.go:68:11:68:18 | password | provenance | |
|
||||
| main.go:59:18:59:25 | password | main.go:68:11:68:18 | password | provenance | |
|
||||
| main.go:59:18:59:25 | password | main.go:71:18:71:25 | password | provenance | |
|
||||
| main.go:59:18:59:25 | password | main.go:71:18:71:25 | password | provenance | |
|
||||
| main.go:59:18:59:25 | password | main.go:74:12:74:19 | password | provenance | |
|
||||
| main.go:59:18:59:25 | password | main.go:74:12:74:19 | password | provenance | Sink:MaD:9 |
|
||||
| main.go:59:18:59:25 | password | main.go:77:13:77:20 | password | provenance | |
|
||||
| main.go:59:18:59:25 | password | main.go:77:13:77:20 | password | provenance | |
|
||||
| main.go:59:18:59:25 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 |
|
||||
| main.go:59:18:59:25 | password | main.go:80:17:80:24 | password | provenance | |
|
||||
| main.go:62:12:62:19 | password | main.go:65:13:65:20 | password | provenance | |
|
||||
| main.go:62:12:62:19 | password | main.go:65:13:65:20 | password | provenance | |
|
||||
| main.go:62:12:62:19 | password | main.go:68:11:68:18 | password | provenance | |
|
||||
| main.go:62:12:62:19 | password | main.go:68:11:68:18 | password | provenance | |
|
||||
| main.go:62:12:62:19 | password | main.go:71:18:71:25 | password | provenance | |
|
||||
| main.go:62:12:62:19 | password | main.go:71:18:71:25 | password | provenance | |
|
||||
| main.go:62:12:62:19 | password | main.go:74:12:74:19 | password | provenance | |
|
||||
| main.go:62:12:62:19 | password | main.go:74:12:74:19 | password | provenance | Sink:MaD:9 |
|
||||
| main.go:62:12:62:19 | password | main.go:77:13:77:20 | password | provenance | |
|
||||
| main.go:62:12:62:19 | password | main.go:77:13:77:20 | password | provenance | |
|
||||
| main.go:62:12:62:19 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 |
|
||||
| main.go:62:12:62:19 | password | main.go:80:17:80:24 | password | provenance | |
|
||||
| main.go:65:13:65:20 | password | main.go:68:11:68:18 | password | provenance | |
|
||||
| main.go:65:13:65:20 | password | main.go:68:11:68:18 | password | provenance | |
|
||||
| main.go:65:13:65:20 | password | main.go:71:18:71:25 | password | provenance | |
|
||||
| main.go:65:13:65:20 | password | main.go:71:18:71:25 | password | provenance | |
|
||||
| main.go:65:13:65:20 | password | main.go:74:12:74:19 | password | provenance | |
|
||||
| main.go:65:13:65:20 | password | main.go:74:12:74:19 | password | provenance | Sink:MaD:9 |
|
||||
| main.go:65:13:65:20 | password | main.go:77:13:77:20 | password | provenance | |
|
||||
| main.go:65:13:65:20 | password | main.go:77:13:77:20 | password | provenance | |
|
||||
| main.go:65:13:65:20 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 |
|
||||
| main.go:65:13:65:20 | password | main.go:80:17:80:24 | password | provenance | |
|
||||
| main.go:68:11:68:18 | password | main.go:71:18:71:25 | password | provenance | |
|
||||
| main.go:68:11:68:18 | password | main.go:71:18:71:25 | password | provenance | |
|
||||
| main.go:68:11:68:18 | password | main.go:74:12:74:19 | password | provenance | |
|
||||
| main.go:68:11:68:18 | password | main.go:74:12:74:19 | password | provenance | Sink:MaD:9 |
|
||||
| main.go:68:11:68:18 | password | main.go:77:13:77:20 | password | provenance | |
|
||||
| main.go:68:11:68:18 | password | main.go:77:13:77:20 | password | provenance | |
|
||||
| main.go:68:11:68:18 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 |
|
||||
| main.go:68:11:68:18 | password | main.go:80:17:80:24 | password | provenance | |
|
||||
| main.go:71:18:71:25 | password | main.go:74:12:74:19 | password | provenance | |
|
||||
| main.go:71:18:71:25 | password | main.go:74:12:74:19 | password | provenance | Sink:MaD:9 |
|
||||
| main.go:71:18:71:25 | password | main.go:77:13:77:20 | password | provenance | |
|
||||
| main.go:71:18:71:25 | password | main.go:77:13:77:20 | password | provenance | |
|
||||
| main.go:71:18:71:25 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 |
|
||||
| main.go:71:18:71:25 | password | main.go:80:17:80:24 | password | provenance | |
|
||||
| main.go:74:12:74:19 | password | main.go:77:13:77:20 | password | provenance | |
|
||||
| main.go:74:12:74:19 | password | main.go:77:13:77:20 | password | provenance | |
|
||||
| main.go:74:12:74:19 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 |
|
||||
| main.go:74:12:74:19 | password | main.go:80:17:80:24 | password | provenance | |
|
||||
| main.go:77:13:77:20 | password | main.go:79:14:79:21 | password | provenance | Sink:MaD:8 |
|
||||
| main.go:77:13:77:20 | password | main.go:80:17:80:24 | password | provenance | |
|
||||
| main.go:80:17:80:24 | password | main.go:82:12:82:19 | password | provenance | |
|
||||
| main.go:80:17:80:24 | password | main.go:83:17:83:24 | password | provenance | |
|
||||
| main.go:80:17:80:24 | password | main.go:86:19:86:26 | password | provenance | |
|
||||
@@ -102,46 +182,46 @@ edges
|
||||
| passwords.go:8:12:8:12 | definition of x | passwords.go:9:14:9:14 | x | provenance | |
|
||||
| passwords.go:21:2:21:9 | definition of password | passwords.go:25:14:25:21 | password | provenance | |
|
||||
| passwords.go:21:2:21:9 | definition of password | passwords.go:30:8:30:15 | password | provenance | |
|
||||
| passwords.go:21:2:21:9 | definition of password | passwords.go:33:13:33:20 | password | provenance | |
|
||||
| passwords.go:21:2:21:9 | definition of password | passwords.go:36:28:36:35 | password | provenance | |
|
||||
| passwords.go:21:2:21:9 | definition of password | passwords.go:32:12:32:19 | password | provenance | |
|
||||
| passwords.go:21:2:21:9 | definition of password | passwords.go:34:28:34:35 | password | provenance | |
|
||||
| passwords.go:30:8:30:15 | password | passwords.go:8:12:8:12 | definition of x | provenance | |
|
||||
| passwords.go:36:28:36:35 | password | passwords.go:36:14:36:35 | ...+... | provenance | Config |
|
||||
| passwords.go:36:28:36:35 | password | passwords.go:44:6:44:13 | password | provenance | |
|
||||
| passwords.go:38:10:40:2 | struct literal | passwords.go:41:14:41:17 | obj1 | provenance | |
|
||||
| passwords.go:39:13:39:13 | x | passwords.go:38:10:40:2 | struct literal | provenance | Config |
|
||||
| passwords.go:43:10:45:2 | struct literal | passwords.go:46:14:46:17 | obj2 | provenance | |
|
||||
| passwords.go:44:6:44:13 | password | passwords.go:43:10:45:2 | struct literal | provenance | Config |
|
||||
| passwords.go:44:6:44:13 | password | passwords.go:50:11:50:18 | password | provenance | |
|
||||
| passwords.go:50:11:50:18 | password | passwords.go:94:23:94:28 | secret | provenance | |
|
||||
| passwords.go:50:11:50:18 | password | passwords.go:104:33:104:40 | password | provenance | |
|
||||
| passwords.go:50:11:50:18 | password | passwords.go:110:34:110:41 | password | provenance | |
|
||||
| passwords.go:50:11:50:18 | password | passwords.go:115:33:115:40 | password | provenance | |
|
||||
| passwords.go:50:11:50:18 | password | passwords.go:125:13:125:20 | password | provenance | |
|
||||
| passwords.go:52:2:52:15 | definition of fixed_password | passwords.go:53:14:53:27 | fixed_password | provenance | |
|
||||
| passwords.go:88:19:90:2 | struct literal | passwords.go:91:14:91:26 | utilityObject | provenance | |
|
||||
| passwords.go:89:16:89:36 | call to make | passwords.go:88:19:90:2 | struct literal | provenance | Config |
|
||||
| passwords.go:104:33:104:40 | password | passwords.go:104:15:104:40 | ...+... | provenance | Config |
|
||||
| passwords.go:104:33:104:40 | password | passwords.go:110:34:110:41 | password | provenance | |
|
||||
| passwords.go:104:33:104:40 | password | passwords.go:115:33:115:40 | password | provenance | |
|
||||
| passwords.go:104:33:104:40 | password | passwords.go:125:13:125:20 | password | provenance | |
|
||||
| passwords.go:110:34:110:41 | password | passwords.go:110:16:110:41 | ...+... | provenance | Config |
|
||||
| passwords.go:110:34:110:41 | password | passwords.go:115:33:115:40 | password | provenance | |
|
||||
| passwords.go:110:34:110:41 | password | passwords.go:125:13:125:20 | password | provenance | |
|
||||
| passwords.go:115:33:115:40 | password | passwords.go:115:15:115:40 | ...+... | provenance | Config |
|
||||
| passwords.go:115:33:115:40 | password | passwords.go:125:13:125:20 | password | provenance | |
|
||||
| passwords.go:118:6:118:14 | definition of password1 | passwords.go:119:28:119:36 | password1 | provenance | |
|
||||
| passwords.go:119:28:119:36 | password1 | passwords.go:119:28:119:45 | call to String | provenance | Config |
|
||||
| passwords.go:119:28:119:45 | call to String | passwords.go:119:14:119:45 | ...+... | provenance | Config |
|
||||
| passwords.go:122:12:127:2 | struct literal | passwords.go:129:14:129:19 | config | provenance | |
|
||||
| passwords.go:122:12:127:2 | struct literal [x] | passwords.go:130:14:130:19 | config [x] | provenance | |
|
||||
| passwords.go:122:12:127:2 | struct literal [y] | passwords.go:131:14:131:19 | config [y] | provenance | |
|
||||
| passwords.go:123:13:123:14 | x3 | passwords.go:122:12:127:2 | struct literal | provenance | Config |
|
||||
| passwords.go:125:13:125:20 | password | passwords.go:122:12:127:2 | struct literal | provenance | Config |
|
||||
| passwords.go:125:13:125:20 | password | passwords.go:122:12:127:2 | struct literal [x] | provenance | |
|
||||
| passwords.go:126:13:126:25 | call to getPassword | passwords.go:122:12:127:2 | struct literal | provenance | Config |
|
||||
| passwords.go:126:13:126:25 | call to getPassword | passwords.go:122:12:127:2 | struct literal [y] | provenance | |
|
||||
| passwords.go:130:14:130:19 | config [x] | passwords.go:130:14:130:21 | selection of x | provenance | |
|
||||
| passwords.go:131:14:131:19 | config [y] | passwords.go:131:14:131:21 | selection of y | provenance | |
|
||||
| passwords.go:34:28:34:35 | password | passwords.go:34:14:34:35 | ...+... | provenance | Config |
|
||||
| passwords.go:34:28:34:35 | password | passwords.go:42:6:42:13 | password | provenance | |
|
||||
| passwords.go:36:10:38:2 | struct literal | passwords.go:39:14:39:17 | obj1 | provenance | |
|
||||
| passwords.go:37:13:37:13 | x | passwords.go:36:10:38:2 | struct literal | provenance | Config |
|
||||
| passwords.go:41:10:43:2 | struct literal | passwords.go:44:14:44:17 | obj2 | provenance | |
|
||||
| passwords.go:42:6:42:13 | password | passwords.go:41:10:43:2 | struct literal | provenance | Config |
|
||||
| passwords.go:42:6:42:13 | password | passwords.go:48:11:48:18 | password | provenance | |
|
||||
| passwords.go:48:11:48:18 | password | passwords.go:92:23:92:28 | secret | provenance | |
|
||||
| passwords.go:48:11:48:18 | password | passwords.go:102:33:102:40 | password | provenance | |
|
||||
| passwords.go:48:11:48:18 | password | passwords.go:108:34:108:41 | password | provenance | |
|
||||
| passwords.go:48:11:48:18 | password | passwords.go:113:33:113:40 | password | provenance | |
|
||||
| passwords.go:48:11:48:18 | password | passwords.go:123:13:123:20 | password | provenance | |
|
||||
| passwords.go:50:2:50:15 | definition of fixed_password | passwords.go:51:14:51:27 | fixed_password | provenance | |
|
||||
| passwords.go:86:19:88:2 | struct literal | passwords.go:89:14:89:26 | utilityObject | provenance | |
|
||||
| passwords.go:87:16:87:36 | call to make | passwords.go:86:19:88:2 | struct literal | provenance | Config |
|
||||
| passwords.go:102:33:102:40 | password | passwords.go:102:15:102:40 | ...+... | provenance | Config |
|
||||
| passwords.go:102:33:102:40 | password | passwords.go:108:34:108:41 | password | provenance | |
|
||||
| passwords.go:102:33:102:40 | password | passwords.go:113:33:113:40 | password | provenance | |
|
||||
| passwords.go:102:33:102:40 | password | passwords.go:123:13:123:20 | password | provenance | |
|
||||
| passwords.go:108:34:108:41 | password | passwords.go:108:16:108:41 | ...+... | provenance | Config |
|
||||
| passwords.go:108:34:108:41 | password | passwords.go:113:33:113:40 | password | provenance | |
|
||||
| passwords.go:108:34:108:41 | password | passwords.go:123:13:123:20 | password | provenance | |
|
||||
| passwords.go:113:33:113:40 | password | passwords.go:113:15:113:40 | ...+... | provenance | Config |
|
||||
| passwords.go:113:33:113:40 | password | passwords.go:123:13:123:20 | password | provenance | |
|
||||
| passwords.go:116:6:116:14 | definition of password1 | passwords.go:117:28:117:36 | password1 | provenance | |
|
||||
| passwords.go:117:28:117:36 | password1 | passwords.go:117:28:117:45 | call to String | provenance | Config |
|
||||
| passwords.go:117:28:117:45 | call to String | passwords.go:117:14:117:45 | ...+... | provenance | Config |
|
||||
| passwords.go:120:12:125:2 | struct literal | passwords.go:127:14:127:19 | config | provenance | |
|
||||
| passwords.go:120:12:125:2 | struct literal [x] | passwords.go:128:14:128:19 | config [x] | provenance | |
|
||||
| passwords.go:120:12:125:2 | struct literal [y] | passwords.go:129:14:129:19 | config [y] | provenance | |
|
||||
| passwords.go:121:13:121:14 | x3 | passwords.go:120:12:125:2 | struct literal | provenance | Config |
|
||||
| passwords.go:123:13:123:20 | password | passwords.go:120:12:125:2 | struct literal | provenance | Config |
|
||||
| passwords.go:123:13:123:20 | password | passwords.go:120:12:125:2 | struct literal [x] | provenance | |
|
||||
| passwords.go:124:13:124:25 | call to getPassword | passwords.go:120:12:125:2 | struct literal | provenance | Config |
|
||||
| passwords.go:124:13:124:25 | call to getPassword | passwords.go:120:12:125:2 | struct literal [y] | provenance | |
|
||||
| passwords.go:128:14:128:19 | config [x] | passwords.go:128:14:128:21 | selection of x | provenance | |
|
||||
| passwords.go:129:14:129:19 | config [y] | passwords.go:129:14:129:21 | selection of y | provenance | |
|
||||
| protobuf.go:9:2:9:9 | definition of password | protobuf.go:12:22:12:29 | password | provenance | |
|
||||
| protobuf.go:12:2:12:6 | implicit dereference [postupdate] [Description] | protobuf.go:12:2:12:6 | query [postupdate] [pointer, Description] | provenance | |
|
||||
| protobuf.go:12:2:12:6 | query [postupdate] [pointer, Description] | protobuf.go:14:14:14:18 | query [pointer, Description] | provenance | |
|
||||
@@ -194,12 +274,20 @@ nodes
|
||||
| main.go:54:12:54:19 | password | semmle.label | password |
|
||||
| main.go:54:12:54:19 | password | semmle.label | password |
|
||||
| main.go:56:11:56:18 | password | semmle.label | password |
|
||||
| main.go:56:11:56:18 | password | semmle.label | password |
|
||||
| main.go:59:18:59:25 | password | semmle.label | password |
|
||||
| main.go:59:18:59:25 | password | semmle.label | password |
|
||||
| main.go:62:12:62:19 | password | semmle.label | password |
|
||||
| main.go:62:12:62:19 | password | semmle.label | password |
|
||||
| main.go:65:13:65:20 | password | semmle.label | password |
|
||||
| main.go:65:13:65:20 | password | semmle.label | password |
|
||||
| main.go:68:11:68:18 | password | semmle.label | password |
|
||||
| main.go:68:11:68:18 | password | semmle.label | password |
|
||||
| main.go:71:18:71:25 | password | semmle.label | password |
|
||||
| main.go:71:18:71:25 | password | semmle.label | password |
|
||||
| main.go:74:12:74:19 | password | semmle.label | password |
|
||||
| main.go:74:12:74:19 | password | semmle.label | password |
|
||||
| main.go:77:13:77:20 | password | semmle.label | password |
|
||||
| main.go:77:13:77:20 | password | semmle.label | password |
|
||||
| main.go:79:14:79:21 | password | semmle.label | password |
|
||||
| main.go:80:17:80:24 | password | semmle.label | password |
|
||||
@@ -220,43 +308,43 @@ nodes
|
||||
| passwords.go:27:14:27:26 | call to getPassword | semmle.label | call to getPassword |
|
||||
| passwords.go:28:14:28:28 | call to getPassword | semmle.label | call to getPassword |
|
||||
| passwords.go:30:8:30:15 | password | semmle.label | password |
|
||||
| passwords.go:33:13:33:20 | password | semmle.label | password |
|
||||
| passwords.go:36:14:36:35 | ...+... | semmle.label | ...+... |
|
||||
| passwords.go:36:28:36:35 | password | semmle.label | password |
|
||||
| passwords.go:38:10:40:2 | struct literal | semmle.label | struct literal |
|
||||
| passwords.go:39:13:39:13 | x | semmle.label | x |
|
||||
| passwords.go:41:14:41:17 | obj1 | semmle.label | obj1 |
|
||||
| passwords.go:43:10:45:2 | struct literal | semmle.label | struct literal |
|
||||
| passwords.go:44:6:44:13 | password | semmle.label | password |
|
||||
| passwords.go:46:14:46:17 | obj2 | semmle.label | obj2 |
|
||||
| passwords.go:50:11:50:18 | password | semmle.label | password |
|
||||
| passwords.go:52:2:52:15 | definition of fixed_password | semmle.label | definition of fixed_password |
|
||||
| passwords.go:53:14:53:27 | fixed_password | semmle.label | fixed_password |
|
||||
| passwords.go:88:19:90:2 | struct literal | semmle.label | struct literal |
|
||||
| passwords.go:89:16:89:36 | call to make | semmle.label | call to make |
|
||||
| passwords.go:91:14:91:26 | utilityObject | semmle.label | utilityObject |
|
||||
| passwords.go:94:23:94:28 | secret | semmle.label | secret |
|
||||
| passwords.go:104:15:104:40 | ...+... | semmle.label | ...+... |
|
||||
| passwords.go:104:33:104:40 | password | semmle.label | password |
|
||||
| passwords.go:110:16:110:41 | ...+... | semmle.label | ...+... |
|
||||
| passwords.go:110:34:110:41 | password | semmle.label | password |
|
||||
| passwords.go:115:15:115:40 | ...+... | semmle.label | ...+... |
|
||||
| passwords.go:115:33:115:40 | password | semmle.label | password |
|
||||
| passwords.go:118:6:118:14 | definition of password1 | semmle.label | definition of password1 |
|
||||
| passwords.go:119:14:119:45 | ...+... | semmle.label | ...+... |
|
||||
| passwords.go:119:28:119:36 | password1 | semmle.label | password1 |
|
||||
| passwords.go:119:28:119:45 | call to String | semmle.label | call to String |
|
||||
| passwords.go:122:12:127:2 | struct literal | semmle.label | struct literal |
|
||||
| passwords.go:122:12:127:2 | struct literal [x] | semmle.label | struct literal [x] |
|
||||
| passwords.go:122:12:127:2 | struct literal [y] | semmle.label | struct literal [y] |
|
||||
| passwords.go:123:13:123:14 | x3 | semmle.label | x3 |
|
||||
| passwords.go:125:13:125:20 | password | semmle.label | password |
|
||||
| passwords.go:126:13:126:25 | call to getPassword | semmle.label | call to getPassword |
|
||||
| passwords.go:129:14:129:19 | config | semmle.label | config |
|
||||
| passwords.go:130:14:130:19 | config [x] | semmle.label | config [x] |
|
||||
| passwords.go:130:14:130:21 | selection of x | semmle.label | selection of x |
|
||||
| passwords.go:131:14:131:19 | config [y] | semmle.label | config [y] |
|
||||
| passwords.go:131:14:131:21 | selection of y | semmle.label | selection of y |
|
||||
| passwords.go:32:12:32:19 | password | semmle.label | password |
|
||||
| passwords.go:34:14:34:35 | ...+... | semmle.label | ...+... |
|
||||
| passwords.go:34:28:34:35 | password | semmle.label | password |
|
||||
| passwords.go:36:10:38:2 | struct literal | semmle.label | struct literal |
|
||||
| passwords.go:37:13:37:13 | x | semmle.label | x |
|
||||
| passwords.go:39:14:39:17 | obj1 | semmle.label | obj1 |
|
||||
| passwords.go:41:10:43:2 | struct literal | semmle.label | struct literal |
|
||||
| passwords.go:42:6:42:13 | password | semmle.label | password |
|
||||
| passwords.go:44:14:44:17 | obj2 | semmle.label | obj2 |
|
||||
| passwords.go:48:11:48:18 | password | semmle.label | password |
|
||||
| passwords.go:50:2:50:15 | definition of fixed_password | semmle.label | definition of fixed_password |
|
||||
| passwords.go:51:14:51:27 | fixed_password | semmle.label | fixed_password |
|
||||
| passwords.go:86:19:88:2 | struct literal | semmle.label | struct literal |
|
||||
| passwords.go:87:16:87:36 | call to make | semmle.label | call to make |
|
||||
| passwords.go:89:14:89:26 | utilityObject | semmle.label | utilityObject |
|
||||
| passwords.go:92:23:92:28 | secret | semmle.label | secret |
|
||||
| passwords.go:102:15:102:40 | ...+... | semmle.label | ...+... |
|
||||
| passwords.go:102:33:102:40 | password | semmle.label | password |
|
||||
| passwords.go:108:16:108:41 | ...+... | semmle.label | ...+... |
|
||||
| passwords.go:108:34:108:41 | password | semmle.label | password |
|
||||
| passwords.go:113:15:113:40 | ...+... | semmle.label | ...+... |
|
||||
| passwords.go:113:33:113:40 | password | semmle.label | password |
|
||||
| passwords.go:116:6:116:14 | definition of password1 | semmle.label | definition of password1 |
|
||||
| passwords.go:117:14:117:45 | ...+... | semmle.label | ...+... |
|
||||
| passwords.go:117:28:117:36 | password1 | semmle.label | password1 |
|
||||
| passwords.go:117:28:117:45 | call to String | semmle.label | call to String |
|
||||
| passwords.go:120:12:125:2 | struct literal | semmle.label | struct literal |
|
||||
| passwords.go:120:12:125:2 | struct literal [x] | semmle.label | struct literal [x] |
|
||||
| passwords.go:120:12:125:2 | struct literal [y] | semmle.label | struct literal [y] |
|
||||
| passwords.go:121:13:121:14 | x3 | semmle.label | x3 |
|
||||
| passwords.go:123:13:123:20 | password | semmle.label | password |
|
||||
| passwords.go:124:13:124:25 | call to getPassword | semmle.label | call to getPassword |
|
||||
| passwords.go:127:14:127:19 | config | semmle.label | config |
|
||||
| passwords.go:128:14:128:19 | config [x] | semmle.label | config [x] |
|
||||
| passwords.go:128:14:128:21 | selection of x | semmle.label | selection of x |
|
||||
| passwords.go:129:14:129:19 | config [y] | semmle.label | config [y] |
|
||||
| passwords.go:129:14:129:21 | selection of y | semmle.label | selection of y |
|
||||
| protobuf.go:9:2:9:9 | definition of password | semmle.label | definition of password |
|
||||
| protobuf.go:12:2:12:6 | implicit dereference [postupdate] [Description] | semmle.label | implicit dereference [postupdate] [Description] |
|
||||
| protobuf.go:12:2:12:6 | query [postupdate] [pointer, Description] | semmle.label | query [postupdate] [pointer, Description] |
|
||||
|
||||
@@ -16,7 +16,7 @@ func redact(kind, value string) string {
|
||||
return value
|
||||
}
|
||||
|
||||
func test(selector int) {
|
||||
func test() {
|
||||
name := "user"
|
||||
password := "P@ssw0rd" // $ Source
|
||||
x := "horsebatterystapleincorrect"
|
||||
@@ -29,9 +29,7 @@ func test(selector int) {
|
||||
|
||||
myLog(password)
|
||||
|
||||
if selector == 1 {
|
||||
log.Panic(password) // $ Alert
|
||||
}
|
||||
log.Panic(password) // $ Alert
|
||||
|
||||
log.Println(name + ", " + password) // $ Alert
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ org.apache.hc.core5.http,73,2,45,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,72,,,,,,,,,,,
|
||||
org.apache.hc.core5.net,,,18,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,18,
|
||||
org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,18,6
|
||||
org.apache.hive.hcatalog.templeton,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,
|
||||
org.apache.http,53,3,117,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,51,,,,,,,,,,,,,,,,3,108,9
|
||||
org.apache.http,48,3,95,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,46,,,,,,,,,,,,,,,,3,86,9
|
||||
org.apache.ibatis.jdbc,6,,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,57,
|
||||
org.apache.ibatis.mapping,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.log4j,11,,,,,,,,,,,,,,,,,,,,,,11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
|
||||
|
@@ -13,7 +13,7 @@ Java framework & library support
|
||||
`Apache Commons IO <https://commons.apache.org/proper/commons-io/>`_,``org.apache.commons.io``,,570,124,105,,,,,15
|
||||
`Apache Commons Lang <https://commons.apache.org/proper/commons-lang/>`_,``org.apache.commons.lang3``,,425,7,,,,,,
|
||||
`Apache Commons Text <https://commons.apache.org/proper/commons-text/>`_,``org.apache.commons.text``,,272,,,,,,,
|
||||
`Apache HttpComponents <https://hc.apache.org/>`_,"``org.apache.hc.core5.*``, ``org.apache.http``",5,205,127,,3,,,,124
|
||||
`Apache HttpComponents <https://hc.apache.org/>`_,"``org.apache.hc.core5.*``, ``org.apache.http``",5,183,122,,3,,,,119
|
||||
`Apache Log4j 2 <https://logging.apache.org/log4j/2.0/>`_,``org.apache.logging.log4j``,,8,359,,,,,,
|
||||
`Apache Struts <https://struts.apache.org/>`_,"``org.apache.struts2``, ``org.apache.struts.beanvalidation.validation.interceptor``",,3877,14,,,,,,
|
||||
`Apache Velocity <https://velocity.apache.org/>`_,"``org.apache.velocity.app``, ``org.apache.velocity.runtime``",,,8,,,,,,
|
||||
@@ -41,5 +41,5 @@ Java framework & library support
|
||||
`Thymeleaf <https://www.thymeleaf.org/>`_,``org.thymeleaf``,,2,2,,,,,,
|
||||
`jOOQ <https://www.jooq.org/>`_,``org.jooq``,,,1,,,1,,,
|
||||
Others,"``actions.osgi``, ``antlr``, ``ch.ethz.ssh2``, ``cn.hutool.core.codec``, ``com.alibaba.com.caucho.hessian.io``, ``com.alibaba.druid.sql``, ``com.alibaba.fastjson2``, ``com.amazonaws.auth``, ``com.auth0.jwt.algorithms``, ``com.azure.identity``, ``com.caucho.burlap.io``, ``com.caucho.hessian.io``, ``com.cedarsoftware.util.io``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.esotericsoftware.yamlbeans``, ``com.hubspot.jinjava``, ``com.jcraft.jsch``, ``com.microsoft.sqlserver.jdbc``, ``com.mitchellbosecke.pebble``, ``com.opensymphony.xwork2``, ``com.sshtools.j2ssh.authentication``, ``com.sun.crypto.provider``, ``com.sun.jndi.ldap``, ``com.sun.net.httpserver``, ``com.sun.net.ssl``, ``com.sun.rowset``, ``com.sun.security.auth.module``, ``com.sun.security.ntlm``, ``com.sun.security.sasl.digest``, ``com.thoughtworks.xstream``, ``com.trilead.ssh2``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``hudson``, ``io.jsonwebtoken``, ``io.undertow.server.handlers.resource``, ``javafx.scene.web``, ``jenkins``, ``jodd.json``, ``liquibase.database.jvm``, ``liquibase.statement.core``, ``net.lingala.zip4j``, ``net.schmizz.sshj``, ``net.sf.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.acegisecurity``, ``org.antlr.runtime``, ``org.apache.avro``, ``org.apache.commons.codec``, ``org.apache.commons.compress.archivers.tar``, ``org.apache.commons.exec``, ``org.apache.commons.fileupload``, ``org.apache.commons.httpclient.util``, ``org.apache.commons.jelly``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.lang``, ``org.apache.commons.logging``, ``org.apache.commons.net``, ``org.apache.commons.ognl``, ``org.apache.cxf.catalog``, ``org.apache.cxf.common.classloader``, ``org.apache.cxf.common.jaxb``, ``org.apache.cxf.common.logging``, ``org.apache.cxf.configuration.jsse``, ``org.apache.cxf.helpers``, ``org.apache.cxf.resource``, ``org.apache.cxf.staxutils``, ``org.apache.cxf.tools.corba.utils``, ``org.apache.cxf.tools.util``, ``org.apache.cxf.transform``, ``org.apache.directory.ldap.client.api``, ``org.apache.hadoop.fs``, ``org.apache.hadoop.hive.metastore``, ``org.apache.hadoop.hive.ql.exec``, ``org.apache.hadoop.hive.ql.metadata``, ``org.apache.hc.client5.http.async.methods``, ``org.apache.hc.client5.http.classic.methods``, ``org.apache.hc.client5.http.fluent``, ``org.apache.hive.hcatalog.templeton``, ``org.apache.ibatis.jdbc``, ``org.apache.ibatis.mapping``, ``org.apache.log4j``, ``org.apache.shiro.authc``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.apache.shiro.mgt``, ``org.apache.sshd.client.session``, ``org.apache.tools.ant``, ``org.apache.tools.zip``, ``org.codehaus.cargo.container.installer``, ``org.dom4j``, ``org.exolab.castor.xml``, ``org.fusesource.leveldbjni``, ``org.geogebra.web.full.main``, ``org.gradle.api.file``, ``org.ho.yaml``, ``org.influxdb``, ``org.jabsorb``, ``org.jboss.vfs``, ``org.jdbi.v3.core``, ``org.jenkins.ui.icon``, ``org.jenkins.ui.symbol``, ``org.keycloak.models.map.storage``, ``org.kohsuke.stapler``, ``org.lastaflute.web``, ``org.mvel2``, ``org.openjdk.jmh.runner.options``, ``org.owasp.esapi``, ``org.pac4j.jwt.config.encryption``, ``org.pac4j.jwt.config.signature``, ``org.scijava.log``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.libs.ws``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``software.amazon.awssdk.transfer.s3.model``, ``sun.jvmstat.perfdata.monitor.protocol.local``, ``sun.jvmstat.perfdata.monitor.protocol.rmi``, ``sun.misc``, ``sun.net.ftp``, ``sun.net.www.protocol.http``, ``sun.security.acl``, ``sun.security.jgss.krb5``, ``sun.security.krb5``, ``sun.security.pkcs``, ``sun.security.pkcs11``, ``sun.security.provider``, ``sun.security.ssl``, ``sun.security.x509``, ``sun.tools.jconsole``",127,6034,775,148,6,14,18,,186
|
||||
Totals,,382,26403,2707,421,16,137,33,1,415
|
||||
Totals,,382,26381,2702,421,16,137,33,1,410
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Improved modeling of Apache HttpClient `execute` method sinks for `java/ssrf` and `java/non-https-url`.
|
||||
@@ -11,7 +11,7 @@ extensions:
|
||||
- ["org.apache.http.client.methods", "HttpPost", False, "HttpPost", "", "", "Argument[0]", "request-forgery", "manual"]
|
||||
- ["org.apache.http.client.methods", "HttpPut", False, "HttpPut", "", "", "Argument[0]", "request-forgery", "manual"]
|
||||
- ["org.apache.http.client.methods", "HttpRequestBase", True, "setURI", "", "", "Argument[0]", "request-forgery", "manual"]
|
||||
- ["org.apache.http.client.methods", "HttpRequestWrapper", True, "setURI", "(URI)", "", "Argument[0]", "request-forgery", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "HttpRequestWrapper", True, "setURI", "(URI)", "", "Argument[0]", "request-forgery", "hq-manual"]
|
||||
- ["org.apache.http.client.methods", "HttpTrace", False, "HttpTrace", "", "", "Argument[0]", "request-forgery", "manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", False, "delete", "", "", "Argument[0]", "request-forgery", "manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", False, "get", "", "", "Argument[0]", "request-forgery", "manual"]
|
||||
@@ -22,29 +22,3 @@ extensions:
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", False, "put", "", "", "Argument[0]", "request-forgery", "manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", False, "setUri", "", "", "Argument[0]", "request-forgery", "manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", False, "trace", "", "", "Argument[0]", "request-forgery", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/java-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "build", "()", "", "Argument[this]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "delete", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "delete", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "get", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "get", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "getUri", "()", "", "Argument[this]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "head", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "head", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "options", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "options", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "patch", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "patch", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "post", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "post", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "put", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "put", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "setUri", "(String)", "", "Argument[0]", "Argument[this]", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "setUri", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "setUri", "(URI)", "", "Argument[0]", "Argument[this]", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "setUri", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "trace", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
|
||||
- ["org.apache.http.client.methods", "RequestBuilder", True, "trace", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
|
||||
|
||||
@@ -3,11 +3,6 @@ extensions:
|
||||
pack: codeql/java-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["org.apache.http.client", "HttpClient", True, "execute", "(HttpHost,HttpRequest)", "", "Argument[0]", "request-forgery", "ai-manual"]
|
||||
- ["org.apache.http.client", "HttpClient", True, "execute", "(HttpHost,HttpRequest,HttpContext)", "", "Argument[0]", "request-forgery", "ai-manual"]
|
||||
- ["org.apache.http.client", "HttpClient", True, "execute", "(HttpHost,HttpRequest,ResponseHandler)", "", "Argument[0]", "request-forgery", "ai-manual"]
|
||||
- ["org.apache.http.client", "HttpClient", True, "execute", "(HttpHost,HttpRequest,ResponseHandler,HttpContext)", "", "Argument[0]", "request-forgery", "ai-manual"]
|
||||
- ["org.apache.http.client", "HttpClient", True, "execute", "(HttpUriRequest)", "", "Argument[0]", "request-forgery", "ai-manual"]
|
||||
- ["org.apache.http.client", "HttpClient", True, "execute", "(HttpUriRequest,HttpContext)", "", "Argument[0]", "request-forgery", "ai-manual"]
|
||||
- ["org.apache.http.client", "HttpClient", True, "execute", "(HttpUriRequest,ResponseHandler)", "", "Argument[0]", "request-forgery", "ai-manual"]
|
||||
- ["org.apache.http.client", "HttpClient", True, "execute", "(HttpUriRequest,ResponseHandler,HttpContext)", "", "Argument[0]", "request-forgery", "ai-manual"]
|
||||
- ["org.apache.http.client", "HttpClient", True, "execute", "(HttpUriRequest)", "", "Argument[0]", "request-forgery", "ai-manual"]
|
||||
|
||||
@@ -4,33 +4,67 @@
|
||||
overlay[local?]
|
||||
module;
|
||||
|
||||
private import java as J
|
||||
private import semmle.code.java.dataflow.SSA
|
||||
private import semmle.code.java.dataflow.RangeUtils as RU
|
||||
private import codeql.rangeanalysis.Bound as SharedBound
|
||||
private import internal.rangeanalysis.BoundSpecific
|
||||
|
||||
private module BoundDefs implements SharedBound::BoundDefinitions<J::Location> {
|
||||
class SsaVariable extends Ssa::SsaDefinition {
|
||||
/** Gets a use of this variable. */
|
||||
Expr getAUse() { result = super.getARead() }
|
||||
private newtype TBound =
|
||||
TBoundZero() or
|
||||
TBoundSsa(SsaVariable v) { v.getSourceVariable().getType() instanceof IntegralType } or
|
||||
TBoundExpr(Expr e) {
|
||||
interestingExprBound(e) and
|
||||
not exists(SsaVariable v | e = v.getAUse())
|
||||
}
|
||||
|
||||
class SsaSourceVariable = Ssa::SourceVariable;
|
||||
/**
|
||||
* A bound that may be inferred for an expression plus/minus an integer delta.
|
||||
*/
|
||||
abstract class Bound extends TBound {
|
||||
/** Gets a textual representation of this bound. */
|
||||
abstract string toString();
|
||||
|
||||
class Type = J::Type;
|
||||
/** Gets an expression that equals this bound plus `delta`. */
|
||||
abstract Expr getExpr(int delta);
|
||||
|
||||
class Expr = J::Expr;
|
||||
/** Gets an expression that equals this bound. */
|
||||
Expr getExpr() { result = this.getExpr(0) }
|
||||
|
||||
class IntegralType = J::IntegralType;
|
||||
|
||||
class ConstantIntegerExpr = RU::ConstantIntegerExpr;
|
||||
|
||||
/** Holds if `e` is a bound expression and it is not an SSA variable read. */
|
||||
predicate interestingExprBound(Expr e) {
|
||||
e.(J::FieldRead).getField() instanceof J::ArrayLengthField
|
||||
}
|
||||
/** Gets the location of this bound. */
|
||||
abstract Location getLocation();
|
||||
}
|
||||
|
||||
module BoundImpl = SharedBound::Bound<J::Location, BoundDefs>;
|
||||
/**
|
||||
* The bound that corresponds to the integer 0. This is used to represent all
|
||||
* integer bounds as bounds are always accompanied by an added integer delta.
|
||||
*/
|
||||
class ZeroBound extends Bound, TBoundZero {
|
||||
override string toString() { result = "0" }
|
||||
|
||||
import BoundImpl
|
||||
override Expr getExpr(int delta) { result.(ConstantIntegerExpr).getIntValue() = delta }
|
||||
|
||||
override Location getLocation() { result.hasLocationInfo("", 0, 0, 0, 0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bound corresponding to the value of an SSA variable.
|
||||
*/
|
||||
class SsaBound extends Bound, TBoundSsa {
|
||||
/** Gets the SSA variable that equals this bound. */
|
||||
SsaVariable getSsa() { this = TBoundSsa(result) }
|
||||
|
||||
override string toString() { result = this.getSsa().toString() }
|
||||
|
||||
override Expr getExpr(int delta) { result = this.getSsa().getAUse() and delta = 0 }
|
||||
|
||||
override Location getLocation() { result = this.getSsa().getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bound that corresponds to the value of a specific expression that might be
|
||||
* interesting, but isn't otherwise represented by the value of an SSA variable.
|
||||
*/
|
||||
class ExprBound extends Bound, TBoundExpr {
|
||||
override string toString() { result = this.getExpr().toString() }
|
||||
|
||||
override Expr getExpr(int delta) { this = TBoundExpr(result) and delta = 0 }
|
||||
|
||||
override Location getLocation() { result = this.getExpr().getLocation() }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Provides Java-specific definitions for bounds.
|
||||
*/
|
||||
overlay[local?]
|
||||
module;
|
||||
|
||||
private import java as J
|
||||
private import semmle.code.java.dataflow.SSA as Ssa
|
||||
private import semmle.code.java.dataflow.RangeUtils as RU
|
||||
|
||||
class SsaVariable extends Ssa::SsaDefinition {
|
||||
/** Gets a use of this variable. */
|
||||
Expr getAUse() { result = super.getARead() }
|
||||
}
|
||||
|
||||
class Expr = J::Expr;
|
||||
|
||||
class Location = J::Location;
|
||||
|
||||
class IntegralType = J::IntegralType;
|
||||
|
||||
class ConstantIntegerExpr = RU::ConstantIntegerExpr;
|
||||
|
||||
/** Holds if `e` is a bound expression and it is not an SSA variable read. */
|
||||
predicate interestingExprBound(Expr e) {
|
||||
e.(J::FieldRead).getField() instanceof J::ArrayLengthField
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.ResponseHandler;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.client.methods.RequestBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.message.BasicHttpRequest;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class ApacheHttpClientExecuteSSRF extends HttpServlet {
|
||||
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
try {
|
||||
|
||||
String source = request.getParameter("host"); // $ Source
|
||||
|
||||
HttpHost host = new HttpHost(source);
|
||||
HttpRequest req = new BasicHttpRequest("GET", "/");
|
||||
HttpUriRequest uriReq = RequestBuilder.get(source).build(); // $ Alert
|
||||
HttpContext context = null;
|
||||
HttpClient client = HttpClients.createDefault();
|
||||
ResponseHandler<Object> handler = null;
|
||||
|
||||
client.execute(host, req); // $ Alert
|
||||
client.execute(host, req, context); // $ Alert
|
||||
client.execute(host, req, handler); // $ Alert
|
||||
client.execute(host, req, handler, context); // $ Alert
|
||||
client.execute(uriReq); // $ Alert
|
||||
client.execute(uriReq, context); // $ Alert
|
||||
client.execute(uriReq, handler); // $ Alert
|
||||
client.execute(uriReq, handler, context); // $ Alert
|
||||
|
||||
} catch (Exception e) {
|
||||
// TODO: handle exception
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1 +1 @@
|
||||
//semmle-extractor-options: --javac-args -source 11 -target 11 -cp ${testdir}/../../../stubs/javax-validation-constraints:${testdir}/../../../stubs/springframework-5.8.x:${testdir}/../../../stubs/javax-ws-rs-api-2.1.1:${testdir}/../../../stubs/javax-ws-rs-api-3.0.0:${testdir}/../../../stubs/apache-http-4.4.13/:${testdir}/../../../stubs/apache-http-client-4.4.13:${testdir}/../../../stubs/projectreactor-3.4.3/:${testdir}/../../../stubs/postgresql-42.3.3/:${testdir}/../../../stubs/HikariCP-3.4.5/:${testdir}/../../../stubs/spring-jdbc-5.3.8/:${testdir}/../../../stubs/jdbi3-core-3.27.2/:${testdir}/../../../stubs/cargo:${testdir}/../../../stubs/javafx-web:${testdir}/../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../stubs/dom4j-2.1.1:${testdir}/../../../stubs/jaxen-1.2.0:${testdir}/../../../stubs/stapler-1.263:${testdir}/../../../stubs/javax-servlet-2.5:${testdir}/../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../stubs/saxon-xqj-9.x:${testdir}/../../../stubs/apache-commons-beanutils:${testdir}/../../../stubs/apache-commons-lang:${testdir}/../../../stubs/apache-http-5:${testdir}/../../../stubs/playframework-2.6.x:${testdir}/../../../stubs/jaxws-api-2.0:${testdir}/../../../stubs/apache-cxf
|
||||
//semmle-extractor-options: --javac-args -source 11 -target 11 -cp ${testdir}/../../../stubs/javax-validation-constraints:${testdir}/../../../stubs/springframework-5.8.x:${testdir}/../../../stubs/javax-ws-rs-api-2.1.1:${testdir}/../../../stubs/javax-ws-rs-api-3.0.0:${testdir}/../../../stubs/apache-http-4.4.13/:${testdir}/../../../stubs/projectreactor-3.4.3/:${testdir}/../../../stubs/postgresql-42.3.3/:${testdir}/../../../stubs/HikariCP-3.4.5/:${testdir}/../../../stubs/spring-jdbc-5.3.8/:${testdir}/../../../stubs/jdbi3-core-3.27.2/:${testdir}/../../../stubs/cargo:${testdir}/../../../stubs/javafx-web:${testdir}/../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../stubs/dom4j-2.1.1:${testdir}/../../../stubs/jaxen-1.2.0:${testdir}/../../../stubs/stapler-1.263:${testdir}/../../../stubs/javax-servlet-2.5:${testdir}/../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../stubs/saxon-xqj-9.x:${testdir}/../../../stubs/apache-commons-beanutils:${testdir}/../../../stubs/apache-commons-lang:${testdir}/../../../stubs/apache-http-5:${testdir}/../../../stubs/playframework-2.6.x:${testdir}/../../../stubs/jaxws-api-2.0:${testdir}/../../../stubs/apache-cxf
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
// Generated automatically from org.apache.http.client.HttpClient for testing purposes
|
||||
|
||||
package org.apache.http.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
|
||||
public interface HttpClient {
|
||||
HttpResponse execute(HttpHost target, HttpRequest request) throws IOException;
|
||||
HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) throws IOException;
|
||||
<T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler) throws IOException;
|
||||
<T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context)
|
||||
throws IOException;
|
||||
HttpResponse execute(HttpUriRequest request) throws IOException;
|
||||
HttpResponse execute(HttpUriRequest request, HttpContext context) throws IOException;
|
||||
<T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler) throws IOException;
|
||||
<T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context)
|
||||
throws IOException;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
// Generated automatically from org.apache.http.client.ResponseHandler for testing purposes
|
||||
|
||||
package org.apache.http.client;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
|
||||
public interface ResponseHandler<T> {
|
||||
T handleResponse(HttpResponse response);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package org.apache.http.impl.client;
|
||||
|
||||
import org.apache.http.client.HttpClient;
|
||||
|
||||
public abstract class CloseableHttpClient implements HttpClient {
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
// Generated automatically from org.apache.http.client.HttpClient for testing purposes
|
||||
|
||||
package org.apache.http.impl.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
|
||||
public final class HttpClients {
|
||||
public static CloseableHttpClient createDefault() { return null; }
|
||||
}
|
||||
@@ -21,19 +21,13 @@ file_coverage_languages:
|
||||
scc_languages:
|
||||
- TypeScript
|
||||
- TypeScript Typings
|
||||
- name: vue
|
||||
display_name: Vue.js component
|
||||
scc_languages:
|
||||
- Vue
|
||||
github_api_languages:
|
||||
- JavaScript
|
||||
- TypeScript
|
||||
- Vue
|
||||
scc_languages:
|
||||
- JavaScript
|
||||
- TypeScript
|
||||
- TypeScript Typings
|
||||
- Vue
|
||||
file_types:
|
||||
- name: javascript
|
||||
display_name: JavaScript
|
||||
|
||||
@@ -36,8 +36,6 @@ private module Input implements InputSig<Location, PythonDataFlow> {
|
||||
// parameter, but dataflow-consistency queries should _not_ complain about there not
|
||||
// being a post-update node for the synthetic `**kwargs` parameter.
|
||||
n instanceof SynthDictSplatParameterNode
|
||||
or
|
||||
Private::Conversions::readStep(n, _, _)
|
||||
}
|
||||
|
||||
predicate uniqueParameterNodePositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) {
|
||||
|
||||
@@ -213,9 +213,11 @@ class ExprWithPointsTo extends Expr {
|
||||
* Gets what this expression might "refer-to" in the given `context`.
|
||||
*/
|
||||
predicate refersTo(Context context, Object obj, ClassObject cls, AstNode origin) {
|
||||
this.getAFlowNode()
|
||||
.(ControlFlowNodeWithPointsTo)
|
||||
.refersTo(context, obj, cls, origin.getAFlowNode())
|
||||
exists(ControlFlowNode this_, ControlFlowNode origin_ |
|
||||
this_.getNode() = this and origin_.getNode() = origin
|
||||
|
|
||||
this_.(ControlFlowNodeWithPointsTo).refersTo(context, obj, cls, origin_)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,7 +228,11 @@ class ExprWithPointsTo extends Expr {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate refersTo(Object obj, AstNode origin) {
|
||||
this.getAFlowNode().(ControlFlowNodeWithPointsTo).refersTo(obj, origin.getAFlowNode())
|
||||
exists(ControlFlowNode this_, ControlFlowNode origin_ |
|
||||
this_.getNode() = this and origin_.getNode() = origin
|
||||
|
|
||||
this_.(ControlFlowNodeWithPointsTo).refersTo(obj, origin_)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -240,16 +246,22 @@ class ExprWithPointsTo extends Expr {
|
||||
* in the given `context`.
|
||||
*/
|
||||
predicate pointsTo(Context context, Value value, AstNode origin) {
|
||||
this.getAFlowNode()
|
||||
.(ControlFlowNodeWithPointsTo)
|
||||
.pointsTo(context, value, origin.getAFlowNode())
|
||||
exists(ControlFlowNode this_, ControlFlowNode origin_ |
|
||||
this_.getNode() = this and origin_.getNode() = origin
|
||||
|
|
||||
this_.(ControlFlowNodeWithPointsTo).pointsTo(context, value, origin_)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this expression might "point-to" to `value` which is from `origin`.
|
||||
*/
|
||||
predicate pointsTo(Value value, AstNode origin) {
|
||||
this.getAFlowNode().(ControlFlowNodeWithPointsTo).pointsTo(value, origin.getAFlowNode())
|
||||
exists(ControlFlowNode this_, ControlFlowNode origin_ |
|
||||
this_.getNode() = this and origin_.getNode() = origin
|
||||
|
|
||||
this_.(ControlFlowNodeWithPointsTo).pointsTo(value, origin_)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -475,7 +487,10 @@ class FunctionMetricsWithPointsTo extends FunctionMetrics {
|
||||
not non_coupling_method(result) and
|
||||
exists(Call call | call.getScope() = this |
|
||||
exists(FunctionObject callee | callee.getFunction() = result |
|
||||
call.getAFlowNode().getFunction().(ControlFlowNodeWithPointsTo).refersTo(callee)
|
||||
exists(CallNode call_ |
|
||||
call_.getNode() = call and
|
||||
call_.getFunction().(ControlFlowNodeWithPointsTo).refersTo(callee)
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(Attribute a | call.getFunc() = a |
|
||||
|
||||
@@ -64,7 +64,7 @@ private predicate jump_to_defn(ControlFlowNode use, Definition defn) {
|
||||
private predicate preferred_jump_to_defn(Expr use, Definition def) {
|
||||
not use instanceof ClassExpr and
|
||||
not use instanceof FunctionExpr and
|
||||
jump_to_defn(use.getAFlowNode(), def)
|
||||
exists(ControlFlowNode useNode | useNode.getNode() = use | jump_to_defn(useNode, def))
|
||||
}
|
||||
|
||||
private predicate unique_jump_to_defn(Expr use, Definition def) {
|
||||
@@ -452,7 +452,7 @@ private predicate self_parameter_jump_to_defn_attribute(
|
||||
* This exists primarily for testing use `getPreferredDefinition()` instead.
|
||||
*/
|
||||
Definition getADefinition(Expr use) {
|
||||
jump_to_defn(use.getAFlowNode(), result) and
|
||||
exists(ControlFlowNode useNode | useNode.getNode() = use | jump_to_defn(useNode, result)) and
|
||||
not use instanceof Call and
|
||||
not use.isArtificial() and
|
||||
// Not the use itself
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* The `AstNode.getAFlowNode()` predicate has been deprecated. Use `ControlFlowNode.getNode()` from the other direction instead: replace `e.getAFlowNode() = n` with `n.getNode() = e`. This is a preparatory step towards migrating the dataflow library off the legacy CFG; it has no semantic effect.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Python taint tracking is now more precise for values flowing through container contents, such as list, set, tuple, and dictionary elements. This may remove some false positive alerts.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* The `Function.getAReturnValueFlowNode()` predicate has been deprecated. Bind a `Return` node explicitly instead — `exists(Return ret | ret.getScope() = f and n.getNode() = ret.getValue())`. This is a preparatory step towards migrating the dataflow library off the legacy CFG; it has no semantic effect.
|
||||
@@ -16,21 +16,26 @@ abstract class AstNode extends AstNode_ {
|
||||
/** Gets the scope that this node occurs in */
|
||||
abstract Scope getScope();
|
||||
|
||||
/**
|
||||
* Gets a flow node corresponding directly to this node.
|
||||
* NOTE: For some statements and other purely syntactic elements,
|
||||
* there may not be a `ControlFlowNode`
|
||||
*/
|
||||
cached
|
||||
ControlFlowNode getAFlowNode() {
|
||||
Stages::AST::ref() and
|
||||
py_flow_bb_node(result, this, _, _)
|
||||
}
|
||||
|
||||
/** Gets the location for this AST node */
|
||||
cached
|
||||
Location getLocation() { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `ControlFlowNode.getNode()` from the other direction instead;
|
||||
* that is, replace `e.getAFlowNode() = n` with `n.getNode() = e`. This API is
|
||||
* being removed to untangle the AST and CFG hierarchies in preparation for
|
||||
* migrating the dataflow library off the legacy CFG.
|
||||
*
|
||||
* Gets a flow node corresponding directly to this node.
|
||||
* NOTE: For some statements and other purely syntactic elements,
|
||||
* there may not be a `ControlFlowNode`.
|
||||
*/
|
||||
cached
|
||||
deprecated ControlFlowNode getAFlowNode() {
|
||||
Stages::AST::ref() and
|
||||
py_flow_bb_node(result, this, _, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this syntactic element is artificial, that is it is generated
|
||||
* by the compiler and is not present in the source
|
||||
|
||||
@@ -28,7 +28,9 @@ class Expr extends Expr_, AstNode {
|
||||
/** Whether this expression may have a side effect (as determined purely from its syntax) */
|
||||
predicate hasSideEffects() {
|
||||
/* If an exception raised by this expression handled, count that as a side effect */
|
||||
this.getAFlowNode().getASuccessor().getNode() instanceof ExceptStmt
|
||||
exists(ControlFlowNode n | n.getNode() = this |
|
||||
n.getASuccessor().getNode() instanceof ExceptStmt
|
||||
)
|
||||
or
|
||||
this.getASubExpression().hasSideEffects()
|
||||
}
|
||||
@@ -68,8 +70,6 @@ class Attribute extends Attribute_ {
|
||||
/* syntax: Expr.name */
|
||||
override Expr getASubExpression() { result = this.getObject() }
|
||||
|
||||
override AttrNode getAFlowNode() { result = super.getAFlowNode() }
|
||||
|
||||
/** Gets the name of this attribute. That is the `name` in `obj.name` */
|
||||
string getName() { result = Attribute_.super.getAttr() }
|
||||
|
||||
@@ -96,8 +96,6 @@ class Subscript extends Subscript_ {
|
||||
}
|
||||
|
||||
Expr getObject() { result = Subscript_.super.getValue() }
|
||||
|
||||
override SubscriptNode getAFlowNode() { result = super.getAFlowNode() }
|
||||
}
|
||||
|
||||
/** A call expression, such as `func(...)` */
|
||||
@@ -113,8 +111,6 @@ class Call extends Call_ {
|
||||
|
||||
override string toString() { result = this.getFunc().toString() + "()" }
|
||||
|
||||
override CallNode getAFlowNode() { result = super.getAFlowNode() }
|
||||
|
||||
/** Gets a tuple (*) argument of this call. */
|
||||
Expr getStarargs() { result = this.getAPositionalArg().(Starred).getValue() }
|
||||
|
||||
@@ -200,8 +196,6 @@ class IfExp extends IfExp_ {
|
||||
override Expr getASubExpression() {
|
||||
result = this.getTest() or result = this.getBody() or result = this.getOrelse()
|
||||
}
|
||||
|
||||
override IfExprNode getAFlowNode() { result = super.getAFlowNode() }
|
||||
}
|
||||
|
||||
/** A starred expression, such as the `*rest` in the assignment `first, *rest = seq` */
|
||||
@@ -410,8 +404,6 @@ class PlaceHolder extends PlaceHolder_ {
|
||||
override Expr getASubExpression() { none() }
|
||||
|
||||
override string toString() { result = "$" + this.getId() }
|
||||
|
||||
override NameNode getAFlowNode() { result = super.getAFlowNode() }
|
||||
}
|
||||
|
||||
/** A tuple expression such as `( 1, 3, 5, 7, 9 )` */
|
||||
@@ -478,8 +470,6 @@ class Name extends Name_ {
|
||||
|
||||
override string toString() { result = this.getId() }
|
||||
|
||||
override NameNode getAFlowNode() { result = super.getAFlowNode() }
|
||||
|
||||
override predicate isArtificial() {
|
||||
/* Artificial variable names in comprehensions all start with "." */
|
||||
this.getId().charAt(0) = "."
|
||||
@@ -585,8 +575,6 @@ abstract class NameConstant extends Name, ImmutableLiteral {
|
||||
|
||||
override predicate isConstant() { any() }
|
||||
|
||||
override NameConstantNode getAFlowNode() { result = Name.super.getAFlowNode() }
|
||||
|
||||
override predicate isArtificial() { none() }
|
||||
}
|
||||
|
||||
|
||||
@@ -555,27 +555,27 @@ class DefinitionNode extends ControlFlowNode {
|
||||
cached
|
||||
DefinitionNode() {
|
||||
Stages::AST::ref() and
|
||||
exists(Assign a | a.getATarget().getAFlowNode() = this)
|
||||
exists(Assign a | this.getNode() = a.getATarget())
|
||||
or
|
||||
exists(AssignExpr a | a.getTarget().getAFlowNode() = this)
|
||||
exists(AssignExpr a | this.getNode() = a.getTarget())
|
||||
or
|
||||
exists(AnnAssign a | a.getTarget().getAFlowNode() = this and exists(a.getValue()))
|
||||
exists(AnnAssign a | this.getNode() = a.getTarget() and exists(a.getValue()))
|
||||
or
|
||||
exists(Alias a | a.getAsname().getAFlowNode() = this)
|
||||
exists(Alias a | this.getNode() = a.getAsname())
|
||||
or
|
||||
augstore(_, this)
|
||||
or
|
||||
// `x, y = 1, 2` where LHS is a combination of list or tuples
|
||||
exists(Assign a | list_or_tuple_nested_element(a.getATarget()).getAFlowNode() = this)
|
||||
exists(Assign a | this.getNode() = list_or_tuple_nested_element(a.getATarget()))
|
||||
or
|
||||
exists(For for | for.getTarget().getAFlowNode() = this)
|
||||
exists(For for | this.getNode() = for.getTarget())
|
||||
or
|
||||
exists(Parameter param | this = param.asName().getAFlowNode() and exists(param.getDefault()))
|
||||
exists(Parameter param | this.getNode() = param.asName() and exists(param.getDefault()))
|
||||
}
|
||||
|
||||
/** flow node corresponding to the value assigned for the definition corresponding to this flow node */
|
||||
ControlFlowNode getValue() {
|
||||
result = assigned_value(this.getNode()).getAFlowNode() and
|
||||
result.getNode() = assigned_value(this.getNode()) and
|
||||
(
|
||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||
or
|
||||
@@ -584,7 +584,7 @@ class DefinitionNode extends ControlFlowNode {
|
||||
// since the default value for a parameter is evaluated in the same basic block as
|
||||
// the function definition, but the parameter belongs to the basic block of the function,
|
||||
// there is no dominance relationship between the two.
|
||||
exists(Parameter param | this = param.asName().getAFlowNode())
|
||||
exists(Parameter param | this.getNode() = param.asName())
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -901,7 +901,7 @@ class ExceptFlowNode extends ControlFlowNode {
|
||||
exists(ExceptStmt ex |
|
||||
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
||||
ex = this.getNode() and
|
||||
result = ex.getType().getAFlowNode()
|
||||
result.getNode() = ex.getType()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -913,7 +913,7 @@ class ExceptFlowNode extends ControlFlowNode {
|
||||
exists(ExceptStmt ex |
|
||||
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
||||
ex = this.getNode() and
|
||||
result = ex.getName().getAFlowNode()
|
||||
result.getNode() = ex.getName()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -928,7 +928,7 @@ class ExceptGroupFlowNode extends ControlFlowNode {
|
||||
*/
|
||||
ControlFlowNode getType() {
|
||||
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
||||
result = this.getNode().(ExceptGroupStmt).getType().getAFlowNode()
|
||||
result.getNode() = this.getNode().(ExceptGroupStmt).getType()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -937,7 +937,7 @@ class ExceptGroupFlowNode extends ControlFlowNode {
|
||||
*/
|
||||
ControlFlowNode getName() {
|
||||
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
||||
result = this.getNode().(ExceptGroupStmt).getName().getAFlowNode()
|
||||
result.getNode() = this.getNode().(ExceptGroupStmt).getName()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -153,8 +153,16 @@ class Function extends Function_, Scope, AstNode {
|
||||
|
||||
override predicate contains(AstNode inner) { Scope.super.contains(inner) }
|
||||
|
||||
/** Gets a control flow node for a return value of this function */
|
||||
ControlFlowNode getAReturnValueFlowNode() {
|
||||
/**
|
||||
* DEPRECATED: bind a `Return` node explicitly instead, e.g.
|
||||
* `exists(Return ret | ret.getScope() = this and n.getNode() = ret.getValue())`.
|
||||
* This API is being phased out together with `AstNode.getAFlowNode()` to
|
||||
* untangle the AST and CFG hierarchies in preparation for migrating the
|
||||
* dataflow library off the legacy CFG.
|
||||
*
|
||||
* Gets a control flow node for a return value of this function.
|
||||
*/
|
||||
deprecated ControlFlowNode getAReturnValueFlowNode() {
|
||||
exists(Return ret |
|
||||
ret.getScope() = this and
|
||||
ret.getValue() = result.getNode()
|
||||
|
||||
@@ -162,8 +162,6 @@ class ImportMember extends ImportMember_ {
|
||||
string getImportedModuleName() {
|
||||
result = this.getModule().(ImportExpr).getImportedModuleName() + "." + this.getName()
|
||||
}
|
||||
|
||||
override ImportMemberNode getAFlowNode() { result = super.getAFlowNode() }
|
||||
}
|
||||
|
||||
/** An import statement */
|
||||
|
||||
@@ -46,20 +46,23 @@ class SelfAttributeRead extends SelfAttribute {
|
||||
}
|
||||
|
||||
predicate guardedByHasattr() {
|
||||
exists(Variable var, ControlFlowNode n |
|
||||
var.getAUse() = this.getObject().getAFlowNode() and
|
||||
exists(Variable var, ControlFlowNode n, ControlFlowNode this_, ControlFlowNode obj_ |
|
||||
this_.getNode() = this and obj_.getNode() = this.getObject()
|
||||
|
|
||||
var.getAUse() = obj_ and
|
||||
hasattr(n, var.getAUse(), this.getName()) and
|
||||
n.strictlyDominates(this.getAFlowNode())
|
||||
n.strictlyDominates(this_)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
predicate locallyDefined() {
|
||||
exists(SelfAttributeStore store |
|
||||
this.getName() = store.getName() and
|
||||
this.getScope() = store.getScope()
|
||||
exists(SelfAttributeStore store, ControlFlowNode store_, ControlFlowNode this_ |
|
||||
store_.getNode() = store and this_.getNode() = this
|
||||
|
|
||||
store.getAFlowNode().strictlyDominates(this.getAFlowNode())
|
||||
this.getName() = store.getName() and
|
||||
this.getScope() = store.getScope() and
|
||||
store_.strictlyDominates(this_)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,24 +5,30 @@ private import semmle.python.dataflow.new.DataFlow
|
||||
|
||||
private predicate constCompare(DataFlow::GuardNode g, ControlFlowNode node, boolean branch) {
|
||||
exists(CompareNode cn | cn = g |
|
||||
exists(ImmutableLiteral const, Cmpop op |
|
||||
op = any(Eq eq) and branch = true
|
||||
or
|
||||
op = any(NotEq ne) and branch = false
|
||||
exists(ImmutableLiteral const, Cmpop op, ControlFlowNode c |
|
||||
c.getNode() = const and
|
||||
(
|
||||
op = any(Eq eq) and branch = true
|
||||
or
|
||||
op = any(NotEq ne) and branch = false
|
||||
)
|
||||
|
|
||||
cn.operands(const.getAFlowNode(), op, node)
|
||||
cn.operands(c, op, node)
|
||||
or
|
||||
cn.operands(node, op, const.getAFlowNode())
|
||||
cn.operands(node, op, c)
|
||||
)
|
||||
or
|
||||
exists(NameConstant const, Cmpop op |
|
||||
op = any(Is is_) and branch = true
|
||||
or
|
||||
op = any(IsNot isn) and branch = false
|
||||
exists(NameConstant const, Cmpop op, ControlFlowNode c |
|
||||
c.getNode() = const and
|
||||
(
|
||||
op = any(Is is_) and branch = true
|
||||
or
|
||||
op = any(IsNot isn) and branch = false
|
||||
)
|
||||
|
|
||||
cn.operands(const.getAFlowNode(), op, node)
|
||||
cn.operands(c, op, node)
|
||||
or
|
||||
cn.operands(node, op, const.getAFlowNode())
|
||||
cn.operands(node, op, c)
|
||||
)
|
||||
or
|
||||
exists(IterableNode const_iterable, Cmpop op |
|
||||
|
||||
@@ -228,7 +228,7 @@ private class ClassDefinitionAsAttrWrite extends AttrWrite, CfgNode {
|
||||
|
||||
override Node getValue() { result.asCfgNode() = node.getValue() }
|
||||
|
||||
override Node getObject() { result.asCfgNode() = cls.getAFlowNode() }
|
||||
override Node getObject() { result.asCfgNode().getNode() = cls }
|
||||
|
||||
override ExprNode getAttributeNameExpr() { none() }
|
||||
|
||||
|
||||
@@ -1913,8 +1913,8 @@ abstract class ReturnNode extends Node {
|
||||
class ExtractedReturnNode extends ReturnNode, CfgNode {
|
||||
// See `TaintTrackingImplementation::returnFlowStep`
|
||||
ExtractedReturnNode() {
|
||||
node = any(Return ret).getValue().getAFlowNode() or
|
||||
node = any(Yield yield).getAFlowNode()
|
||||
node.getNode() = any(Return ret).getValue() or
|
||||
node.getNode() = any(Yield yield)
|
||||
}
|
||||
|
||||
override ReturnKind getKind() { any() }
|
||||
@@ -1932,7 +1932,7 @@ class ExtractedReturnNode extends ReturnNode, CfgNode {
|
||||
class YieldNodeInContextManagerFunction extends ReturnNode, CfgNode {
|
||||
YieldNodeInContextManagerFunction() {
|
||||
hasContextmanagerDecorator(node.getScope()) and
|
||||
node = any(Yield yield).getValue().getAFlowNode()
|
||||
node.getNode() = any(Yield yield).getValue()
|
||||
}
|
||||
|
||||
override ReturnKind getKind() { any() }
|
||||
|
||||
@@ -185,8 +185,8 @@ private predicate synthDictSplatArgumentNodeStoreStep(
|
||||
*/
|
||||
predicate yieldStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(Yield yield |
|
||||
nodeTo.asCfgNode() = yield.getAFlowNode() and
|
||||
nodeFrom.asCfgNode() = yield.getValue().getAFlowNode() and
|
||||
nodeTo.asCfgNode().getNode() = yield and
|
||||
nodeFrom.asCfgNode().getNode() = yield.getValue() and
|
||||
// TODO: Consider if this will also need to transfer dictionary content
|
||||
// once dictionary comprehensions are supported.
|
||||
c instanceof ListElementContent
|
||||
@@ -753,7 +753,7 @@ predicate jumpStepNotSharedWithTypeTracker(Node nodeFrom, Node nodeTo) {
|
||||
* As of 2024-04-02 the type-tracking library only supports precise content, so there is
|
||||
* no reason to include steps for list content right now.
|
||||
*/
|
||||
predicate storeStepCommon(Node nodeFrom, Content c, Node nodeTo) {
|
||||
predicate storeStepCommon(Node nodeFrom, ContentSet c, Node nodeTo) {
|
||||
tupleStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
dictStoreStep(nodeFrom, c, nodeTo)
|
||||
@@ -767,31 +767,29 @@ predicate storeStepCommon(Node nodeFrom, Content c, Node nodeTo) {
|
||||
* Holds if data can flow from `nodeFrom` to `nodeTo` via an assignment to
|
||||
* content `c`.
|
||||
*/
|
||||
predicate storeStep(Node nodeFrom, ContentSet cs, Node nodeTo) {
|
||||
exists(Content c | cs = singleton(c) |
|
||||
storeStepCommon(nodeFrom, c, nodeTo)
|
||||
or
|
||||
listStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
setStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
attributeStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
matchStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
any(Orm::AdditionalOrmSteps es).storeStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
synthStarArgsElementParameterNodeStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
synthDictSplatArgumentNodeStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
yieldStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
VariableCapture::storeStep(nodeFrom, c, nodeTo)
|
||||
)
|
||||
predicate storeStep(Node nodeFrom, ContentSet c, Node nodeTo) {
|
||||
storeStepCommon(nodeFrom, c, nodeTo)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryStoreStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), cs,
|
||||
listStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
setStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
attributeStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
matchStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
any(Orm::AdditionalOrmSteps es).storeStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryStoreStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), c,
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode())
|
||||
or
|
||||
synthStarArgsElementParameterNodeStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
synthDictSplatArgumentNodeStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
yieldStoreStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
VariableCapture::storeStep(nodeFrom, c, nodeTo)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -987,7 +985,7 @@ predicate attributeStoreStep(Node nodeFrom, AttributeContent c, Node nodeTo) {
|
||||
/**
|
||||
* Subset of `readStep` that should be shared with type-tracking.
|
||||
*/
|
||||
predicate readStepCommon(Node nodeFrom, Content c, Node nodeTo) {
|
||||
predicate readStepCommon(Node nodeFrom, ContentSet c, Node nodeTo) {
|
||||
subscriptReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
iterableUnpackingReadStep(nodeFrom, c, nodeTo)
|
||||
@@ -996,25 +994,21 @@ predicate readStepCommon(Node nodeFrom, Content c, Node nodeTo) {
|
||||
/**
|
||||
* Holds if data can flow from `nodeFrom` to `nodeTo` via a read of content `c`.
|
||||
*/
|
||||
predicate readStep(Node nodeFrom, ContentSet cs, Node nodeTo) {
|
||||
exists(Content c | cs = singleton(c) |
|
||||
readStepCommon(nodeFrom, c, nodeTo)
|
||||
or
|
||||
matchReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
forReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
attributeReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
synthDictSplatParameterNodeReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
VariableCapture::readStep(nodeFrom, c, nodeTo)
|
||||
)
|
||||
predicate readStep(Node nodeFrom, ContentSet c, Node nodeTo) {
|
||||
readStepCommon(nodeFrom, c, nodeTo)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryReadStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), cs,
|
||||
matchReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
forReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
attributeReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryReadStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), c,
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode())
|
||||
or
|
||||
Conversions::readStep(nodeFrom, cs, nodeTo)
|
||||
synthDictSplatParameterNodeReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
VariableCapture::readStep(nodeFrom, c, nodeTo)
|
||||
}
|
||||
|
||||
/** Data flows from a sequence to a subscript of the sequence. */
|
||||
@@ -1070,68 +1064,23 @@ predicate attributeReadStep(Node nodeFrom, AttributeContent c, AttrRead nodeTo)
|
||||
nodeTo.accesses(nodeFrom, c.getAttribute())
|
||||
}
|
||||
|
||||
module Conversions {
|
||||
private import semmle.python.Concepts
|
||||
|
||||
predicate decoderReadStep(Node nodeFrom, ContentSet c, Node nodeTo) {
|
||||
exists(Decoding decoding |
|
||||
nodeFrom = decoding.getAnInput() and
|
||||
nodeTo = decoding.getOutput()
|
||||
) and
|
||||
c.isAnyTupleOrDictionaryElement()
|
||||
}
|
||||
|
||||
predicate encoderReadStep(Node nodeFrom, ContentSet c, Node nodeTo) {
|
||||
exists(Encoding encoding |
|
||||
nodeFrom = encoding.getAnInput() and
|
||||
nodeTo = encoding.getOutput()
|
||||
) and
|
||||
c.isAnyTupleOrDictionaryElement()
|
||||
}
|
||||
|
||||
predicate formatReadStep(Node nodeFrom, ContentSet c, Node nodeTo) {
|
||||
// % formatting
|
||||
exists(BinaryExprNode fmt | fmt = nodeTo.asCfgNode() |
|
||||
fmt.getOp() instanceof Mod and
|
||||
fmt.getRight() = nodeFrom.asCfgNode()
|
||||
) and
|
||||
c.isAnyTupleElement()
|
||||
or
|
||||
// format_map
|
||||
// see https://docs.python.org/3/library/stdtypes.html#str.format_map
|
||||
nodeTo.(MethodCallNode).calls(_, "format_map") and
|
||||
nodeTo.(MethodCallNode).getArg(0) = nodeFrom and
|
||||
c.isAnyDictionaryElement()
|
||||
}
|
||||
|
||||
predicate readStep(Node nodeFrom, ContentSet c, Node nodeTo) {
|
||||
decoderReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
encoderReadStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
formatReadStep(nodeFrom, c, nodeTo)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if values stored inside content `c` are cleared at node `n`. For example,
|
||||
* any value stored inside `f` is cleared at the pre-update node associated with `x`
|
||||
* in `x.f = newValue`.
|
||||
*/
|
||||
predicate clearsContent(Node n, ContentSet cs) {
|
||||
exists(Content c | cs = singleton(c) |
|
||||
matchClearStep(n, c)
|
||||
or
|
||||
attributeClearStep(n, c)
|
||||
or
|
||||
dictClearStep(n, c)
|
||||
or
|
||||
dictSplatParameterNodeClearStep(n, c)
|
||||
or
|
||||
VariableCapture::clearsContent(n, c)
|
||||
)
|
||||
predicate clearsContent(Node n, ContentSet c) {
|
||||
matchClearStep(n, c)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(FlowSummaryNode).getSummaryNode(), cs)
|
||||
attributeClearStep(n, c)
|
||||
or
|
||||
dictClearStep(n, c)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(FlowSummaryNode).getSummaryNode(), c)
|
||||
or
|
||||
dictSplatParameterNodeClearStep(n, c)
|
||||
or
|
||||
VariableCapture::clearsContent(n, c)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1249,65 +1198,12 @@ predicate allowParameterReturnInSelf(ParameterNode p) {
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[s]
|
||||
private string getFirstChar(string s) {
|
||||
result =
|
||||
min(int i, string c |
|
||||
c = s.charAt(i) and c != "_"
|
||||
or
|
||||
c = "" and i = s.length()
|
||||
|
|
||||
c order by i
|
||||
)
|
||||
}
|
||||
|
||||
private string getAttributeContentFirstChar(AttributeContent ac) {
|
||||
result = getFirstChar(ac.getAttribute())
|
||||
}
|
||||
|
||||
private string getDictionaryElementContentKeyFirstChar(DictionaryElementContent dec) {
|
||||
result = getFirstChar(dec.getKey())
|
||||
}
|
||||
|
||||
private newtype TContentApprox =
|
||||
TListElementContentApprox() or
|
||||
TSetElementContentApprox() or
|
||||
TTupleElementContentApprox() or
|
||||
TDictionaryElementContentApprox(string first) {
|
||||
first = "" // for `TDictionaryElementAnyContent`
|
||||
or
|
||||
first = getDictionaryElementContentKeyFirstChar(_)
|
||||
} or
|
||||
TAttributeContentApprox(string first) { first = getAttributeContentFirstChar(_) } or
|
||||
TCapturedVariableContentApprox()
|
||||
|
||||
/** An approximated `Content`. */
|
||||
class ContentApprox extends TContentApprox {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "" }
|
||||
}
|
||||
class ContentApprox = Unit;
|
||||
|
||||
/** Gets an approximated value for content `c`. */
|
||||
ContentApprox getContentApprox(Content c) {
|
||||
c = TListElementContent() and
|
||||
result = TListElementContentApprox()
|
||||
or
|
||||
c = TSetElementContent() and
|
||||
result = TSetElementContentApprox()
|
||||
or
|
||||
c = TTupleElementContent(_) and
|
||||
result = TTupleElementContentApprox()
|
||||
or
|
||||
result = TDictionaryElementContentApprox(getDictionaryElementContentKeyFirstChar(c))
|
||||
or
|
||||
c = TDictionaryElementAnyContent() and
|
||||
result = TDictionaryElementContentApprox("")
|
||||
or
|
||||
result = TAttributeContentApprox(getAttributeContentFirstChar(c))
|
||||
or
|
||||
c = TCapturedVariableContent(_) and
|
||||
result = TCapturedVariableContentApprox()
|
||||
}
|
||||
pragma[inline]
|
||||
ContentApprox getContentApprox(Content c) { any() }
|
||||
|
||||
/** Helper for `.getEnclosingCallable`. */
|
||||
DataFlowCallable getCallableScope(Scope s) {
|
||||
|
||||
@@ -485,7 +485,7 @@ class ModuleVariableNode extends Node, TModuleVariableNode {
|
||||
|
||||
/** Gets a node that reads this variable, excluding reads that happen through `from ... import *`. */
|
||||
Node getALocalRead() {
|
||||
result.asCfgNode() = var.getALoad().getAFlowNode() and
|
||||
result.asCfgNode().getNode() = var.getALoad() and
|
||||
not result.getScope() = mod
|
||||
}
|
||||
|
||||
@@ -898,78 +898,19 @@ class CapturedVariableContent extends Content, TCapturedVariableContent {
|
||||
override string getMaDRepresentation() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An entity that represents a set of `Content`s.
|
||||
*
|
||||
* Most `ContentSet`s are singletons (i.e. they consist of a single `Content`),
|
||||
* but `AnyDictionaryElement` and `AnyTupleElement` act as wildcards on the
|
||||
* read side: a read at such a `ContentSet` matches any specific dictionary
|
||||
* key / tuple index store, as well as (for dictionaries) the
|
||||
* "unknown-bucket" Content `DictionaryElementAnyContent`.
|
||||
*
|
||||
* Keeping these as wildcard `ContentSet`s (rather than enumerating one
|
||||
* `ContentSet` per key/index) keeps the dataflow `readSetEx` relation small
|
||||
* when implicit reads are used (e.g. at sinks via `defaultImplicitTaintRead`).
|
||||
*/
|
||||
private newtype TContentSet =
|
||||
TSingletonContent(Content c) or
|
||||
TAnyTupleElement() or
|
||||
TAnyDictionaryElement() or
|
||||
TAnyTupleOrDictionaryElement()
|
||||
|
||||
/**
|
||||
* An entity that represents a set of `Content`s.
|
||||
*
|
||||
* The set may be interpreted differently depending on whether it is
|
||||
* stored into (`getAStoreContent`) or read from (`getAReadContent`).
|
||||
*/
|
||||
class ContentSet extends TContentSet {
|
||||
/** Holds if this content set is the singleton `{c}`. */
|
||||
predicate isSingleton(Content c) { this = TSingletonContent(c) }
|
||||
|
||||
/** Holds if this content set is the wildcard for all tuple elements. */
|
||||
predicate isAnyTupleElement() { this = TAnyTupleElement() }
|
||||
|
||||
/** Holds if this content set is the wildcard for all dictionary elements. */
|
||||
predicate isAnyDictionaryElement() { this = TAnyDictionaryElement() }
|
||||
|
||||
/** Holds if this content set is the wildcard for all tuple elements or dictionary elements. */
|
||||
predicate isAnyTupleOrDictionaryElement() { this = TAnyTupleOrDictionaryElement() }
|
||||
|
||||
class ContentSet instanceof Content {
|
||||
/** Gets a content that may be stored into when storing into this set. */
|
||||
Content getAStoreContent() { this = TSingletonContent(result) }
|
||||
Content getAStoreContent() { result = this }
|
||||
|
||||
/** Gets a content that may be read from when reading from this set. */
|
||||
Content getAReadContent() {
|
||||
this = TSingletonContent(result)
|
||||
or
|
||||
// Wildcard expansion: a read at "any tuple element" matches a store at any
|
||||
// specific tuple index. (Stores always target a specific index, so we don't
|
||||
// need a `TupleElementAnyContent` Content kind here.)
|
||||
this = TAnyTupleElement() and result instanceof TupleElementContent
|
||||
or
|
||||
this = TAnyDictionaryElement() and
|
||||
(result instanceof DictionaryElementContent or result instanceof DictionaryElementAnyContent)
|
||||
or
|
||||
this = TAnyTupleOrDictionaryElement() and
|
||||
(
|
||||
result instanceof TupleElementContent or
|
||||
result instanceof DictionaryElementContent or
|
||||
result instanceof DictionaryElementAnyContent
|
||||
)
|
||||
}
|
||||
Content getAReadContent() { result = this }
|
||||
|
||||
/** Gets a textual representation of this content set. */
|
||||
string toString() {
|
||||
exists(Content c | this = TSingletonContent(c) | result = c.toString())
|
||||
or
|
||||
this = TAnyTupleElement() and result = "Any tuple element"
|
||||
or
|
||||
this = TAnyDictionaryElement() and result = "Any dictionary element"
|
||||
or
|
||||
this = TAnyTupleOrDictionaryElement() and result = "Any tuple or dictionary element"
|
||||
}
|
||||
string toString() { result = super.toString() }
|
||||
}
|
||||
|
||||
/** Gets the singleton `ContentSet` wrapping the `Content` `c`. */
|
||||
ContentSet singleton(Content c) { result = TSingletonContent(c) }
|
||||
|
||||
@@ -66,29 +66,21 @@ module Input implements InputSig<Location, DataFlowImplSpecific::PythonDataFlow>
|
||||
}
|
||||
|
||||
string encodeContent(ContentSet cs, string arg) {
|
||||
exists(Content c | cs.isSingleton(c) |
|
||||
c = TListElementContent() and result = "ListElement" and arg = ""
|
||||
or
|
||||
c = TSetElementContent() and result = "SetElement" and arg = ""
|
||||
or
|
||||
exists(int index |
|
||||
c = TTupleElementContent(index) and result = "TupleElement" and arg = index.toString()
|
||||
)
|
||||
or
|
||||
exists(string key |
|
||||
c = TDictionaryElementContent(key) and result = "DictionaryElement" and arg = key
|
||||
)
|
||||
or
|
||||
c = TDictionaryElementAnyContent() and result = "DictionaryElementAny" and arg = ""
|
||||
or
|
||||
exists(string attr | c = TAttributeContent(attr) and result = "Attribute" and arg = attr)
|
||||
cs = TListElementContent() and result = "ListElement" and arg = ""
|
||||
or
|
||||
cs = TSetElementContent() and result = "SetElement" and arg = ""
|
||||
or
|
||||
exists(int index |
|
||||
cs = TTupleElementContent(index) and result = "TupleElement" and arg = index.toString()
|
||||
)
|
||||
or
|
||||
cs.isAnyTupleElement() and result = "AnyTupleElement" and arg = ""
|
||||
exists(string key |
|
||||
cs = TDictionaryElementContent(key) and result = "DictionaryElement" and arg = key
|
||||
)
|
||||
or
|
||||
cs.isAnyDictionaryElement() and result = "AnyDictionaryElement" and arg = ""
|
||||
cs = TDictionaryElementAnyContent() and result = "DictionaryElementAny" and arg = ""
|
||||
or
|
||||
cs.isAnyTupleOrDictionaryElement() and result = "AnyTupleOrDictionaryElement" and arg = ""
|
||||
exists(string attr | cs = TAttributeContent(attr) and result = "Attribute" and arg = attr)
|
||||
}
|
||||
|
||||
bindingset[token]
|
||||
@@ -147,29 +139,27 @@ module Private {
|
||||
predicate withContent = SC::withContent/1;
|
||||
|
||||
/** Gets a summary component that represents a list element. */
|
||||
SummaryComponent listElement() { result = content(singleton(any(ListElementContent c))) }
|
||||
SummaryComponent listElement() { result = content(any(ListElementContent c)) }
|
||||
|
||||
/** Gets a summary component that represents a set element. */
|
||||
SummaryComponent setElement() { result = content(singleton(any(SetElementContent c))) }
|
||||
SummaryComponent setElement() { result = content(any(SetElementContent c)) }
|
||||
|
||||
/** Gets a summary component that represents a tuple element. */
|
||||
SummaryComponent tupleElement(int index) {
|
||||
exists(TupleElementContent c | c.getIndex() = index and result = content(singleton(c)))
|
||||
exists(TupleElementContent c | c.getIndex() = index and result = content(c))
|
||||
}
|
||||
|
||||
/** Gets a summary component that represents a dictionary element. */
|
||||
SummaryComponent dictionaryElement(string key) {
|
||||
exists(DictionaryElementContent c | c.getKey() = key and result = content(singleton(c)))
|
||||
exists(DictionaryElementContent c | c.getKey() = key and result = content(c))
|
||||
}
|
||||
|
||||
/** Gets a summary component that represents a dictionary element at any key. */
|
||||
SummaryComponent dictionaryElementAny() {
|
||||
result = content(singleton(any(DictionaryElementAnyContent c)))
|
||||
}
|
||||
SummaryComponent dictionaryElementAny() { result = content(any(DictionaryElementAnyContent c)) }
|
||||
|
||||
/** Gets a summary component that represents an attribute element. */
|
||||
SummaryComponent attribute(string attr) {
|
||||
exists(AttributeContent c | c.getAttribute() = attr and result = content(singleton(c)))
|
||||
exists(AttributeContent c | c.getAttribute() = attr and result = content(c))
|
||||
}
|
||||
|
||||
/** Gets a summary component that represents the return value of a call. */
|
||||
|
||||
@@ -9,7 +9,19 @@ private import semmle.python.dataflow.new.DataFlow
|
||||
private import semmle.python.dataflow.new.internal.ImportStar
|
||||
private import semmle.python.dataflow.new.TypeTracking
|
||||
private import semmle.python.dataflow.new.internal.DataFlowPrivate
|
||||
private import semmle.python.essa.SsaDefinitions
|
||||
|
||||
/**
|
||||
* Holds if `init` is a package's `__init__.py` and `var` is a global variable in
|
||||
* `init` whose name matches a submodule of the package.
|
||||
*
|
||||
* Inlined from `SsaSource::init_module_submodule_defn` to avoid pulling
|
||||
* `semmle.python.essa.SsaDefinitions` into the new dataflow stack.
|
||||
*/
|
||||
private predicate initModuleSubmoduleDefn(GlobalVariable var, Module init) {
|
||||
init.isPackageInit() and
|
||||
exists(init.getPackage().getSubModule(var.getId())) and
|
||||
var.getScope() = init
|
||||
}
|
||||
|
||||
/**
|
||||
* Python modules and the way imports are resolved are... complicated. Here's a crash course in how
|
||||
@@ -326,7 +338,7 @@ module ImportResolution {
|
||||
// imported yet.
|
||||
exists(string submodule, Module package, EssaVariable var |
|
||||
submodule = var.getName() and
|
||||
SsaSource::init_module_submodule_defn(var.getSourceVariable(), package.getEntryNode()) and
|
||||
initModuleSubmoduleDefn(var.getSourceVariable(), package) and
|
||||
m = getModuleFromName(package.getPackageName() + "." + submodule) and
|
||||
result.asCfgNode() = var.getDefinition().(EssaNodeDefinition).getDefiningNode()
|
||||
)
|
||||
|
||||
@@ -11,34 +11,12 @@ private import semmle.python.ApiGraphs
|
||||
*/
|
||||
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if default taint tracking should read content `contentSet` implicitly and
|
||||
* propagate taint from a container to reads of that content.
|
||||
*/
|
||||
private predicate defaultTaintReadContent(DataFlow::ContentSet contentSet) {
|
||||
// Tuple and dictionary content is precise, so use wildcard content sets to avoid
|
||||
// blowing up the size of `Stage1::readSetEx` (otherwise this predicate would
|
||||
// expand to one row per (node, distinct key or index) and the framework's
|
||||
// read-set relation grows quadratically). `ContentSet.getAReadContent` expands
|
||||
// these wildcards back to the specific contents when matching against stores.
|
||||
contentSet.isAnyTupleOrDictionaryElement()
|
||||
or
|
||||
// List and set element content is already imprecise, so no wildcard expansion is
|
||||
// needed.
|
||||
contentSet.getAStoreContent() instanceof DataFlow::ListElementContent
|
||||
or
|
||||
contentSet.getAStoreContent() instanceof DataFlow::SetElementContent
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if default `TaintTracking::Configuration`s should allow implicit reads
|
||||
* of `c` at sinks and inputs to additional taint steps.
|
||||
*/
|
||||
bindingset[node]
|
||||
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) {
|
||||
exists(node) and
|
||||
defaultTaintReadContent(c)
|
||||
}
|
||||
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) { none() }
|
||||
|
||||
private module Cached {
|
||||
/**
|
||||
@@ -150,6 +128,11 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT
|
||||
nodeFrom.getNode() = object and
|
||||
method_name in ["partition", "rpartition", "rsplit", "split", "splitlines"]
|
||||
or
|
||||
// Iterable[str] -> str
|
||||
// TODO: check if these should be handled differently in regards to content
|
||||
method_name = "join" and
|
||||
nodeFrom.getNode() = call.getArg(0)
|
||||
or
|
||||
// Mapping[str, Any] -> str
|
||||
method_name = "format_map" and
|
||||
nodeFrom.getNode() = call.getArg(0)
|
||||
@@ -178,21 +161,32 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint can flow from `nodeFrom` to `nodeTo` with a step related to reading
|
||||
* content from containers (lists/sets/dictionaries/tuples): subscripts, iteration,
|
||||
* constructor invocation, methods.
|
||||
* Holds if taint can flow from `nodeFrom` to `nodeTo` with a step related to containers
|
||||
* (lists/sets/dictionaries): literals, constructor invocation, methods. Note that this
|
||||
* is currently very imprecise, as an example, since we model `dict.get`, we treat any
|
||||
* `<tainted object>.get(<arg>)` will be tainted, whether it's true or not.
|
||||
*/
|
||||
predicate containerStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
exists(DataFlow::ContentSet contentSet |
|
||||
DataFlowPrivate::readStep(nodeFrom, contentSet, nodeTo) and
|
||||
exists(DataFlow::Content c | c = contentSet.getAReadContent() |
|
||||
c instanceof DataFlow::TupleElementContent or
|
||||
c instanceof DataFlow::DictionaryElementContent or
|
||||
c instanceof DataFlow::DictionaryElementAnyContent or
|
||||
c instanceof DataFlow::ListElementContent or
|
||||
c instanceof DataFlow::SetElementContent
|
||||
)
|
||||
)
|
||||
// construction by literal
|
||||
//
|
||||
// TODO: once we have proper flow-summary modeling, we might not need this step any
|
||||
// longer -- but there needs to be a matching read-step for the store-step, and we
|
||||
// don't provide that right now.
|
||||
DataFlowPrivate::listStoreStep(nodeFrom, _, nodeTo)
|
||||
or
|
||||
DataFlowPrivate::setStoreStep(nodeFrom, _, nodeTo)
|
||||
or
|
||||
DataFlowPrivate::tupleStoreStep(nodeFrom, _, nodeTo)
|
||||
or
|
||||
DataFlowPrivate::dictStoreStep(nodeFrom, _, nodeTo)
|
||||
or
|
||||
// comprehension, so there is taint-flow from `x` in `[x for x in xs]` to the
|
||||
// resulting list of the list-comprehension.
|
||||
//
|
||||
// TODO: once we have proper flow-summary modeling, we might not need this step any
|
||||
// longer -- but there needs to be a matching read-step for the store-step, and we
|
||||
// don't provide that right now.
|
||||
DataFlowPrivate::yieldStoreStep(nodeFrom, _, nodeTo)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -94,8 +94,10 @@ private module SummaryTypeTrackerInput implements SummaryTypeTracker::Input {
|
||||
Node returnOf(Node callable, SummaryComponent return) {
|
||||
return = FlowSummaryImpl::Private::SummaryComponent::return() and
|
||||
// `result` should be the return value of a callable expression (lambda or function) referenced by `callable`
|
||||
result.asCfgNode() =
|
||||
callable.getALocalSource().asExpr().(CallableExpr).getInnerScope().getAReturnValueFlowNode()
|
||||
exists(Return ret |
|
||||
ret.getScope() = callable.getALocalSource().asExpr().(CallableExpr).getInnerScope() and
|
||||
result.asCfgNode().getNode() = ret.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
// Relating callables to nodes
|
||||
@@ -241,7 +243,7 @@ module TypeTrackingInput implements Shared::TypeTrackingInput<Location> {
|
||||
// is only fed set/list content)
|
||||
not nodeFrom instanceof DataFlowPublic::IterableElementNode
|
||||
or
|
||||
TypeTrackerSummaryFlow::basicStoreStep(nodeFrom, nodeTo, DataFlowPublic::singleton(content))
|
||||
TypeTrackerSummaryFlow::basicStoreStep(nodeFrom, nodeTo, content)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,15 +274,14 @@ module TypeTrackingInput implements Shared::TypeTrackingInput<Location> {
|
||||
nodeFrom.asCfgNode() instanceof SequenceNode
|
||||
)
|
||||
or
|
||||
TypeTrackerSummaryFlow::basicLoadStep(nodeFrom, nodeTo, DataFlowPublic::singleton(content))
|
||||
TypeTrackerSummaryFlow::basicLoadStep(nodeFrom, nodeTo, content)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the `loadContent` of `nodeFrom` is stored in the `storeContent` of `nodeTo`.
|
||||
*/
|
||||
predicate loadStoreStep(Node nodeFrom, Node nodeTo, Content loadContent, Content storeContent) {
|
||||
TypeTrackerSummaryFlow::basicLoadStoreStep(nodeFrom, nodeTo,
|
||||
DataFlowPublic::singleton(loadContent), DataFlowPublic::singleton(storeContent))
|
||||
TypeTrackerSummaryFlow::basicLoadStoreStep(nodeFrom, nodeTo, loadContent, storeContent)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,7 +61,7 @@ private module CaptureInput implements Shared::InputSig<Location, Cfg::BasicBloc
|
||||
class VariableWrite extends ControlFlowNode {
|
||||
CapturedVariable v;
|
||||
|
||||
VariableWrite() { this = v.getAStore().getAFlowNode().(DefinitionNode).getValue() }
|
||||
VariableWrite() { exists(DefinitionNode d | d.getNode() = v.getAStore() | this = d.getValue()) }
|
||||
|
||||
CapturedVariable getVariable() { result = v }
|
||||
|
||||
@@ -71,7 +71,7 @@ private module CaptureInput implements Shared::InputSig<Location, Cfg::BasicBloc
|
||||
class VariableRead extends Expr {
|
||||
CapturedVariable v;
|
||||
|
||||
VariableRead() { this = v.getALoad().getAFlowNode() }
|
||||
VariableRead() { this.getNode() = v.getALoad() }
|
||||
|
||||
CapturedVariable getVariable() { result = v }
|
||||
}
|
||||
|
||||
@@ -448,8 +448,7 @@ class TaintTrackingImplementation extends string instanceof TaintTracking::Confi
|
||||
context = TNoParam() and
|
||||
src = TTaintTrackingNode_(retval, TNoParam(), path, kind, this) and
|
||||
node.asCfgNode() = call and
|
||||
retval.asCfgNode() =
|
||||
any(Return ret | ret.getScope() = pyfunc.getScope()).getValue().getAFlowNode()
|
||||
retval.asCfgNode().getNode() = any(Return ret | ret.getScope() = pyfunc.getScope()).getValue()
|
||||
) and
|
||||
edgeLabel = "return"
|
||||
}
|
||||
@@ -471,8 +470,7 @@ class TaintTrackingImplementation extends string instanceof TaintTracking::Confi
|
||||
this.callContexts(call, src, pyfunc, context, callee) and
|
||||
retnode = TTaintTrackingNode_(retval, callee, path, kind, this) and
|
||||
node.asCfgNode() = call and
|
||||
retval.asCfgNode() =
|
||||
any(Return ret | ret.getScope() = pyfunc.getScope()).getValue().getAFlowNode()
|
||||
retval.asCfgNode().getNode() = any(Return ret | ret.getScope() = pyfunc.getScope()).getValue()
|
||||
) and
|
||||
edgeLabel = "call"
|
||||
}
|
||||
@@ -716,8 +714,10 @@ private class EssaTaintTracking extends string instanceof TaintTracking::Configu
|
||||
src = TTaintTrackingNode_(srcnode, context, path, srckind, this) and
|
||||
path.noAttribute()
|
||||
|
|
||||
assign.getValue().getAFlowNode() = srcnode.asCfgNode() and
|
||||
depth = iterable_unpacking_descent(assign.getATarget().getAFlowNode(), defn.getDefiningNode()) and
|
||||
srcnode.asCfgNode().getNode() = assign.getValue() and
|
||||
exists(SequenceNode left_parent | left_parent.getNode() = assign.getATarget() |
|
||||
depth = iterable_unpacking_descent(left_parent, defn.getDefiningNode())
|
||||
) and
|
||||
kind = taint_at_depth(srckind, depth)
|
||||
)
|
||||
}
|
||||
@@ -964,7 +964,7 @@ private TaintKind taint_at_depth(SequenceKind parent_kind, int depth) {
|
||||
* - with `left_defn` = `*y`, `left_parent` = `((x, *y), ...)`, result = 1
|
||||
*/
|
||||
int iterable_unpacking_descent(SequenceNode left_parent, ControlFlowNode left_defn) {
|
||||
exists(Assign a | a.getATarget().getASubExpression*().getAFlowNode() = left_parent) and
|
||||
exists(Assign a | left_parent.getNode() = a.getATarget().getASubExpression*()) and
|
||||
left_parent.getAnElement() = left_defn and
|
||||
// Handle `a, *b = some_iterable`
|
||||
if left_defn instanceof StarredNode then result = 0 else result = 1
|
||||
|
||||
@@ -56,7 +56,7 @@ module SsaSource {
|
||||
predicate with_definition(Variable v, ControlFlowNode defn) {
|
||||
exists(With with, Name var |
|
||||
with.getOptionalVars() = var and
|
||||
var.getAFlowNode() = defn
|
||||
defn.getNode() = var
|
||||
|
|
||||
var = v.getAStore()
|
||||
)
|
||||
@@ -67,7 +67,7 @@ module SsaSource {
|
||||
predicate pattern_capture_definition(Variable v, ControlFlowNode defn) {
|
||||
exists(MatchCapturePattern capture, Name var |
|
||||
capture.getVariable() = var and
|
||||
var.getAFlowNode() = defn
|
||||
defn.getNode() = var
|
||||
|
|
||||
var = v.getAStore()
|
||||
)
|
||||
@@ -78,7 +78,7 @@ module SsaSource {
|
||||
predicate pattern_alias_definition(Variable v, ControlFlowNode defn) {
|
||||
exists(MatchAsPattern pattern, Name var |
|
||||
pattern.getAlias() = var and
|
||||
var.getAFlowNode() = defn
|
||||
defn.getNode() = var
|
||||
|
|
||||
var = v.getAStore()
|
||||
)
|
||||
|
||||
@@ -59,7 +59,7 @@ module Bottle {
|
||||
|
||||
override Parameter getARoutedParameter() { none() }
|
||||
|
||||
override Function getARequestHandler() { result.getADecorator().getAFlowNode() = node }
|
||||
override Function getARequestHandler() { node.getNode() = result.getADecorator() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,10 @@ module Bottle {
|
||||
/** A response returned by a view callable. */
|
||||
class BottleReturnResponse extends Http::Server::HttpResponse::Range {
|
||||
BottleReturnResponse() {
|
||||
this.asCfgNode() = any(View::ViewCallable vc).getAReturnValueFlowNode()
|
||||
exists(Return ret |
|
||||
ret.getScope() = any(View::ViewCallable vc) and
|
||||
this.asCfgNode().getNode() = ret.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getBody() { result = this }
|
||||
|
||||
@@ -2872,7 +2872,10 @@ module PrivateDjango {
|
||||
DataFlow::CfgNode
|
||||
{
|
||||
DjangoRedirectViewGetRedirectUrlReturn() {
|
||||
node = any(GetRedirectUrlFunction f).getAReturnValueFlowNode()
|
||||
exists(Return ret |
|
||||
ret.getScope() = any(GetRedirectUrlFunction f) and
|
||||
node.getNode() = ret.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getRedirectLocation() { result = this }
|
||||
|
||||
@@ -129,7 +129,7 @@ module FastApi {
|
||||
result in [this.getArg(0), this.getArgByName("path")]
|
||||
}
|
||||
|
||||
override Function getARequestHandler() { result.getADecorator().getAFlowNode() = node }
|
||||
override Function getARequestHandler() { node.getNode() = result.getADecorator() }
|
||||
|
||||
override string getFramework() { result = "FastAPI" }
|
||||
|
||||
@@ -309,7 +309,10 @@ module FastApi {
|
||||
FastApiRouteSetup routeSetup;
|
||||
|
||||
FastApiRequestHandlerReturn() {
|
||||
node = routeSetup.getARequestHandler().getAReturnValueFlowNode()
|
||||
exists(Return ret |
|
||||
ret.getScope() = routeSetup.getARequestHandler() and
|
||||
node.getNode() = ret.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getBody() { result = this }
|
||||
|
||||
@@ -371,7 +371,7 @@ module Flask {
|
||||
result in [this.getArg(0), this.getArgByName("rule")]
|
||||
}
|
||||
|
||||
override Function getARequestHandler() { result.getADecorator().getAFlowNode() = node }
|
||||
override Function getARequestHandler() { node.getNode() = result.getADecorator() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -536,7 +536,7 @@ module Flask {
|
||||
FlaskRouteHandlerReturn() {
|
||||
exists(Function routeHandler |
|
||||
routeHandler = any(FlaskRouteSetup rs).getARequestHandler() and
|
||||
node = routeHandler.getAReturnValueFlowNode() and
|
||||
exists(Return ret | ret.getScope() = routeHandler and node.getNode() = ret.getValue()) and
|
||||
not this instanceof Flask::Response::InstanceSource
|
||||
)
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ private module FlaskAdmin {
|
||||
result in [this.getArg(0), this.getArgByName("url")]
|
||||
}
|
||||
|
||||
override Function getARequestHandler() { result.getADecorator().getAFlowNode() = node }
|
||||
override Function getARequestHandler() { node.getNode() = result.getADecorator() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,7 +71,7 @@ private module FlaskAdmin {
|
||||
|
||||
override Function getARequestHandler() {
|
||||
exists(Flask::FlaskViewClass cls |
|
||||
cls.getADecorator().getAFlowNode() = node and
|
||||
node.getNode() = cls.getADecorator() and
|
||||
result = cls.getARequestHandler()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -166,7 +166,10 @@ module Pyramid {
|
||||
/** A response returned by a view callable. */
|
||||
private class PyramidReturnResponse extends Http::Server::HttpResponse::Range {
|
||||
PyramidReturnResponse() {
|
||||
this.asCfgNode() = any(View::ViewCallable vc).getAReturnValueFlowNode() and
|
||||
exists(Return ret |
|
||||
ret.getScope() = any(View::ViewCallable vc) and
|
||||
this.asCfgNode().getNode() = ret.getValue()
|
||||
) and
|
||||
not this = instance()
|
||||
}
|
||||
|
||||
|
||||
@@ -2254,8 +2254,9 @@ module StdlibPrivate {
|
||||
DataFlow::CfgNode
|
||||
{
|
||||
WsgirefSimpleServerApplicationReturn() {
|
||||
exists(WsgirefSimpleServerApplication requestHandler |
|
||||
node = requestHandler.getAReturnValueFlowNode()
|
||||
exists(WsgirefSimpleServerApplication requestHandler, Return ret |
|
||||
ret.getScope() = requestHandler and
|
||||
node.getNode() = ret.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4244,7 +4245,6 @@ module StdlibPrivate {
|
||||
)
|
||||
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
||||
) and
|
||||
// Element content is mutated into list element content
|
||||
output = "ReturnValue.ListElement" and
|
||||
preservesValue = true
|
||||
or
|
||||
@@ -4271,9 +4271,11 @@ module StdlibPrivate {
|
||||
preservesValue = true
|
||||
)
|
||||
or
|
||||
input = "Argument[0].ListElement" and
|
||||
// TODO: We need to also translate iterable content such as list element
|
||||
// but we currently lack TupleElementAny
|
||||
input = "Argument[0]" and
|
||||
output = "ReturnValue" and
|
||||
preservesValue = true
|
||||
preservesValue = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4968,26 +4970,6 @@ module StdlibPrivate {
|
||||
}
|
||||
}
|
||||
|
||||
/** A flow summary for `str.join`. */
|
||||
class StrJoinSummary extends SummarizedCallable::Range {
|
||||
StrJoinSummary() { this = "str.join" }
|
||||
|
||||
override DataFlow::CallCfgNode getACall() { result.(DataFlow::MethodCallNode).calls(_, "join") }
|
||||
|
||||
override DataFlow::ArgumentNode getACallback() {
|
||||
result.(DataFlow::AttrRead).getAttributeName() = "join"
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
(
|
||||
// For code like `" ".join([name])`
|
||||
input = "Argument[0,iterable:].ListElement" and
|
||||
preservesValue = true
|
||||
) and
|
||||
output = "ReturnValue"
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// asyncio
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -182,7 +182,10 @@ private module Twisted {
|
||||
DataFlow::CfgNode
|
||||
{
|
||||
TwistedResourceRenderMethodReturn() {
|
||||
this.asCfgNode() = any(TwistedResourceRenderMethod meth).getAReturnValueFlowNode()
|
||||
exists(Return ret |
|
||||
ret.getScope() = any(TwistedResourceRenderMethod meth) and
|
||||
this.asCfgNode().getNode() = ret.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getBody() { result = this }
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user