Compare commits

..

140 Commits

Author SHA1 Message Date
Owen Mansel-Chan
7126b95b16 Add test with MISSING alerts 2026-06-11 07:22:17 +02:00
Asger F
b60bf8c79f Merge pull request #21950 from tonghuaroot/experimental-ssrf-ipv6-transition-js
Add experimental query: SSRF host guard missing IPv6-transition unwrap (CWE-918/CWE-1389)
2026-06-10 21:42:54 +02:00
tonghuaroot (童话)
4c1a0058bf Add SsrfIpv6TransitionIncompleteGuard.ql to not_included_in_qls.expected
Fix the JS integration test failure flagged in review by listing the new
experimental CWE-918 query in the expected not-included-in-qls suite, in
sorted order.
2026-06-10 08:42:42 +08:00
Tom Hvitved
f5919875b7 Merge pull request #21941 from hvitved/python/content-approx
Python: Implement `ContentApprox`
2026-06-09 15:46:04 +02:00
Owen Mansel-Chan
8d456df26f Merge pull request #21960 from github/dependabot/go_modules/go/extractor/extractor-dependencies-28a04969f3
Bump golang.org/x/mod from 0.36.0 to 0.37.0 in /go/extractor in the extractor-dependencies group
2026-06-09 05:30:45 +01:00
dependabot[bot]
72fcf27d1a Bump golang.org/x/mod
Bumps the extractor-dependencies group in /go/extractor with 1 update: [golang.org/x/mod](https://github.com/golang/mod).


Updates `golang.org/x/mod` from 0.36.0 to 0.37.0
- [Commits](https://github.com/golang/mod/compare/v0.36.0...v0.37.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-version: 0.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: extractor-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-09 03:03:37 +00:00
yoff
0cea01c22f Merge pull request #21926 from github/yoff/python-simplify-decorator-predicates
Python: simplify decorator-detection predicates to pure AST match
2026-06-08 22:04:33 +02:00
Anders Schack-Mulligen
a473565256 Merge pull request #21954 from aschackmull/cfg/consistency-child-idx
Cfg: Add consistency check for relevant child indices.
2026-06-08 14:44:20 +02:00
Anders Schack-Mulligen
c47135a40b Cfg: Add consistency check for relevant child indices. 2026-06-08 13:40:33 +02:00
Owen Mansel-Chan
3cbc8f0262 Merge pull request #21951 from github/workflow/go-version-update
Go: Update to 1.26.4
2026-06-08 11:47:47 +01:00
Tom Hvitved
cc1ea25856 Python: Implement ContentApprox 2026-06-08 08:41:28 +02:00
github-actions[bot]
5a38cbd5d5 Go: Update to 1.26.4 2026-06-08 04:30:10 +00:00
tonghuaroot
e93bc11f6f Add experimental JS query for SSRF guards missing IPv6-transition unwrap
Add javascript/ssrf-ipv6-transition-incomplete-guard, an experimental
@kind problem query that flags hand-rolled SSRF host guards which reject
private/loopback IPv4 ranges but never unwrap IPv6-transition forms
(IPv4-mapped ::ffff:, NAT64 64:ff9b::, 6to4 2002::). Such guards can be
bypassed by wrapping an internal IPv4 address in a transition literal.

Includes a .qhelp with good/bad examples, a change note, and a test pack
with two true-positive fixtures (private-ip package guard and a
hand-written RFC 1918 denylist) and two negative-control fixtures
(ipaddr.js range classifier and an explicit ::ffff: unwrap).

Signed-off-by: tonghuaroot <23011166+tonghuaroot@users.noreply.github.com>
2026-06-06 21:47:24 +08:00
Owen Mansel-Chan
cf6d94cf8a Merge pull request #21324 from github/copilot/automate-go-version-updates-again
Automate Go version updates via scheduled workflow
2026-06-06 03:03:03 +01:00
Owen Mansel-Chan
292fc8b777 Fix detection of failed text replacement
I checked and the comment seems to be correct.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-06 02:52:21 +01:00
Owen Mansel-Chan
a1759d9834 Use --force-with-lease for slightly improved safety
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-06 02:51:36 +01:00
Owen Mansel-Chan
6b74874372 Minor improvement to PR text 2026-06-06 02:32:43 +01:00
copilot-swe-agent[bot]
ef29d22c75 Update Go version workflow to include patch numbers in messages 2026-06-06 01:03:44 +00:00
Owen Mansel-Chan
1f91f915c7 Merge pull request #21888 from owen-mc/py/remove-imprecise-container-steps
Python: Remove imprecise container steps #2
2026-06-04 22:16:24 +01:00
Jon Janego
ba8eebe2b5 Merge pull request #21948 from github/codeql-spark-run-26974832191
Update changelog documentation site for codeql-cli-2.25.6
2026-06-04 14:55:17 -05:00
github-actions[bot]
dc1409e5f4 update codeql documentation 2026-06-04 19:36:45 +00:00
Mario Campos
284f42bb9e Merge pull request #21945 from github/codeql-spark-run-26947645690
Update changelog documentation site for codeql-cli-2.25.6
2026-06-04 13:09:04 -05:00
Henry Mercer
2f3524de74 Merge branch 'rc/3.22' into codeql-spark-run-26947645690 2026-06-04 16:01:11 +01:00
github-actions[bot]
b32573b060 update codeql documentation 2026-06-04 14:57:38 +00:00
Owen Mansel-Chan
cd2398aeea Merge pull request #21936 from github/workflow/coverage/update
Update CSV framework coverage reports
2026-06-04 12:45:21 +01:00
Sotiris Dragonas
d6892eaf0d Merge pull request #21900 from github/bazookamusic/range-analysis-bound-move-to-shared
Bound.qll - Replace utility for range analysis duplicate across java and cs with shared file
2026-06-04 12:45:11 +02:00
BazookaMusic
d2972cb53f Add back alias for module 2026-06-04 11:08:49 +02:00
github-actions[bot]
5576d30780 Add changed framework coverage reports 2026-06-04 01:04:50 +00:00
Owen Mansel-Chan
da999ee440 Address review comments 2026-06-03 21:24:16 +01:00
Tom Hvitved
3da195f50f Merge pull request #21918 from hvitved/rust/expose-resolution
Rust: Add `Impl::getSelf()` and `Impl::getTrait()`
2026-06-03 20:18:05 +02:00
Henry Mercer
93a4b427e3 Merge pull request #21933 from github/post-release-prep/codeql-cli-2.25.6
Post-release preparation for codeql-cli-2.25.6
2026-06-03 16:57:48 +01:00
Tom Hvitved
0430c71318 Merge pull request #21922 from hvitved/rust/static-const-resolution
Rust: Path resolution for `static` items
2026-06-03 17:48:21 +02:00
Owen Mansel-Chan
52f2a5825a Merge pull request #21804 from github/copilot/add-tests-for-models
Java: Update CWE-918 model coverage for Apache HttpClient `execute` sinks
2026-06-03 12:55:56 +01:00
Owen Mansel-Chan
d55ff83568 Merge pull request #21269 from owen-mc/go/improve-tests-for-varargs-flow
Go: improve tests for varargs flow
2026-06-03 12:39:46 +01:00
BazookaMusic
f34275636c No duplicate Ssa and remove release changenot 2026-06-03 11:54:24 +02:00
BazookaMusic
0a801440b9 review comments 2026-06-03 10:48:50 +02:00
Asger F
7edf0100cc Merge pull request #21924 from asgerf/asgerf/yeast-changes
Yeast: some fixes
2026-06-03 10:32:38 +02:00
Owen Mansel-Chan
167c837088 Merge pull request #21914 from owen-mc/shared/cfg/if-init
Shared CFG: allow init stmts for IfStmt
2026-06-02 22:01:02 +01:00
Owen Mansel-Chan
6f2cc43f32 Remove imprecise model for tuple() 2026-06-02 21:59:48 +01:00
Owen Mansel-Chan
5042fdee84 Remove imprecise model for list() 2026-06-02 21:59:46 +01:00
Owen Mansel-Chan
04341c47bd Tweak model for str.join 2026-06-02 21:59:44 +01:00
Tom Hvitved
af45e53e77 Rust: Rename parameter in DB upgrade script 2026-06-02 21:18:53 +02:00
Owen Mansel-Chan
b27d08ee32 Update edges in expected test output 2026-06-02 18:29:56 +01:00
Jeroen Ketema
d11fc3a00e Merge pull request #21932 from jketema/jketema/vue
JS: Add Vue to `file_coverage_languages` and `github_api_languages`
2026-06-02 17:53:25 +02:00
Owen Mansel-Chan
20ce679d61 Accept changed edges in test output
No changes to alerts
2026-06-02 16:15:08 +01:00
Owen Mansel-Chan
f62ebef9e0 Adjust expected test output 2026-06-02 16:15:06 +01:00
Owen Mansel-Chan
c3ef1ddd64 Add MaD models for lxml and xml etree.fromstringlist 2026-06-02 16:15:01 +01:00
Owen Mansel-Chan
dede5bc49b Track flow through tuple() with list with tainted elements 2026-06-02 16:14:59 +01:00
Owen Mansel-Chan
ad97b6dd64 Use access path for str.join model 2026-06-02 16:14:56 +01:00
Jeroen Ketema
9d5dfea5c5 JS: Add Vue to file_coverage_languages and github_api_languages 2026-06-02 16:57:51 +02:00
Tom Hvitved
dc0c7d7ec2 Fix commment typos 2026-06-02 14:41:27 +02:00
Owen Mansel-Chan
aaa3b363e1 Merge pull request #21929 from owen-mc/go/no-ret-functions
Go: Recognize more non-returning logging functions
2026-06-02 10:39:28 +01:00
Sotiris Dragonas
61a5cece56 Merge branch 'main' into bazookamusic/range-analysis-bound-move-to-shared 2026-06-02 10:41:49 +02:00
BazookaMusic
566a92e555 formatting again 2026-06-02 10:41:10 +02:00
Owen Mansel-Chan
9dbe9adb00 Update tests 2026-06-02 09:34:03 +01:00
Owen Mansel-Chan
be9c785cb2 Fix incorrect QLDoc
Co-authored-by: Tom Hvitved <hvitved@github.com>
2026-06-02 09:26:13 +01:00
Tom Hvitved
1fd31d0ddd Rust: Data flow for consts and statics 2026-06-02 09:55:51 +02:00
Tom Hvitved
c4e3720d8a Rust: Run codegen 2026-06-02 09:02:57 +02:00
Tom Hvitved
0547e9c98d Rust: Path resolution for static items 2026-06-02 09:02:56 +02:00
Owen Mansel-Chan
703cea2b65 Model panicking log functions better 2026-06-02 01:32:00 +01:00
Owen Mansel-Chan
e6e8e3d005 Taint doesn't flow through panicking functions 2026-06-02 01:31:44 +01:00
Owen Mansel-Chan
adc9b7714b Accept changed test output 2026-06-02 00:57:06 +01:00
Owen Mansel-Chan
e706c5f444 Improve test for non-returning fns 2026-06-02 00:56:12 +01:00
Owen Mansel-Chan
8a1e6d4f64 Add missing QLDocs 2026-06-02 00:41:48 +01:00
Owen Mansel-Chan
1a747dd8be (Trivial) Fix QLDoc grammar 2026-06-02 00:39:25 +01:00
Owen Mansel-Chan
28bb1a6870 Add change note 2026-06-02 00:16:23 +01:00
Owen Mansel-Chan
45b1253b23 Improve glog and klog tests 2026-06-02 00:16:21 +01:00
Owen Mansel-Chan
c99dab1d71 Improve glog (and klog) modelling 2026-06-02 00:16:19 +01:00
Owen Mansel-Chan
f3e3647209 Improve noretFunctions test 2026-06-02 00:16:17 +01:00
Owen Mansel-Chan
8d099cbe38 Recognize more non-returning logging functions 2026-06-02 00:15:58 +01:00
Tom Hvitved
9618e9b35c Merge pull request #21873 from hvitved/local-name-resolution
Shared: Local name resolution library
2026-06-01 20:51:07 +02:00
BazookaMusic
2a3cff382c more specific comment 2026-06-01 18:20:50 +02:00
BazookaMusic
c610af88d3 fix comment and add overlay[local?] 2026-06-01 18:18:37 +02:00
BazookaMusic
fa63dad1d1 change note 2026-06-01 18:16:51 +02:00
Sotiris Dragonas
019a5c01ad Merge branch 'main' into bazookamusic/range-analysis-bound-move-to-shared 2026-06-01 18:10:02 +02:00
BazookaMusic
c1c9287535 restore file header 2026-06-01 15:48:26 +02:00
BazookaMusic
d1226b71de formatting 2026-06-01 15:46:52 +02:00
BazookaMusic
71a363545a formatting 2026-06-01 15:24:06 +02:00
Asger F
3f3bed62d3 yeast: type-check for missing required fields
Add FieldCardinality to Schema to track required/multiple per field,
populated from the ast_types.yml suffixes (bare = required single,
? = optional single, + = required multiple, * = optional multiple).

dump_ast_with_type_errors now emits:
  <-- ERROR: missing required field 'name'
for any node in the output AST whose declared schema requires a field
that is absent from the actual node.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-01 14:18:37 +02:00
Asger F
21f216af8c yeast-macros: omit empty fields produced by .. splice
When a {..expr} splice in an output template is empty (e.g. from an
optional capture that did not match), drop the field entirely rather
than emitting an empty named field. This lets a single rule with
optional captures replace what used to be two near-identical rules.

Also re-renders the corpus to drop the now-suppressed empty fields.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-01 14:18:37 +02:00
Asger F
1751d70c62 Fix parsing of corpus tests when --- delimiter is missing 2026-06-01 14:18:37 +02:00
Asger F
ac8eb50c26 Yeast: Allow 'r#type' to escape the 'type' keyword in macro 2026-06-01 14:18:37 +02:00
Asger F
1ecdc3614f Yeast: Fix matching against extras like comments 2026-06-01 14:18:37 +02:00
Asger F
e3b3888bee Yeast: Fix handling of captures with multiple results 2026-06-01 14:18:36 +02:00
Asger F
ef9306d82c Yeast: Allow rules that return an empty sequence 2026-06-01 14:18:36 +02:00
Asger F
56822f8ee1 Tree-sitter-extactor: More helpful panic message 2026-06-01 14:04:49 +02:00
Tom Hvitved
62207f152c Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-01 13:55:22 +02:00
Tom Hvitved
d5f94475b5 Rust: DB upgrade/downgrade scripts 2026-06-01 10:38:10 +02:00
Tom Hvitved
00e95a0757 Rust: Add Impl::getSelf() and Impl::getTrait() 2026-06-01 10:38:09 +02:00
Tom Hvitved
c695c151ea Rust: Rename Impl::getTrait to Impl::getTraitTy 2026-06-01 10:38:07 +02:00
Tom Hvitved
d2f474d998 Address review comments 2026-06-01 08:30:01 +02:00
Owen Mansel-Chan
b38440490a Address review comment 2026-05-31 21:47:44 +01:00
Owen Mansel-Chan
5e5a0437e1 Shared CFG: allow init stmts for IfStmt 2026-05-30 07:35:29 +01:00
Tom Hvitved
caae5a8bf1 Apply suggestions from code review
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-29 14:24:45 +02:00
Owen Mansel-Chan
aee33a0cc9 Add missing code for TAnyTupleOrDictionaryElement 2026-05-29 10:26:24 +01:00
Tom Hvitved
09371339d7 Ruby: Adopt shared local name resolution library 2026-05-29 09:06:14 +02:00
Owen Mansel-Chan
df15a719cb Add a ContentSet for any tuple or dictionary element 2026-05-28 16:48:23 +01:00
Owen Mansel-Chan
812e8e6b34 Add change note 2026-05-28 11:37:54 +01:00
Owen Mansel-Chan
80c6f082d1 Fix TODO in containerStep 2026-05-28 11:34:02 +01:00
Owen Mansel-Chan
d95d99848c Build RequestBuilder more realistically 2026-05-28 11:05:40 +01:00
Owen Mansel-Chan
8937e22735 Add summary models for org.apache.http.client.methods.RequestBuilder
Generated by GPT 5.3-codex, verified by me.
2026-05-28 10:56:37 +01:00
Owen Mansel-Chan
37589dd8a0 Improve how org.apache.http.client.HttpClient is created in test 2026-05-28 10:30:43 +01:00
Owen Mansel-Chan
a159dc1c66 Change variable name in test 2026-05-28 10:28:14 +01:00
Tom Hvitved
7718fe40a0 Ruby: Add more variable tests 2026-05-28 10:50:15 +02:00
Tom Hvitved
aeb82858d7 Rust: Run codegen 2026-05-28 10:50:13 +02:00
Tom Hvitved
c08cf81665 Rust: Adopt shared local name resolution library 2026-05-28 10:50:10 +02:00
Tom Hvitved
e06158629e Rust: More local variable tests 2026-05-28 10:50:05 +02:00
Tom Hvitved
3e09961662 Shared: Add local name binding library 2026-05-28 10:50:03 +02:00
BazookaMusic
cc12740c0e remove check for files in sync 2026-05-27 17:41:44 +02:00
BazookaMusic
acb5c0e70f missed changes 2026-05-27 17:23:45 +02:00
BazookaMusic
6042adebae move identical java and cs bound.qll to shared library 2026-05-27 17:23:28 +02:00
Owen Mansel-Chan
ec13e1bcd3 Add wildcard ContentSets to avoid performance problems 2026-05-27 15:28:07 +01:00
Owen Mansel-Chan
e8779295ee Update test results 2026-05-22 11:43:18 +01:00
Rasmus Lerchedahl Petersen
fa758d6bf5 python: fix test 2026-05-21 16:59:19 +01:00
Rasmus Lerchedahl Petersen
fa9426c749 Python: extra tests for comprehension 2026-05-21 16:59:18 +01:00
Rasmus Lerchedahl Petersen
0ecca91dea Python: typo 2026-05-21 16:59:16 +01:00
Rasmus Lerchedahl Petersen
f669a4f3bf Python: Make sure all imprecise taint bubbles up 2026-05-21 16:59:14 +01:00
Rasmus Lerchedahl Petersen
3275c814bd Python: reset test expectations 2026-05-21 16:59:11 +01:00
Rasmus Lerchedahl Petersen
9a180036a5 Python: conversion step for format_map
and adjust collection test
2026-05-21 16:59:08 +01:00
Rasmus Lerchedahl Petersen
93e7ab52b7 Python: adjust test expectations
We now find an alert on this line as we hope to
It is not an alert for _full_ SSRF, though, since that configuration cannot handle multiple substitutions.
2026-05-21 16:58:51 +01:00
Rasmus Lerchedahl Petersen
facb3b681d Python: recover taint for % format strings 2026-05-21 16:57:50 +01:00
Rasmus Lerchedahl Petersen
b67694b2ab Python: Remove imprecise container steps
- remove `tupleStoreStep` and `dictStoreStep` from `containerStep`
   These are imprecise compared to the content being precise.
- add implicit reads to recover taint at sinks
- add implicit read steps for decoders
  to supplement the `AdditionalTaintStep`
  that now only covers when the full container is tainted.
2026-05-21 16:57:44 +01:00
Owen Mansel-Chan
dc864762c3 Add change note 2026-05-07 10:23:50 +01:00
Owen Mansel-Chan
dd35bc0722 Update test output 2026-05-07 10:17:47 +01:00
copilot-swe-agent[bot]
043ec857ab Replace fluent SSRF changes with Apache HttpClient execute model tests
Agent-Logs-Url: https://github.com/github/codeql/sessions/3db201db-a1b5-4353-a94a-14a8d156dd3b

Co-authored-by: owen-mc <62447351+owen-mc@users.noreply.github.com>
2026-05-06 20:31:34 +00:00
copilot-swe-agent[bot]
f5b17b0b48 Add SSRF tests and stubs for Apache Http fluent Request models
Agent-Logs-Url: https://github.com/github/codeql/sessions/bd4fa112-dbc3-47e8-9cef-9b1b13c7e549

Co-authored-by: owen-mc <62447351+owen-mc@users.noreply.github.com>
2026-05-06 16:08:02 +00:00
copilot-swe-agent[bot]
26dca558c7 Initial plan 2026-05-06 16:02:08 +00:00
Owen Mansel-Chan
a367294c23 Merge branch 'main' into copilot/automate-go-version-updates-again 2026-04-23 14:41:46 +01:00
copilot-swe-agent[bot]
b6004045bd Clean up Go version workflow - remove unnecessary escaping and checks
Co-authored-by: mbg <278086+mbg@users.noreply.github.com>
2026-02-13 11:23:44 +00:00
copilot-swe-agent[bot]
cc7e03b0f5 Add error handling and validation to Go version workflow
Co-authored-by: mbg <278086+mbg@users.noreply.github.com>
2026-02-13 11:22:36 +00:00
copilot-swe-agent[bot]
1cbd423251 Improve portability and fix PR detection in Go version workflow
Co-authored-by: mbg <278086+mbg@users.noreply.github.com>
2026-02-13 11:21:13 +00:00
copilot-swe-agent[bot]
437244fe90 Fix portability issues in Go version update workflow
Co-authored-by: mbg <278086+mbg@users.noreply.github.com>
2026-02-13 11:19:56 +00:00
copilot-swe-agent[bot]
f7cf24d1f9 Add Go version update workflow
Co-authored-by: mbg <278086+mbg@users.noreply.github.com>
2026-02-13 11:17:57 +00:00
copilot-swe-agent[bot]
c3bafacf81 Initial plan 2026-02-13 11:15:15 +00:00
Owen Mansel-Chan
57ce0b3d51 Accept data flow consistency result 2026-02-05 22:28:54 +00:00
Owen Mansel-Chan
408ba2e139 (Misc) Delete spuriously committed binary file 2026-02-04 13:41:14 +00:00
Owen Mansel-Chan
7632bdba88 (Misc) fix variable names 2026-02-04 13:40:52 +00:00
Owen Mansel-Chan
4b830c1864 Test varargs flow with models-as-data 2026-02-04 13:40:33 +00:00
Owen Mansel-Chan
d6c8767647 Test flow out of varargs parameter in function model 2026-02-04 13:40:01 +00:00
Owen Mansel-Chan
ec815397a2 Test flow out of varargs parameter in source function 2026-02-04 13:38:48 +00:00
203 changed files with 22340 additions and 5384 deletions

208
.github/workflows/go-version-update.yml vendored Normal file
View File

@@ -0,0 +1,208 @@
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

View File

@@ -273,7 +273,7 @@ use_repo(
)
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
go_sdk.download(version = "1.26.0")
go_sdk.download(version = "1.26.4")
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//go/extractor:go.mod")

View File

@@ -11,10 +11,6 @@
"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"

View File

@@ -9,6 +9,7 @@ dependencies:
codeql/controlflow: ${workspace}
codeql/dataflow: ${workspace}
codeql/mad: ${workspace}
codeql/rangeanalysis: ${workspace}
codeql/ssa: ${workspace}
codeql/threat-models: ${workspace}
codeql/tutorial: ${workspace}

View File

@@ -4,67 +4,31 @@
overlay[local?]
module;
private import internal.rangeanalysis.BoundSpecific
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 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())
}
/** Provides C#-specific definitions for bounds. */
private module BoundDefs implements SharedBound::BoundDefinitions<CS::Location> {
class Type = CS::Type;
/**
* 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 SsaVariable = SU::SsaVariable;
/** Gets an expression that equals this bound plus `delta`. */
abstract Expr getExpr(int delta);
class SsaSourceVariable = SourceVariable;
/** Gets an expression that equals this bound. */
Expr getExpr() { result = this.getExpr(0) }
class Expr = CS::ControlFlowNodes::ExprNode;
/** Gets the location of this bound. */
abstract Location getLocation();
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()) }
}
/**
* 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" }
module BoundImpl = SharedBound::Bound<CS::Location, BoundDefs>;
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() }
}
import BoundImpl

View File

@@ -1,22 +0,0 @@
/**
* 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()) }

View File

@@ -0,0 +1,139 @@
.. _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.

View File

@@ -11,6 +11,7 @@ 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

View File

@@ -4,7 +4,7 @@ inputs:
go-test-version:
description: Which Go version to use for running the tests
required: false
default: "~1.26.0"
default: "~1.26.4"
run-code-checks:
description: Whether to run formatting, code and qhelp generation checks
required: false

View File

@@ -2,14 +2,14 @@ module github.com/github/codeql-go/extractor
go 1.26
toolchain go1.26.0
toolchain go1.26.4
// 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.36.0
golang.org/x/mod v0.37.0
golang.org/x/tools v0.45.0
)

View File

@@ -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.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4=
golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ=
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/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=

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* More logging functions are now recognized as not returning or panicking.

View File

@@ -413,17 +413,13 @@ private class ExternalLoggerCall extends LoggerCall::Range, DataFlow::CallNode {
}
}
/**
* 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
private class HeuristicLoggerFunction extends Method {
string logFunctionPrefix;
HeuristicLoggerFunction() {
exists(string tp, string name |
this.hasQualifiedName(_, tp, name) and
this.getReceiverBaseType().getUnderlyingType() instanceof InterfaceType
|
tp.regexpMatch(".*[lL]ogger") and
logFunctionPrefix =
@@ -435,6 +431,19 @@ private class HeuristicLoggerCall extends LoggerCall::Range, DataFlow::CallNode
)
}
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() }
}

View File

@@ -12,17 +12,37 @@ 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 fn, string level |
pkg = package(["github.com/golang/glog", "gopkg.in/glog", "k8s.io/klog"], "") and
exists(string pkg, string context, int nContextArgs, string depth, int nDepthArgs, string fn |
pkg = packagePath() and
level = ["Error", "Exit", "Fatal", "Info", "Warning"] and
(
fn = level + ["", "f", "ln"] and firstPrintedArg = 0
context = "" and nContextArgs = 0
or
fn = level + "Depth" and firstPrintedArg = 1
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
)
|
this.hasQualifiedName(pkg, fn)
@@ -35,10 +55,15 @@ 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.getName().matches("%f") }
StringFormatter() { this.formatter() }
override int getFormatStringIndex() { result = super.getFirstPrintedArg() }
}

View File

@@ -28,6 +28,12 @@ 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 {

View File

@@ -47,7 +47,7 @@ module Zap {
}
/** A Zap logging function which always panics. */
private class FatalLogMethod extends Method {
private class FatalLogMethod extends ZapFunction {
FatalLogMethod() {
this.hasQualifiedName(packagePath(), "Logger", "Fatal")
or
@@ -58,7 +58,7 @@ module Zap {
}
/** A Zap logging function which always panics. */
private class MustPanicLogMethod extends Method {
private class MustPanicLogMethod extends ZapFunction {
MustPanicLogMethod() {
this.hasQualifiedName(packagePath(), "Logger", "Panic")
or

View File

@@ -29,18 +29,37 @@ module Log {
}
private class LogFormatter extends StringOps::Formatting::Range instanceof LogFunction {
LogFormatter() { this.getName() = ["Fatalf", "Panicf", "Printf"] }
LogFormatter() { this.getName() = ["Fatalf", "Panicf", "Printf", "Panic", "Panicf", "Panicln"] }
override int getFormatStringIndex() { result = 0 }
}
/** A fatal log function, which calls `os.Exit`. */
private class FatalLogFunction extends Function {
FatalLogFunction() { this.hasQualifiedName("log", ["Fatal", "Fatalf", "Fatalln"]) }
FatalLogFunction() {
exists(string fn | fn = ["Fatal", "Fatalf", "Fatalln"] |
this.hasQualifiedName("log", fn)
or
this.(Method).hasQualifiedName("log", "Logger", fn)
)
}
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;
@@ -63,30 +82,6 @@ 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())

View File

@@ -1,54 +1,181 @@
//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
//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
package main
import (
"context"
"github.com/golang/glog"
"k8s.io/klog"
)
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
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
// components corresponding to the format specifier "%T" are not considered vulnerable
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
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
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.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.Info(text) // $ logger=text
klog.InfoDepth(0, text) // $ logger=text
klog.Infof(fmt, text) // $ logger=fmt logger=text
@@ -57,11 +184,19 @@ func glogTest() {
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
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
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
}

View File

@@ -3,7 +3,7 @@ module codeql-go-tests/concepts/loggercall
go 1.15
require (
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/golang/glog v1.2.5
github.com/sirupsen/logrus v1.7.0
k8s.io/klog v1.0.0
)

View File

@@ -6,5 +6,6 @@ const text = "test"
var v []byte
func main() {
glogTest(len(v))
stdlib()
}

View File

@@ -2,47 +2,125 @@
// 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: ; functions: Error,ErrorDepth,Errorf,Errorln,Exit,ExitDepth,Exitf,Exitln,Fatal,FatalDepth,Fatalf,Fatalln,Info,InfoDepth,Infof,Infoln,Warning,WarningDepth,Warningf,Warningln)
// 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)
// 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{}) {}

View File

@@ -2,11 +2,15 @@
// 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: ; functions: Error,ErrorDepth,Errorf,Errorln,Exit,ExitDepth,Exitf,Exitln,Fatal,FatalDepth,Fatalf,Fatalln,Info,InfoDepth,Infof,Infoln,Warning,WarningDepth,Warningf,Warningln)
// 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)
// 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{}) {}
@@ -39,6 +43,8 @@ func Infof(_ string, _ ...interface{}) {}
func Infoln(_ ...interface{}) {}
func V(_ Level) Verbose { return false }
func Warning(_ ...interface{}) {}
func WarningDepth(_ int, _ ...interface{}) {}
@@ -46,3 +52,9 @@ func WarningDepth(_ int, _ ...interface{}) {}
func Warningf(_ string, _ ...interface{}) {}
func Warningln(_ ...interface{}) {}
func (_ Verbose) Info(_ ...interface{}) {}
func (_ Verbose) Infof(_ string, _ ...interface{}) {}
func (_ Verbose) Infoln(_ ...interface{}) {}

View File

@@ -1,4 +1,4 @@
# github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
# github.com/golang/glog v1.2.5
## explicit
github.com/golang/glog
# github.com/sirupsen/logrus v1.7.0

View File

@@ -1,11 +1,21 @@
| 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 |
| 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 |

View File

@@ -2,4 +2,4 @@ import go
from Function f
where not f.mayReturnNormally()
select f, f.getPackage()
select f, f.getQualifiedName()

View File

@@ -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 src) { sourceNode(src, "qltest") }
predicate isSource(DataFlow::Node source) { sourceNode(source, "qltest") }
predicate isSink(DataFlow::Node src) { sinkNode(src, "qltest") }
predicate isSink(DataFlow::Node sink) { sinkNode(sink, "qltest") }
}
import ValueFlowTest<Config>

View File

@@ -0,0 +1,2 @@
reverseRead
| main.go:23:3:23:5 | out | Origin of readStep is missing a PostUpdateNode. |

View File

@@ -4,7 +4,7 @@ func source() string {
return "untrusted data"
}
func sink(string) {
func sink(any) {
}
type A struct {
@@ -19,6 +19,10 @@ 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
}
@@ -38,6 +42,12 @@ 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"

View File

@@ -0,0 +1,2 @@
invalidModelRow
testFailures

View File

@@ -0,0 +1,21 @@
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"]

View File

@@ -0,0 +1,22 @@
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>

View File

@@ -0,0 +1,5 @@
module semmle.go.Packages
go 1.25
require github.com/nonexistent/test v0.0.0-20200203000000-0000000000000

View File

@@ -0,0 +1,56 @@
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}"
}

View File

@@ -0,0 +1,32 @@
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) {}

View File

@@ -0,0 +1,3 @@
# github.com/nonexistent/test v0.0.0-20200203000000-0000000000000
## explicit
github.com/nonexistent/test

View File

@@ -20,6 +20,9 @@ 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

View File

@@ -1,5 +1,5 @@
module semmle.go.Packages
go 1.17
go 1.25
require github.com/nonexistent/test v0.0.0-20200203000000-0000000000000

View File

@@ -8,7 +8,7 @@ func source() string {
return "untrusted data"
}
func sink(string) {
func sink(any) {
}
func main() {
@@ -21,10 +21,17 @@ 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"
sink(test.FunctionWithVarArgsParameter(s0, s1)) // $ MISSING: hasValueFlow="call to FunctionWithVarArgsParameter"
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"
sliceOfStructs := []test.A{{Field: source()}}
sink(sliceOfStructs[0].Field) // $ hasValueFlow="selection of Field"
@@ -37,3 +44,6 @@ 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) {
}

View File

@@ -16,6 +16,9 @@ func FunctionWithVarArgsParameter(s ...string) string {
return ""
}
func FunctionWithVarArgsOutParameter(in string, out ...*string) {
}
func FunctionWithSliceOfStructsParameter(s []A) string {
return ""
}

View File

@@ -15,62 +15,6 @@ 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
@@ -125,46 +69,6 @@ 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)

View File

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

View File

@@ -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 == "true" {
if testFlag == "1" {
log.Fatal("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
}
if testFlag == "true" {
if testFlag == "2" {
log.Fatalf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password"
}
if testFlag == "true" {
if testFlag == "3" {
log.Fatalln("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
}
if testFlag == "true" {
if testFlag == "4" {
log.Panic("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
}
if testFlag == "true" {
if testFlag == "5" {
log.Panicf(formatString, username, password) // $ hasTaintFlow="formatString" hasTaintFlow="username" hasTaintFlow="password"
}
if testFlag == "true" {
if testFlag == "6" {
log.Panicln("user is logged in:", username, password) // $ hasTaintFlow="username" hasTaintFlow="password"
}
@@ -72,12 +72,24 @@ 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"
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"
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"
}
}
// k8s.io/klog
{
@@ -91,12 +103,24 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
klog.Error(username) // $ hasTaintFlow="username"
klog.Errorf(username) // $ hasTaintFlow="username"
klog.Errorln(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"
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"
}
}
// astaxie/beego
{
@@ -161,14 +185,30 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) {
glog.ErrorDepth(0, username) // $ hasTaintFlow="username"
glog.Errorf(username) // $ hasTaintFlow="username"
glog.Errorln(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"
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"
}
}
// sirupsen/logrus
@@ -179,26 +219,42 @@ 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"
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.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.Print(username) // $ hasTaintFlow="username"
logrus.Printf(username, "") // $ hasTaintFlow="username"
logrus.Printf("", username) // $ hasTaintFlow="username"
@@ -220,30 +276,46 @@ 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"
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.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.Print(username) // $ hasTaintFlow="username"
entry.Printf(username, "") // $ hasTaintFlow="username"
entry.Printf("", username) // $ hasTaintFlow="username"
@@ -265,30 +337,46 @@ 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"
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.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.Print(username) // $ hasTaintFlow="username"
logger.Printf(username, "") // $ hasTaintFlow="username"
logger.Printf("", username) // $ hasTaintFlow="username"
@@ -311,26 +399,42 @@ 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"
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.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.Print(username) // $ hasTaintFlow="username"
fieldlogger.Printf(username, "") // $ hasTaintFlow="username"
fieldlogger.Printf("", username) // $ hasTaintFlow="username"
@@ -366,11 +470,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 == " true" {
if testFlag == "45" {
logger.Fatal(username) // $ hasTaintFlow="username"
}
logger.Info(username) // $ hasTaintFlow="username"
if testFlag == " true" {
if testFlag == "46" {
logger.Panic(username) // $ hasTaintFlow="username"
}
logger.Warn(username) // $ hasTaintFlow="username"
@@ -382,33 +486,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 == " true" {
if testFlag == "47" {
sLogger.Fatal(username) // $ hasTaintFlow="username"
}
sLogger.Info(username) // $ hasTaintFlow="username"
if testFlag == " true" {
if testFlag == "48" {
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 == " true" {
if testFlag == "49" {
sLogger.Fatalf(username) // $ hasTaintFlow="username"
}
sLogger.Infof(username) // $ hasTaintFlow="username"
if testFlag == " true" {
if testFlag == "50" {
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 == " true" {
if testFlag == "51" {
sLogger.Fatalw(username) // $ hasTaintFlow="username"
}
sLogger.Infow(username) // $ hasTaintFlow="username"
if testFlag == " true" {
if testFlag == "52" {
sLogger.Panicw(username) // $ hasTaintFlow="username"
}
sLogger.Warnw(username) // $ hasTaintFlow="username"
@@ -515,10 +619,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 == " true" {
if testFlag == "53" {
klog.Fatalf("user %q logged in.\n", username)
}
if testFlag == " true" {
if testFlag == "54" {
klog.Exitf("user %q logged in.\n", username)
}
}
@@ -534,10 +638,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 == " true" {
if testFlag == "55" {
glog.Fatalf("user %q logged in.\n", username)
}
if testFlag == " true" {
if testFlag == "56" {
glog.Exitf("user %q logged in.\n", username)
}
}
@@ -545,11 +649,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 == " true" {
if testFlag == "57" {
logrus.Fatalf("user %q logged in.\n", username)
}
logrus.Infof("user %q logged in.\n", username)
if testFlag == " true" {
if testFlag == "58" {
logrus.Panicf("user %q logged in.\n", username)
}
logrus.Printf("user %q logged in.\n", username)
@@ -561,12 +665,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 == " true" {
if testFlag == "59" {
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 == " true" {
if testFlag == "60" {
entry.Panicf("user %q logged in.\n", username)
}
entry.Printf("user %q logged in.\n", username)
@@ -577,12 +681,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 == " true" {
if testFlag == "61" {
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 == " true" {
if testFlag == "62" {
logger.Panicf("user %q logged in.\n", username)
}
logger.Printf("user %q logged in.\n", username)
@@ -603,11 +707,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 == " true" {
if testFlag == "63" {
sLogger.Fatalf("user %q logged in.\n", username)
}
sLogger.Infof("user %q logged in.\n", username)
if testFlag == " true" {
if testFlag == "64" {
sLogger.Panicf("user %q logged in.\n", username)
}
sLogger.Warnf("user %q logged in.\n", username)
@@ -620,10 +724,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 == " true" {
if testFlag == "65" {
klog.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
}
if testFlag == " true" {
if testFlag == "66" {
klog.Exitf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
}
}
@@ -639,10 +743,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 == " true" {
if testFlag == "67" {
glog.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
}
if testFlag == " true" {
if testFlag == "68" {
glog.Exitf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
}
}
@@ -650,11 +754,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 == " true" {
if testFlag == "69" {
logrus.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
}
logrus.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username"
if testFlag == " true" {
if testFlag == "70" {
logrus.Panicf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
}
logrus.Printf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
@@ -666,12 +770,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 == " true" {
if testFlag == "71" {
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 == " true" {
if testFlag == "72" {
entry.Panicf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
}
entry.Printf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
@@ -682,12 +786,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 == " true" {
if testFlag == "73" {
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 == " true" {
if testFlag == "74" {
logger.Panicf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
}
logger.Printf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
@@ -708,11 +812,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 == " true" {
if testFlag == "75" {
sLogger.Fatalf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
}
sLogger.Infof("user %#q logged in.\n", username) // $ hasTaintFlow="username"
if testFlag == " true" {
if testFlag == "76" {
sLogger.Panicf("user %#q logged in.\n", username) // $ hasTaintFlow="username"
}
sLogger.Warnf("user %#q logged in.\n", username) // $ hasTaintFlow="username"

View File

@@ -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: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 |
| 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 |
| 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,95 +82,15 @@ 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 | |
@@ -182,46 +102,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: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: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:30:8:30:15 | password | passwords.go:8:12:8:12 | definition of x | 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 | |
| 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 | |
| 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 | |
@@ -274,20 +194,12 @@ 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 |
@@ -308,43 +220,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: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 |
| 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 |
| 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] |

View File

@@ -16,7 +16,7 @@ func redact(kind, value string) string {
return value
}
func test() {
func test(selector int) {
name := "user"
password := "P@ssw0rd" // $ Source
x := "horsebatterystapleincorrect"
@@ -29,7 +29,9 @@ func test() {
myLog(password)
log.Panic(password) // $ Alert
if selector == 1 {
log.Panic(password) // $ Alert
}
log.Println(name + ", " + password) // $ Alert

View File

@@ -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,48,3,95,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,46,,,,,,,,,,,,,,,,3,86,9
org.apache.http,53,3,117,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,51,,,,,,,,,,,,,,,,3,108,9
org.apache.ibatis.jdbc,6,,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,57,
org.apache.ibatis.mapping,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
org.apache.log4j,11,,,,,,,,,,,,,,,,,,,,,,11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1 package sink source summary sink:bean-validation sink:command-injection sink:credentials-key sink:credentials-password sink:credentials-username sink:encryption-iv sink:encryption-salt sink:environment-injection sink:file-content-store sink:fragment-injection sink:groovy-injection sink:hostname-verification sink:html-injection sink:information-leak sink:intent-redirection sink:jexl-injection sink:jndi-injection sink:js-injection sink:ldap-injection sink:log-injection sink:mvel-injection sink:notification sink:ognl-injection sink:path-injection sink:path-injection[read] sink:pending-intents sink:regex-use sink:regex-use[-1] sink:regex-use[0] sink:regex-use[] sink:regex-use[f-1] sink:regex-use[f1] sink:regex-use[f] sink:request-forgery sink:response-splitting sink:sql-injection sink:template-injection sink:trust-boundary-violation sink:unsafe-deserialization sink:url-forward sink:url-redirection sink:xpath-injection sink:xslt-injection source:android-external-storage-dir source:commandargs source:contentprovider source:database source:environment source:file source:remote summary:taint summary:value
194 org.apache.hc.core5.net 18 18
195 org.apache.hc.core5.util 24 18 6
196 org.apache.hive.hcatalog.templeton 1 1
197 org.apache.http 48 53 3 95 117 2 46 51 3 86 108 9
198 org.apache.ibatis.jdbc 6 57 6 57
199 org.apache.ibatis.mapping 1 1
200 org.apache.log4j 11 11

View File

@@ -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,183,122,,3,,,,119
`Apache HttpComponents <https://hc.apache.org/>`_,"``org.apache.hc.core5.*``, ``org.apache.http``",5,205,127,,3,,,,124
`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,26381,2702,421,16,137,33,1,410
Totals,,382,26403,2707,421,16,137,33,1,415

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Improved modeling of Apache HttpClient `execute` method sinks for `java/ssrf` and `java/non-https-url`.

View File

@@ -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", "hq-manual"]
- ["org.apache.http.client.methods", "HttpRequestWrapper", True, "setURI", "(URI)", "", "Argument[0]", "request-forgery", "ai-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,3 +22,29 @@ 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"]

View File

@@ -3,6 +3,11 @@ extensions:
pack: codeql/java-all
extensible: sinkModel
data:
- ["org.apache.http.client", "HttpClient", True, "execute", "(HttpUriRequest,HttpContext)", "", "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", "(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"]

View File

@@ -4,67 +4,33 @@
overlay[local?]
module;
private import internal.rangeanalysis.BoundSpecific
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 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())
private module BoundDefs implements SharedBound::BoundDefinitions<J::Location> {
class SsaVariable extends Ssa::SsaDefinition {
/** Gets a use of this variable. */
Expr getAUse() { result = super.getARead() }
}
/**
* 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 = Ssa::SourceVariable;
/** Gets an expression that equals this bound plus `delta`. */
abstract Expr getExpr(int delta);
class Type = J::Type;
/** Gets an expression that equals this bound. */
Expr getExpr() { result = this.getExpr(0) }
class Expr = J::Expr;
/** Gets the location of this bound. */
abstract Location getLocation();
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
}
}
/**
* 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" }
module BoundImpl = SharedBound::Bound<J::Location, BoundDefs>;
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() }
}
import BoundImpl

View File

@@ -1,27 +0,0 @@
/**
* 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
}

View File

@@ -0,0 +1,45 @@
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
}
}
}

View File

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

View File

@@ -0,0 +1,23 @@
// 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;
}

View File

@@ -0,0 +1,9 @@
// 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);
}

View File

@@ -0,0 +1,7 @@
package org.apache.http.impl.client;
import org.apache.http.client.HttpClient;
public abstract class CloseableHttpClient implements HttpClient {
}

View File

@@ -0,0 +1,10 @@
// 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; }
}

View File

@@ -63,6 +63,7 @@ ql/javascript/ql/src/experimental/Security/CWE-347/decodeJwtWithoutVerificationL
ql/javascript/ql/src/experimental/Security/CWE-444/InsecureHttpParser.ql
ql/javascript/ql/src/experimental/Security/CWE-522-DecompressionBombs/DecompressionBombs.ql
ql/javascript/ql/src/experimental/Security/CWE-918/SSRF.ql
ql/javascript/ql/src/experimental/Security/CWE-918/SsrfIpv6TransitionIncompleteGuard.ql
ql/javascript/ql/src/experimental/StandardLibrary/MultipleArgumentsToSetConstructor.ql
ql/javascript/ql/src/experimental/heuristics/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql
ql/javascript/ql/src/experimental/heuristics/ql/src/Security/CWE-078/CommandInjection.ql

View File

@@ -0,0 +1,4 @@
---
category: newQuery
---
* Added a new experimental query, `javascript/ssrf-ipv6-transition-incomplete-guard`, to detect SSRF host-validation guards that reject private IPv4 ranges but fail to unwrap IPv6-transition forms (IPv4-mapped `::ffff:`, NAT64 `64:ff9b::`, 6to4 `2002::`), allowing the guard to be bypassed by wrapping an internal IPv4 address in a transition literal.

View File

@@ -0,0 +1,59 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Server-side request forgery (SSRF) guards frequently reject requests to internal
addresses by checking the request host against a denylist of private, loopback and
cloud-metadata IPv4 ranges. When such a guard inspects only the dotted-quad IPv4 form
and never unwraps IPv6-transition representations, it can be bypassed: the host
validator classifies the address as public, but the operating system routes the
connection to the embedded internal IPv4 endpoint.
</p>
<p>
The affected forms include IPv4-mapped IPv6 (<code>::ffff:169.254.169.254</code>),
NAT64 (<code>64:ff9b::a9fe:a9fe</code>) and 6to4 (<code>2002::</code>). A URL such as
<code>http://[::ffff:169.254.169.254]/</code> passes a dotted-quad denylist unchanged
while still reaching the internal address.
</p>
</overview>
<recommendation>
<p>
Normalize the host before validating it: parse the address with a transition-aware
library and unwrap IPv4-mapped, NAT64 and 6to4 forms to their embedded IPv4 address,
then apply the private-range check to the normalized value. Libraries such as
<code>ipaddr.js</code> classify these forms correctly via their range API, and
SSRF-protection libraries such as <code>request-filtering-agent</code> apply the check
after DNS resolution. Validate the resolved address rather than the textual host.
</p>
</recommendation>
<example>
<p>
The following guard rejects private IPv4 ranges using the <code>private-ip</code>
package, which inspects the textual IPv4 form only. An attacker supplies
<code>::ffff:169.254.169.254</code>, which the guard classifies as public, but the
request still reaches the internal metadata endpoint.
</p>
<sample src="examples/SsrfIpv6TransitionIncompleteGuardBad.js"/>
<p>
The following guard parses the host with a transition-aware classifier, so the
embedded internal IPv4 address is detected regardless of the transition form used.
</p>
<sample src="examples/SsrfIpv6TransitionIncompleteGuardGood.js"/>
</example>
<references>
<li>OWASP: <a href="https://owasp.org/www-community/attacks/Server_Side_Request_Forgery">Server-Side Request Forgery</a>.</li>
<li>Common Weakness Enumeration: <a href="https://cwe.mitre.org/data/definitions/918.html">CWE-918</a>.</li>
<li>Common Weakness Enumeration: <a href="https://cwe.mitre.org/data/definitions/1389.html">CWE-1389</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,129 @@
/**
* @name SSRF host guard does not reject IPv6-transition forms
* @description An SSRF host guard that rejects private or loopback IPv4 ranges but never
* unwraps IPv6-transition forms (IPv4-mapped `::ffff:`, NAT64 `64:ff9b::`,
* 6to4 `2002::`) can be bypassed by wrapping an internal IPv4 address in a
* transition literal, allowing requests to reach internal endpoints.
* @kind problem
* @problem.severity warning
* @id javascript/ssrf-ipv6-transition-incomplete-guard
* @tags security
* experimental
* external/cwe/cwe-918
* external/cwe/cwe-1389
*/
import javascript
/**
* Holds if `f` imports a dotted-quad-oriented private-IP guard package whose
* classification is performed on the textual IPv4 form and therefore returns
* `false` for an internal address wrapped in an IPv6-transition literal.
*/
predicate importsHandRolledIpGuard(File f) {
exists(DataFlow::SourceNode mod |
mod.getFile() = f and
mod = DataFlow::moduleImport(["private-ip", "is-ip", "ip", "ip-range-check"])
)
}
/**
* Holds if `f` contains a call to an `isPrivate`-style host classifier, the
* common name for a hand-rolled SSRF guard.
*/
predicate hasIsPrivateCall(File f) {
exists(DataFlow::CallNode c |
c.getFile() = f and
c.getCalleeName().regexpMatch("(?i)^is_?private(ip|address|host)?$")
)
or
exists(DataFlow::MethodCallNode m |
m.getFile() = f and
m.getMethodName().regexpMatch("(?i)^is_?private(ip|address|host)?$")
)
}
/**
* Holds if `f` contains a hand-written RFC 1918, loopback or cloud-metadata IPv4
* literal used as a denylist entry.
*/
predicate hasRfc1918Literal(File f) {
exists(StringLiteral s |
s.getFile() = f and
s.getValue()
.regexpMatch("(?i).*(127\\.0\\.0\\.1|169\\.254\\.169\\.254|10\\.|192\\.168|172\\.1[6-9]|::1|fc00|fd00|metadata\\.google).*")
)
}
/** Holds if `f` carries any hand-rolled, dotted-quad-oriented SSRF guard signal. */
predicate hasUnsafeGuardSignal(File f) {
importsHandRolledIpGuard(f) or
hasIsPrivateCall(f) or
hasRfc1918Literal(f)
}
/** Holds if `func` has a name that reads as an SSRF host or URL validator. */
predicate isSsrfValidatorFunction(Function func) {
func.getName()
.regexpMatch("(?i).*(validate|check|guard|reject|deny|block|allow|is_?safe|sanitiz)e?_?.*(url|host|ip|address|target|endpoint|webhook|origin).*")
or
func.getName()
.regexpMatch("(?i).*(is_?)?(private|internal|loopback|reserved|external)_?(ip|address|host|url).*")
or
func.getName().regexpMatch("(?i).*(ssrf|metadata).*")
}
/**
* Holds if `f` imports a maturity-hardened, transition-aware address classifier
* or SSRF-protection library that does unwrap IPv6-transition forms.
*/
predicate importsSafeClassifier(File f) {
exists(DataFlow::SourceNode mod |
mod.getFile() = f and
mod =
DataFlow::moduleImport([
"ipaddr.js", "ssrf-req-filter", "request-filtering-agent", "ssrf-agent", "netmask",
"ip-cidr", "cidr-matcher", "blocked-at"
])
)
}
/**
* Holds if `f` already performs an explicit IPv6-transition unwrap or
* canonicalization, so the guard does see the embedded IPv4 address.
*/
predicate hasTransitionUnwrap(File f) {
exists(StringLiteral s |
s.getFile() = f and
(
s.getValue().matches("%64:ff9b%") or
s.getValue().matches("%::ffff%") or
s.getValue().matches("%2002:%") or
s.getValue().matches("%2001:%")
)
)
or
exists(Identifier id |
id.getFile() = f and
id.getName()
.regexpMatch("(?i).*(ipv4mapped|v4mapped|mappedipv4|ipv4inipv6|embeddedipv4|unwrap.*ip|toipv4|canonicaliz|isipv4compat).*")
)
or
exists(DataFlow::MethodCallNode m | m.getFile() = f and m.getMethodName() = ["range", "kind"])
}
/** Holds if `f` is treated as safe (transition-aware), suppressing the alert. */
predicate isSafe(File f) { importsSafeClassifier(f) or hasTransitionUnwrap(f) }
from Function guard, File f
where
guard.getFile() = f and
isSsrfValidatorFunction(guard) and
hasUnsafeGuardSignal(f) and
not isSafe(f) and
not f.getRelativePath()
.regexpMatch("(?i).*/(tests?|specs?|examples?|__tests__|e2e|node_modules)/.*")
select guard,
"This SSRF host guard rejects private IPv4 ranges but never unwraps IPv6-transition forms " +
"(IPv4-mapped '::ffff:', NAT64 '64:ff9b::', 6to4 '2002::'); an attacker can wrap an internal " +
"IPv4 address in a transition literal to bypass it and reach internal endpoints."

View File

@@ -0,0 +1,14 @@
const isPrivate = require('private-ip');
const fetch = require('node-fetch');
// BAD: `private-ip` classifies the textual IPv4 form only, so it returns false
// for `::ffff:169.254.169.254`. The guard treats the wrapped internal address as
// public, but the request still reaches the metadata endpoint.
async function validateUrlHost(host) {
if (isPrivate(host)) {
throw new Error('blocked private host');
}
return fetch('http://' + host + '/');
}
module.exports = { validateUrlHost };

View File

@@ -0,0 +1,16 @@
const ipaddr = require('ipaddr.js');
const fetch = require('node-fetch');
// GOOD: ipaddr.js parses the host and classifies it with `.range()`, which is
// transition-aware. `::ffff:169.254.169.254` parses as an IPv4-mapped address and
// is reported in the `linkLocal` range, so the guard is complete.
async function validateTargetHost(host) {
const addr = ipaddr.parse(host);
const range = addr.range();
if (range === 'private' || range === 'loopback' || range === 'linkLocal') {
throw new Error('blocked internal host');
}
return fetch('http://' + host + '/');
}
module.exports = { validateTargetHost };

View File

@@ -0,0 +1,2 @@
| bad-private-ip-pkg.js:6:1:11:1 | async f ... '/');\\n} | This SSRF host guard rejects private IPv4 ranges but never unwraps IPv6-transition forms (IPv4-mapped '::ffff:', NAT64 '64:ff9b::', 6to4 '2002::'); an attacker can wrap an internal IPv4 address in a transition literal to bypass it and reach internal endpoints. |
| bad-rfc1918-regex.js:5:1:16:1 | functio ... '/');\\n} | This SSRF host guard rejects private IPv4 ranges but never unwraps IPv6-transition forms (IPv4-mapped '::ffff:', NAT64 '64:ff9b::', 6to4 '2002::'); an attacker can wrap an internal IPv4 address in a transition literal to bypass it and reach internal endpoints. |

View File

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

View File

@@ -0,0 +1,13 @@
const isPrivate = require('private-ip');
const fetch = require('node-fetch');
// BAD: `private-ip` classifies the textual IPv4 form only. It returns false for
// `::ffff:169.254.169.254`, so a transition-wrapped internal address slips past.
async function validateUrlHost(host) { // NOT OK
if (isPrivate(host)) {
throw new Error('blocked private host');
}
return fetch('http://' + host + '/');
}
module.exports = { validateUrlHost };

View File

@@ -0,0 +1,18 @@
const http = require('http');
// BAD: a hand-written RFC 1918 / loopback / metadata denylist matched against the
// host string. The embedded IPv4 inside `::ffff:10.0.0.1` is never seen.
function checkTargetHost(host) { // NOT OK
if (
host === '127.0.0.1' ||
host === '169.254.169.254' ||
host.startsWith('10.') ||
host.startsWith('192.168') ||
host.startsWith('172.16')
) {
throw new Error('blocked internal host');
}
return http.get('http://' + host + '/');
}
module.exports = { checkTargetHost };

View File

@@ -0,0 +1,32 @@
const http = require('http');
const IPV4_MAPPED_PREFIX = '::ffff:';
// OK: this guard uses a hand-rolled denylist, but it first unwraps the
// IPv6-transition form, so the embedded IPv4 is normalized before the check.
function unwrapMapped(host) {
// strip an IPv4-mapped `::ffff:` prefix down to the embedded dotted quad
if (host.toLowerCase().startsWith(IPV4_MAPPED_PREFIX)) {
return host.slice(IPV4_MAPPED_PREFIX.length);
}
return host;
}
function isPrivateAddress(host) { // OK
const h = unwrapMapped(host);
return (
h === '127.0.0.1' ||
h === '169.254.169.254' ||
h.startsWith('10.') ||
h.startsWith('192.168')
);
}
function validateHost(host) { // OK
if (isPrivateAddress(host)) {
throw new Error('blocked internal host');
}
return http.get('http://' + host + '/');
}
module.exports = { validateHost };

View File

@@ -0,0 +1,16 @@
const ipaddr = require('ipaddr.js');
const fetch = require('node-fetch');
// OK: ipaddr.js parses the address and classifies it with `.range()`, which is
// transition-aware. `::ffff:10.0.0.1` parses as an IPv4-mapped address and is
// reported in the `private` range, so the guard is complete.
async function validateTargetHost(host) { // OK
const addr = ipaddr.parse(host);
const range = addr.range();
if (range === 'private' || range === 'loopback' || range === 'linkLocal') {
throw new Error('blocked internal host');
}
return fetch('http://' + host + '/');
}
module.exports = { validateTargetHost };

View File

@@ -21,13 +21,19 @@ 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

View File

@@ -36,6 +36,8 @@ 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) {

View File

@@ -0,0 +1,4 @@
---
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.

View File

@@ -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, ContentSet c, Node nodeTo) {
predicate storeStepCommon(Node nodeFrom, Content c, Node nodeTo) {
tupleStoreStep(nodeFrom, c, nodeTo)
or
dictStoreStep(nodeFrom, c, nodeTo)
@@ -767,29 +767,31 @@ predicate storeStepCommon(Node nodeFrom, ContentSet c, Node nodeTo) {
* Holds if data can flow from `nodeFrom` to `nodeTo` via an assignment to
* content `c`.
*/
predicate storeStep(Node nodeFrom, ContentSet c, Node nodeTo) {
storeStepCommon(nodeFrom, c, nodeTo)
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)
)
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
FlowSummaryImpl::Private::Steps::summaryStoreStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), c,
FlowSummaryImpl::Private::Steps::summaryStoreStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), cs,
nodeTo.(FlowSummaryNode).getSummaryNode())
or
synthStarArgsElementParameterNodeStoreStep(nodeFrom, c, nodeTo)
or
synthDictSplatArgumentNodeStoreStep(nodeFrom, c, nodeTo)
or
yieldStoreStep(nodeFrom, c, nodeTo)
or
VariableCapture::storeStep(nodeFrom, c, nodeTo)
}
/**
@@ -985,7 +987,7 @@ predicate attributeStoreStep(Node nodeFrom, AttributeContent c, Node nodeTo) {
/**
* Subset of `readStep` that should be shared with type-tracking.
*/
predicate readStepCommon(Node nodeFrom, ContentSet c, Node nodeTo) {
predicate readStepCommon(Node nodeFrom, Content c, Node nodeTo) {
subscriptReadStep(nodeFrom, c, nodeTo)
or
iterableUnpackingReadStep(nodeFrom, c, nodeTo)
@@ -994,21 +996,25 @@ predicate readStepCommon(Node nodeFrom, ContentSet c, Node nodeTo) {
/**
* Holds if data can flow from `nodeFrom` to `nodeTo` via a read of content `c`.
*/
predicate readStep(Node nodeFrom, ContentSet c, Node nodeTo) {
readStepCommon(nodeFrom, c, nodeTo)
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)
)
or
matchReadStep(nodeFrom, c, nodeTo)
or
forReadStep(nodeFrom, c, nodeTo)
or
attributeReadStep(nodeFrom, c, nodeTo)
or
FlowSummaryImpl::Private::Steps::summaryReadStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), c,
FlowSummaryImpl::Private::Steps::summaryReadStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), cs,
nodeTo.(FlowSummaryNode).getSummaryNode())
or
synthDictSplatParameterNodeReadStep(nodeFrom, c, nodeTo)
or
VariableCapture::readStep(nodeFrom, c, nodeTo)
Conversions::readStep(nodeFrom, cs, nodeTo)
}
/** Data flows from a sequence to a subscript of the sequence. */
@@ -1064,23 +1070,68 @@ 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 c) {
matchClearStep(n, c)
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)
)
or
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)
FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(FlowSummaryNode).getSummaryNode(), cs)
}
/**
@@ -1198,12 +1249,65 @@ 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 = Unit;
class ContentApprox extends TContentApprox {
/** Gets a textual representation of this element. */
string toString() { result = "" }
}
/** Gets an approximated value for content `c`. */
pragma[inline]
ContentApprox getContentApprox(Content c) { any() }
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()
}
/** Helper for `.getEnclosingCallable`. */
DataFlowCallable getCallableScope(Scope s) {

View File

@@ -898,19 +898,78 @@ 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 instanceof Content {
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() }
/** Gets a content that may be stored into when storing into this set. */
Content getAStoreContent() { result = this }
Content getAStoreContent() { this = TSingletonContent(result) }
/** Gets a content that may be read from when reading from this set. */
Content getAReadContent() { result = this }
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
)
}
/** Gets a textual representation of this content set. */
string toString() { result = super.toString() }
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"
}
}
/** Gets the singleton `ContentSet` wrapping the `Content` `c`. */
ContentSet singleton(Content c) { result = TSingletonContent(c) }

View File

@@ -66,21 +66,29 @@ module Input implements InputSig<Location, DataFlowImplSpecific::PythonDataFlow>
}
string encodeContent(ContentSet cs, string arg) {
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()
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)
)
or
exists(string key |
cs = TDictionaryElementContent(key) and result = "DictionaryElement" and arg = key
)
cs.isAnyTupleElement() and result = "AnyTupleElement" and arg = ""
or
cs = TDictionaryElementAnyContent() and result = "DictionaryElementAny" and arg = ""
cs.isAnyDictionaryElement() and result = "AnyDictionaryElement" and arg = ""
or
exists(string attr | cs = TAttributeContent(attr) and result = "Attribute" and arg = attr)
cs.isAnyTupleOrDictionaryElement() and result = "AnyTupleOrDictionaryElement" and arg = ""
}
bindingset[token]
@@ -139,27 +147,29 @@ module Private {
predicate withContent = SC::withContent/1;
/** Gets a summary component that represents a list element. */
SummaryComponent listElement() { result = content(any(ListElementContent c)) }
SummaryComponent listElement() { result = content(singleton(any(ListElementContent c))) }
/** Gets a summary component that represents a set element. */
SummaryComponent setElement() { result = content(any(SetElementContent c)) }
SummaryComponent setElement() { result = content(singleton(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(c))
exists(TupleElementContent c | c.getIndex() = index and result = content(singleton(c)))
}
/** Gets a summary component that represents a dictionary element. */
SummaryComponent dictionaryElement(string key) {
exists(DictionaryElementContent c | c.getKey() = key and result = content(c))
exists(DictionaryElementContent c | c.getKey() = key and result = content(singleton(c)))
}
/** Gets a summary component that represents a dictionary element at any key. */
SummaryComponent dictionaryElementAny() { result = content(any(DictionaryElementAnyContent c)) }
SummaryComponent dictionaryElementAny() {
result = content(singleton(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(c))
exists(AttributeContent c | c.getAttribute() = attr and result = content(singleton(c)))
}
/** Gets a summary component that represents the return value of a call. */

View File

@@ -9,19 +9,7 @@ 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
/**
* 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
}
private import semmle.python.essa.SsaDefinitions
/**
* Python modules and the way imports are resolved are... complicated. Here's a crash course in how
@@ -338,7 +326,7 @@ module ImportResolution {
// imported yet.
exists(string submodule, Module package, EssaVariable var |
submodule = var.getName() and
initModuleSubmoduleDefn(var.getSourceVariable(), package) and
SsaSource::init_module_submodule_defn(var.getSourceVariable(), package.getEntryNode()) and
m = getModuleFromName(package.getPackageName() + "." + submodule) and
result.asCfgNode() = var.getDefinition().(EssaNodeDefinition).getDefiningNode()
)

View File

@@ -11,12 +11,34 @@ 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) { none() }
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) {
exists(node) and
defaultTaintReadContent(c)
}
private module Cached {
/**
@@ -128,11 +150,6 @@ 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)
@@ -161,32 +178,21 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT
}
/**
* 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.
* 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.
*/
predicate containerStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
// 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)
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
)
)
}
/**

View File

@@ -241,7 +241,7 @@ module TypeTrackingInput implements Shared::TypeTrackingInput<Location> {
// is only fed set/list content)
not nodeFrom instanceof DataFlowPublic::IterableElementNode
or
TypeTrackerSummaryFlow::basicStoreStep(nodeFrom, nodeTo, content)
TypeTrackerSummaryFlow::basicStoreStep(nodeFrom, nodeTo, DataFlowPublic::singleton(content))
}
/**
@@ -272,14 +272,15 @@ module TypeTrackingInput implements Shared::TypeTrackingInput<Location> {
nodeFrom.asCfgNode() instanceof SequenceNode
)
or
TypeTrackerSummaryFlow::basicLoadStep(nodeFrom, nodeTo, content)
TypeTrackerSummaryFlow::basicLoadStep(nodeFrom, nodeTo, DataFlowPublic::singleton(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, loadContent, storeContent)
TypeTrackerSummaryFlow::basicLoadStoreStep(nodeFrom, nodeTo,
DataFlowPublic::singleton(loadContent), DataFlowPublic::singleton(storeContent))
}
/**

View File

@@ -4244,6 +4244,7 @@ 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
@@ -4270,11 +4271,9 @@ module StdlibPrivate {
preservesValue = true
)
or
// TODO: We need to also translate iterable content such as list element
// but we currently lack TupleElementAny
input = "Argument[0]" and
input = "Argument[0].ListElement" and
output = "ReturnValue" and
preservesValue = false
preservesValue = true
}
}
@@ -4969,6 +4968,26 @@ 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
// ---------------------------------------------------------------------------

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/python-all
extensible: summaryModel
data:
- ['lxml', 'Member[etree].Member[fromstringlist]', 'Argument[0,strings:].ListElement', 'ReturnValue', 'taint']

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/python-all
extensible: summaryModel
data:
- ['xml', 'Member[etree].Member[fromstringlist]', 'Argument[0,strings:].ListElement', 'ReturnValue', 'taint']

View File

@@ -61,10 +61,11 @@ module EscapingCaptureFlowConfig implements DataFlow::ConfigSig {
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet cs) {
isSink(node) and
(
cs.(DataFlow::TupleElementContent).getIndex() in [0 .. 10] or
cs instanceof DataFlow::ListElementContent or
cs instanceof DataFlow::SetElementContent or
cs instanceof DataFlow::DictionaryElementAnyContent
cs.isAnyTupleOrDictionaryElement()
or
cs.getAStoreContent() instanceof DataFlow::ListElementContent
or
cs.getAStoreContent() instanceof DataFlow::SetElementContent
)
}
}

View File

@@ -3,11 +3,15 @@ edges
| TarSlipImprov.py:15:7:15:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:15:1:15:3 | ControlFlowNode for tar | provenance | |
| TarSlipImprov.py:17:5:17:10 | ControlFlowNode for member | TarSlipImprov.py:20:19:20:24 | ControlFlowNode for member | provenance | |
| TarSlipImprov.py:20:5:20:10 | [post] ControlFlowNode for result | TarSlipImprov.py:22:35:22:40 | ControlFlowNode for result | provenance | |
| TarSlipImprov.py:20:5:20:10 | [post] ControlFlowNode for result [List element] | TarSlipImprov.py:22:35:22:40 | ControlFlowNode for result | provenance | |
| TarSlipImprov.py:20:19:20:24 | ControlFlowNode for member | TarSlipImprov.py:20:5:20:10 | [post] ControlFlowNode for result | provenance | list.append |
| TarSlipImprov.py:20:19:20:24 | ControlFlowNode for member | TarSlipImprov.py:20:5:20:10 | [post] ControlFlowNode for result [List element] | provenance | list.append |
| TarSlipImprov.py:26:21:26:27 | ControlFlowNode for tarfile | TarSlipImprov.py:28:9:28:14 | ControlFlowNode for member | provenance | |
| TarSlipImprov.py:28:9:28:14 | ControlFlowNode for member | TarSlipImprov.py:35:23:35:28 | ControlFlowNode for member | provenance | |
| TarSlipImprov.py:35:9:35:14 | [post] ControlFlowNode for result | TarSlipImprov.py:36:12:36:17 | ControlFlowNode for result | provenance | |
| TarSlipImprov.py:35:9:35:14 | [post] ControlFlowNode for result [List element] | TarSlipImprov.py:36:12:36:17 | ControlFlowNode for result [List element] | provenance | |
| TarSlipImprov.py:35:23:35:28 | ControlFlowNode for member | TarSlipImprov.py:35:9:35:14 | [post] ControlFlowNode for result | provenance | list.append |
| TarSlipImprov.py:35:23:35:28 | ControlFlowNode for member | TarSlipImprov.py:35:9:35:14 | [post] ControlFlowNode for result [List element] | provenance | list.append |
| TarSlipImprov.py:38:1:38:3 | ControlFlowNode for tar | TarSlipImprov.py:39:65:39:67 | ControlFlowNode for tar | provenance | |
| TarSlipImprov.py:38:7:38:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:38:1:38:3 | ControlFlowNode for tar | provenance | |
| TarSlipImprov.py:39:65:39:67 | ControlFlowNode for tar | TarSlipImprov.py:26:21:26:27 | ControlFlowNode for tarfile | provenance | |
@@ -34,16 +38,19 @@ edges
| TarSlipImprov.py:142:9:142:13 | ControlFlowNode for entry | TarSlipImprov.py:143:36:143:40 | ControlFlowNode for entry | provenance | |
| TarSlipImprov.py:151:14:151:50 | ControlFlowNode for closing() | TarSlipImprov.py:151:55:151:56 | ControlFlowNode for tf | provenance | |
| TarSlipImprov.py:151:22:151:49 | ControlFlowNode for Attribute() | TarSlipImprov.py:151:14:151:50 | ControlFlowNode for closing() | provenance | Config |
| TarSlipImprov.py:151:55:151:56 | ControlFlowNode for tf | TarSlipImprov.py:152:13:152:20 | ControlFlowNode for Yield | provenance | |
| TarSlipImprov.py:151:55:151:56 | ControlFlowNode for tf | TarSlipImprov.py:152:19:152:20 | ControlFlowNode for tf | provenance | |
| TarSlipImprov.py:152:13:152:20 | ControlFlowNode for Yield | TarSlipImprov.py:157:18:157:40 | ControlFlowNode for py2_tarxz() | provenance | |
| TarSlipImprov.py:152:13:152:20 | ControlFlowNode for Yield [List element] | TarSlipImprov.py:157:18:157:40 | ControlFlowNode for py2_tarxz() [List element] | provenance | |
| TarSlipImprov.py:152:19:152:20 | ControlFlowNode for tf | TarSlipImprov.py:152:13:152:20 | ControlFlowNode for Yield [List element] | provenance | |
| TarSlipImprov.py:152:19:152:20 | ControlFlowNode for tf | TarSlipImprov.py:157:18:157:40 | ControlFlowNode for py2_tarxz() | provenance | |
| TarSlipImprov.py:157:9:157:14 | ControlFlowNode for tar_cm | TarSlipImprov.py:162:20:162:23 | ControlFlowNode for tarc | provenance | |
| TarSlipImprov.py:157:9:157:14 | ControlFlowNode for tar_cm [List element] | TarSlipImprov.py:162:20:162:23 | ControlFlowNode for tarc [List element] | provenance | |
| TarSlipImprov.py:157:18:157:40 | ControlFlowNode for py2_tarxz() | TarSlipImprov.py:157:9:157:14 | ControlFlowNode for tar_cm | provenance | |
| TarSlipImprov.py:157:18:157:40 | ControlFlowNode for py2_tarxz() [List element] | TarSlipImprov.py:157:9:157:14 | ControlFlowNode for tar_cm [List element] | provenance | |
| TarSlipImprov.py:159:9:159:14 | ControlFlowNode for tar_cm | TarSlipImprov.py:162:20:162:23 | ControlFlowNode for tarc | provenance | |
| TarSlipImprov.py:159:18:159:52 | ControlFlowNode for closing() | TarSlipImprov.py:159:9:159:14 | ControlFlowNode for tar_cm | provenance | |
| TarSlipImprov.py:159:26:159:51 | ControlFlowNode for Attribute() | TarSlipImprov.py:159:18:159:52 | ControlFlowNode for closing() | provenance | Config |
| TarSlipImprov.py:162:20:162:23 | ControlFlowNode for tarc | TarSlipImprov.py:169:9:169:12 | ControlFlowNode for tarc | provenance | |
| TarSlipImprov.py:162:20:162:23 | ControlFlowNode for tarc [List element] | TarSlipImprov.py:169:9:169:12 | ControlFlowNode for tarc | provenance | |
| TarSlipImprov.py:176:6:176:31 | ControlFlowNode for Attribute() | TarSlipImprov.py:176:36:176:38 | ControlFlowNode for tar | provenance | |
| TarSlipImprov.py:176:36:176:38 | ControlFlowNode for tar | TarSlipImprov.py:177:9:177:13 | ControlFlowNode for entry | provenance | |
| TarSlipImprov.py:177:9:177:13 | ControlFlowNode for entry | TarSlipImprov.py:178:36:178:40 | ControlFlowNode for entry | provenance | |
@@ -60,7 +67,9 @@ edges
| TarSlipImprov.py:231:43:231:52 | ControlFlowNode for corpus_tar | TarSlipImprov.py:233:9:233:9 | ControlFlowNode for f | provenance | |
| TarSlipImprov.py:233:9:233:9 | ControlFlowNode for f | TarSlipImprov.py:235:28:235:28 | ControlFlowNode for f | provenance | |
| TarSlipImprov.py:235:13:235:19 | [post] ControlFlowNode for members | TarSlipImprov.py:236:44:236:50 | ControlFlowNode for members | provenance | |
| TarSlipImprov.py:235:13:235:19 | [post] ControlFlowNode for members [List element] | TarSlipImprov.py:236:44:236:50 | ControlFlowNode for members | provenance | |
| TarSlipImprov.py:235:28:235:28 | ControlFlowNode for f | TarSlipImprov.py:235:13:235:19 | [post] ControlFlowNode for members | provenance | list.append |
| TarSlipImprov.py:235:28:235:28 | ControlFlowNode for f | TarSlipImprov.py:235:13:235:19 | [post] ControlFlowNode for members [List element] | provenance | list.append |
| TarSlipImprov.py:258:6:258:26 | ControlFlowNode for Attribute() | TarSlipImprov.py:258:31:258:33 | ControlFlowNode for tar | provenance | |
| TarSlipImprov.py:258:31:258:33 | ControlFlowNode for tar | TarSlipImprov.py:259:9:259:13 | ControlFlowNode for entry | provenance | |
| TarSlipImprov.py:259:9:259:13 | ControlFlowNode for entry | TarSlipImprov.py:261:25:261:29 | ControlFlowNode for entry | provenance | |
@@ -85,19 +94,24 @@ edges
| TarSlipImprov.py:304:7:304:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:304:1:304:3 | ControlFlowNode for tar | provenance | |
| TarSlipImprov.py:306:5:306:10 | ControlFlowNode for member | TarSlipImprov.py:309:19:309:24 | ControlFlowNode for member | provenance | |
| TarSlipImprov.py:309:5:309:10 | [post] ControlFlowNode for result | TarSlipImprov.py:310:49:310:54 | ControlFlowNode for result | provenance | |
| TarSlipImprov.py:309:5:309:10 | [post] ControlFlowNode for result [List element] | TarSlipImprov.py:310:49:310:54 | ControlFlowNode for result | provenance | |
| TarSlipImprov.py:309:19:309:24 | ControlFlowNode for member | TarSlipImprov.py:309:5:309:10 | [post] ControlFlowNode for result | provenance | list.append |
| TarSlipImprov.py:309:19:309:24 | ControlFlowNode for member | TarSlipImprov.py:309:5:309:10 | [post] ControlFlowNode for result [List element] | provenance | list.append |
nodes
| TarSlipImprov.py:15:1:15:3 | ControlFlowNode for tar | semmle.label | ControlFlowNode for tar |
| TarSlipImprov.py:15:7:15:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| TarSlipImprov.py:17:5:17:10 | ControlFlowNode for member | semmle.label | ControlFlowNode for member |
| TarSlipImprov.py:20:5:20:10 | [post] ControlFlowNode for result | semmle.label | [post] ControlFlowNode for result |
| TarSlipImprov.py:20:5:20:10 | [post] ControlFlowNode for result [List element] | semmle.label | [post] ControlFlowNode for result [List element] |
| TarSlipImprov.py:20:19:20:24 | ControlFlowNode for member | semmle.label | ControlFlowNode for member |
| TarSlipImprov.py:22:35:22:40 | ControlFlowNode for result | semmle.label | ControlFlowNode for result |
| TarSlipImprov.py:26:21:26:27 | ControlFlowNode for tarfile | semmle.label | ControlFlowNode for tarfile |
| TarSlipImprov.py:28:9:28:14 | ControlFlowNode for member | semmle.label | ControlFlowNode for member |
| TarSlipImprov.py:35:9:35:14 | [post] ControlFlowNode for result | semmle.label | [post] ControlFlowNode for result |
| TarSlipImprov.py:35:9:35:14 | [post] ControlFlowNode for result [List element] | semmle.label | [post] ControlFlowNode for result [List element] |
| TarSlipImprov.py:35:23:35:28 | ControlFlowNode for member | semmle.label | ControlFlowNode for member |
| TarSlipImprov.py:36:12:36:17 | ControlFlowNode for result | semmle.label | ControlFlowNode for result |
| TarSlipImprov.py:36:12:36:17 | ControlFlowNode for result [List element] | semmle.label | ControlFlowNode for result [List element] |
| TarSlipImprov.py:38:1:38:3 | ControlFlowNode for tar | semmle.label | ControlFlowNode for tar |
| TarSlipImprov.py:38:7:38:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| TarSlipImprov.py:39:49:39:68 | ControlFlowNode for members_filter1() | semmle.label | ControlFlowNode for members_filter1() |
@@ -133,14 +147,17 @@ nodes
| TarSlipImprov.py:151:14:151:50 | ControlFlowNode for closing() | semmle.label | ControlFlowNode for closing() |
| TarSlipImprov.py:151:22:151:49 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| TarSlipImprov.py:151:55:151:56 | ControlFlowNode for tf | semmle.label | ControlFlowNode for tf |
| TarSlipImprov.py:152:13:152:20 | ControlFlowNode for Yield | semmle.label | ControlFlowNode for Yield |
| TarSlipImprov.py:152:13:152:20 | ControlFlowNode for Yield [List element] | semmle.label | ControlFlowNode for Yield [List element] |
| TarSlipImprov.py:152:19:152:20 | ControlFlowNode for tf | semmle.label | ControlFlowNode for tf |
| TarSlipImprov.py:157:9:157:14 | ControlFlowNode for tar_cm | semmle.label | ControlFlowNode for tar_cm |
| TarSlipImprov.py:157:9:157:14 | ControlFlowNode for tar_cm [List element] | semmle.label | ControlFlowNode for tar_cm [List element] |
| TarSlipImprov.py:157:18:157:40 | ControlFlowNode for py2_tarxz() | semmle.label | ControlFlowNode for py2_tarxz() |
| TarSlipImprov.py:157:18:157:40 | ControlFlowNode for py2_tarxz() [List element] | semmle.label | ControlFlowNode for py2_tarxz() [List element] |
| TarSlipImprov.py:159:9:159:14 | ControlFlowNode for tar_cm | semmle.label | ControlFlowNode for tar_cm |
| TarSlipImprov.py:159:18:159:52 | ControlFlowNode for closing() | semmle.label | ControlFlowNode for closing() |
| TarSlipImprov.py:159:26:159:51 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| TarSlipImprov.py:162:20:162:23 | ControlFlowNode for tarc | semmle.label | ControlFlowNode for tarc |
| TarSlipImprov.py:162:20:162:23 | ControlFlowNode for tarc [List element] | semmle.label | ControlFlowNode for tarc [List element] |
| TarSlipImprov.py:169:9:169:12 | ControlFlowNode for tarc | semmle.label | ControlFlowNode for tarc |
| TarSlipImprov.py:176:6:176:31 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| TarSlipImprov.py:176:36:176:38 | ControlFlowNode for tar | semmle.label | ControlFlowNode for tar |
@@ -163,6 +180,7 @@ nodes
| TarSlipImprov.py:231:43:231:52 | ControlFlowNode for corpus_tar | semmle.label | ControlFlowNode for corpus_tar |
| TarSlipImprov.py:233:9:233:9 | ControlFlowNode for f | semmle.label | ControlFlowNode for f |
| TarSlipImprov.py:235:13:235:19 | [post] ControlFlowNode for members | semmle.label | [post] ControlFlowNode for members |
| TarSlipImprov.py:235:13:235:19 | [post] ControlFlowNode for members [List element] | semmle.label | [post] ControlFlowNode for members [List element] |
| TarSlipImprov.py:235:28:235:28 | ControlFlowNode for f | semmle.label | ControlFlowNode for f |
| TarSlipImprov.py:236:44:236:50 | ControlFlowNode for members | semmle.label | ControlFlowNode for members |
| TarSlipImprov.py:254:1:254:31 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
@@ -198,11 +216,13 @@ nodes
| TarSlipImprov.py:304:7:304:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| TarSlipImprov.py:306:5:306:10 | ControlFlowNode for member | semmle.label | ControlFlowNode for member |
| TarSlipImprov.py:309:5:309:10 | [post] ControlFlowNode for result | semmle.label | [post] ControlFlowNode for result |
| TarSlipImprov.py:309:5:309:10 | [post] ControlFlowNode for result [List element] | semmle.label | [post] ControlFlowNode for result [List element] |
| TarSlipImprov.py:309:19:309:24 | ControlFlowNode for member | semmle.label | ControlFlowNode for member |
| TarSlipImprov.py:310:49:310:54 | ControlFlowNode for result | semmle.label | ControlFlowNode for result |
| TarSlipImprov.py:316:1:316:46 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
subpaths
| TarSlipImprov.py:39:65:39:67 | ControlFlowNode for tar | TarSlipImprov.py:26:21:26:27 | ControlFlowNode for tarfile | TarSlipImprov.py:36:12:36:17 | ControlFlowNode for result | TarSlipImprov.py:39:49:39:68 | ControlFlowNode for members_filter1() |
| TarSlipImprov.py:39:65:39:67 | ControlFlowNode for tar | TarSlipImprov.py:26:21:26:27 | ControlFlowNode for tarfile | TarSlipImprov.py:36:12:36:17 | ControlFlowNode for result [List element] | TarSlipImprov.py:39:49:39:68 | ControlFlowNode for members_filter1() |
#select
| TarSlipImprov.py:22:35:22:40 | ControlFlowNode for result | TarSlipImprov.py:15:7:15:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:22:35:22:40 | ControlFlowNode for result | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:15:7:15:39 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:22:35:22:40 | ControlFlowNode for result | ControlFlowNode for result |
| TarSlipImprov.py:39:49:39:68 | ControlFlowNode for members_filter1() | TarSlipImprov.py:38:7:38:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:39:49:39:68 | ControlFlowNode for members_filter1() | Extraction of tarfile from $@ to a potentially untrusted source $@. | TarSlipImprov.py:38:7:38:39 | ControlFlowNode for Attribute() | ControlFlowNode for Attribute() | TarSlipImprov.py:39:49:39:68 | ControlFlowNode for members_filter1() | ControlFlowNode for members_filter1() |

View File

@@ -93,7 +93,9 @@ edges
| UnsafeUnpack.py:163:23:163:28 | ControlFlowNode for member | UnsafeUnpack.py:166:37:166:42 | ControlFlowNode for member | provenance | |
| UnsafeUnpack.py:163:33:163:35 | ControlFlowNode for tar | UnsafeUnpack.py:163:23:163:28 | ControlFlowNode for member | provenance | |
| UnsafeUnpack.py:166:23:166:28 | [post] ControlFlowNode for result | UnsafeUnpack.py:167:67:167:72 | ControlFlowNode for result | provenance | |
| UnsafeUnpack.py:166:23:166:28 | [post] ControlFlowNode for result [List element] | UnsafeUnpack.py:167:67:167:72 | ControlFlowNode for result | provenance | |
| UnsafeUnpack.py:166:37:166:42 | ControlFlowNode for member | UnsafeUnpack.py:166:23:166:28 | [post] ControlFlowNode for result | provenance | list.append |
| UnsafeUnpack.py:166:37:166:42 | ControlFlowNode for member | UnsafeUnpack.py:166:23:166:28 | [post] ControlFlowNode for result [List element] | provenance | list.append |
| UnsafeUnpack.py:171:1:171:8 | ControlFlowNode for response | UnsafeUnpack.py:174:15:174:22 | ControlFlowNode for response | provenance | |
| UnsafeUnpack.py:171:12:171:50 | ControlFlowNode for Attribute() | UnsafeUnpack.py:171:1:171:8 | ControlFlowNode for response | provenance | |
| UnsafeUnpack.py:173:11:173:17 | ControlFlowNode for tarpath | UnsafeUnpack.py:176:17:176:23 | ControlFlowNode for tarpath | provenance | |
@@ -189,6 +191,7 @@ nodes
| UnsafeUnpack.py:163:23:163:28 | ControlFlowNode for member | semmle.label | ControlFlowNode for member |
| UnsafeUnpack.py:163:33:163:35 | ControlFlowNode for tar | semmle.label | ControlFlowNode for tar |
| UnsafeUnpack.py:166:23:166:28 | [post] ControlFlowNode for result | semmle.label | [post] ControlFlowNode for result |
| UnsafeUnpack.py:166:23:166:28 | [post] ControlFlowNode for result [List element] | semmle.label | [post] ControlFlowNode for result [List element] |
| UnsafeUnpack.py:166:37:166:42 | ControlFlowNode for member | semmle.label | ControlFlowNode for member |
| UnsafeUnpack.py:167:67:167:72 | ControlFlowNode for result | semmle.label | ControlFlowNode for result |
| UnsafeUnpack.py:171:1:171:8 | ControlFlowNode for response | semmle.label | ControlFlowNode for response |

View File

@@ -3,8 +3,10 @@ edges
| Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | Netmiko.py:20:45:20:47 | ControlFlowNode for cmd | provenance | |
| Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | Netmiko.py:21:52:21:54 | ControlFlowNode for cmd | provenance | |
| Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | Netmiko.py:22:52:22:54 | ControlFlowNode for cmd | provenance | |
| Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | Netmiko.py:23:41:23:57 | ControlFlowNode for List | provenance | |
| Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | Netmiko.py:23:43:23:45 | ControlFlowNode for cmd | provenance | |
| Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | Netmiko.py:24:48:24:50 | ControlFlowNode for cmd | provenance | |
| Netmiko.py:23:42:23:56 | ControlFlowNode for List [List element] | Netmiko.py:23:41:23:57 | ControlFlowNode for List | provenance | |
| Netmiko.py:23:43:23:45 | ControlFlowNode for cmd | Netmiko.py:23:42:23:56 | ControlFlowNode for List [List element] | provenance | |
| Pexpect.py:15:16:15:18 | ControlFlowNode for cmd | Pexpect.py:16:14:16:16 | ControlFlowNode for cmd | provenance | |
| Pexpect.py:15:16:15:18 | ControlFlowNode for cmd | Pexpect.py:18:18:18:20 | ControlFlowNode for cmd | provenance | |
| Scrapli.py:13:16:13:18 | ControlFlowNode for cmd | Scrapli.py:24:42:24:44 | ControlFlowNode for cmd | provenance | |
@@ -32,6 +34,8 @@ nodes
| Netmiko.py:21:52:21:54 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
| Netmiko.py:22:52:22:54 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
| Netmiko.py:23:41:23:57 | ControlFlowNode for List | semmle.label | ControlFlowNode for List |
| Netmiko.py:23:42:23:56 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| Netmiko.py:23:43:23:45 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
| Netmiko.py:24:48:24:50 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
| Pexpect.py:15:16:15:18 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
| Pexpect.py:16:14:16:16 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |

View File

@@ -7,6 +7,7 @@ edges
| xslt.py:10:17:10:43 | ControlFlowNode for Attribute() | xslt.py:10:5:10:13 | ControlFlowNode for xsltQuery | provenance | |
| xslt.py:11:5:11:13 | ControlFlowNode for xslt_root | xslt.py:14:29:14:37 | ControlFlowNode for xslt_root | provenance | |
| xslt.py:11:17:11:36 | ControlFlowNode for Attribute() | xslt.py:11:5:11:13 | ControlFlowNode for xslt_root | provenance | |
| xslt.py:11:27:11:35 | ControlFlowNode for xsltQuery | xslt.py:11:17:11:36 | ControlFlowNode for Attribute() | provenance | |
| xslt.py:11:27:11:35 | ControlFlowNode for xsltQuery | xslt.py:11:17:11:36 | ControlFlowNode for Attribute() | provenance | Config |
| xslt.py:11:27:11:35 | ControlFlowNode for xsltQuery | xslt.py:11:17:11:36 | ControlFlowNode for Attribute() | provenance | Decoding-XML |
| xsltInjection.py:3:26:3:32 | ControlFlowNode for ImportMember | xsltInjection.py:3:26:3:32 | ControlFlowNode for request | provenance | |
@@ -21,6 +22,7 @@ edges
| xsltInjection.py:10:17:10:43 | ControlFlowNode for Attribute() | xsltInjection.py:10:5:10:13 | ControlFlowNode for xsltQuery | provenance | |
| xsltInjection.py:11:5:11:13 | ControlFlowNode for xslt_root | xsltInjection.py:12:28:12:36 | ControlFlowNode for xslt_root | provenance | |
| xsltInjection.py:11:17:11:36 | ControlFlowNode for Attribute() | xsltInjection.py:11:5:11:13 | ControlFlowNode for xslt_root | provenance | |
| xsltInjection.py:11:27:11:35 | ControlFlowNode for xsltQuery | xsltInjection.py:11:17:11:36 | ControlFlowNode for Attribute() | provenance | |
| xsltInjection.py:11:27:11:35 | ControlFlowNode for xsltQuery | xsltInjection.py:11:17:11:36 | ControlFlowNode for Attribute() | provenance | Config |
| xsltInjection.py:11:27:11:35 | ControlFlowNode for xsltQuery | xsltInjection.py:11:17:11:36 | ControlFlowNode for Attribute() | provenance | Decoding-XML |
| xsltInjection.py:17:5:17:13 | ControlFlowNode for xsltQuery | xsltInjection.py:18:27:18:35 | ControlFlowNode for xsltQuery | provenance | |
@@ -29,6 +31,7 @@ edges
| xsltInjection.py:17:17:17:43 | ControlFlowNode for Attribute() | xsltInjection.py:17:5:17:13 | ControlFlowNode for xsltQuery | provenance | |
| xsltInjection.py:18:5:18:13 | ControlFlowNode for xslt_root | xsltInjection.py:21:29:21:37 | ControlFlowNode for xslt_root | provenance | |
| xsltInjection.py:18:17:18:36 | ControlFlowNode for Attribute() | xsltInjection.py:18:5:18:13 | ControlFlowNode for xslt_root | provenance | |
| xsltInjection.py:18:27:18:35 | ControlFlowNode for xsltQuery | xsltInjection.py:18:17:18:36 | ControlFlowNode for Attribute() | provenance | |
| xsltInjection.py:18:27:18:35 | ControlFlowNode for xsltQuery | xsltInjection.py:18:17:18:36 | ControlFlowNode for Attribute() | provenance | Config |
| xsltInjection.py:18:27:18:35 | ControlFlowNode for xsltQuery | xsltInjection.py:18:17:18:36 | ControlFlowNode for Attribute() | provenance | Decoding-XML |
| xsltInjection.py:26:5:26:13 | ControlFlowNode for xsltQuery | xsltInjection.py:27:27:27:35 | ControlFlowNode for xsltQuery | provenance | |
@@ -37,6 +40,7 @@ edges
| xsltInjection.py:26:17:26:43 | ControlFlowNode for Attribute() | xsltInjection.py:26:5:26:13 | ControlFlowNode for xsltQuery | provenance | |
| xsltInjection.py:27:5:27:13 | ControlFlowNode for xslt_root | xsltInjection.py:31:24:31:32 | ControlFlowNode for xslt_root | provenance | |
| xsltInjection.py:27:17:27:36 | ControlFlowNode for Attribute() | xsltInjection.py:27:5:27:13 | ControlFlowNode for xslt_root | provenance | |
| xsltInjection.py:27:27:27:35 | ControlFlowNode for xsltQuery | xsltInjection.py:27:17:27:36 | ControlFlowNode for Attribute() | provenance | |
| xsltInjection.py:27:27:27:35 | ControlFlowNode for xsltQuery | xsltInjection.py:27:17:27:36 | ControlFlowNode for Attribute() | provenance | Config |
| xsltInjection.py:27:27:27:35 | ControlFlowNode for xsltQuery | xsltInjection.py:27:17:27:36 | ControlFlowNode for Attribute() | provenance | Decoding-XML |
| xsltInjection.py:35:5:35:13 | ControlFlowNode for xsltQuery | xsltInjection.py:36:34:36:42 | ControlFlowNode for xsltQuery | provenance | |
@@ -45,17 +49,22 @@ edges
| xsltInjection.py:35:17:35:43 | ControlFlowNode for Attribute() | xsltInjection.py:35:5:35:13 | ControlFlowNode for xsltQuery | provenance | |
| xsltInjection.py:36:5:36:13 | ControlFlowNode for xslt_root | xsltInjection.py:40:24:40:32 | ControlFlowNode for xslt_root | provenance | |
| xsltInjection.py:36:17:36:43 | ControlFlowNode for Attribute() | xsltInjection.py:36:5:36:13 | ControlFlowNode for xslt_root | provenance | |
| xsltInjection.py:36:34:36:42 | ControlFlowNode for xsltQuery | xsltInjection.py:36:17:36:43 | ControlFlowNode for Attribute() | provenance | |
| xsltInjection.py:36:34:36:42 | ControlFlowNode for xsltQuery | xsltInjection.py:36:17:36:43 | ControlFlowNode for Attribute() | provenance | Config |
| xsltInjection.py:36:34:36:42 | ControlFlowNode for xsltQuery | xsltInjection.py:36:17:36:43 | ControlFlowNode for Attribute() | provenance | Decoding-XML |
| xsltInjection.py:44:5:44:13 | ControlFlowNode for xsltQuery | xsltInjection.py:45:5:45:15 | ControlFlowNode for xsltStrings | provenance | |
| xsltInjection.py:44:5:44:13 | ControlFlowNode for xsltQuery | xsltInjection.py:45:20:45:28 | ControlFlowNode for xsltQuery | provenance | |
| xsltInjection.py:44:17:44:23 | ControlFlowNode for request | xsltInjection.py:44:17:44:28 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep |
| xsltInjection.py:44:17:44:28 | ControlFlowNode for Attribute | xsltInjection.py:44:17:44:43 | ControlFlowNode for Attribute() | provenance | dict.get |
| xsltInjection.py:44:17:44:43 | ControlFlowNode for Attribute() | xsltInjection.py:44:5:44:13 | ControlFlowNode for xsltQuery | provenance | |
| xsltInjection.py:45:5:45:15 | ControlFlowNode for xsltStrings | xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings | provenance | |
| xsltInjection.py:45:5:45:15 | ControlFlowNode for xsltStrings [List element] | xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings [List element] | provenance | |
| xsltInjection.py:45:19:45:44 | ControlFlowNode for List [List element] | xsltInjection.py:45:5:45:15 | ControlFlowNode for xsltStrings [List element] | provenance | |
| xsltInjection.py:45:20:45:28 | ControlFlowNode for xsltQuery | xsltInjection.py:45:19:45:44 | ControlFlowNode for List [List element] | provenance | |
| xsltInjection.py:46:5:46:13 | ControlFlowNode for xslt_root | xsltInjection.py:50:24:50:32 | ControlFlowNode for xslt_root | provenance | |
| xsltInjection.py:46:17:46:49 | ControlFlowNode for Attribute() | xsltInjection.py:46:5:46:13 | ControlFlowNode for xslt_root | provenance | |
| xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings | xsltInjection.py:46:17:46:49 | ControlFlowNode for Attribute() | provenance | Config |
| xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings | xsltInjection.py:46:17:46:49 | ControlFlowNode for Attribute() | provenance | Decoding-XML |
| xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings [List element] | xsltInjection.py:46:17:46:49 | ControlFlowNode for Attribute() | provenance | |
| xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings [List element] | xsltInjection.py:46:17:46:49 | ControlFlowNode for Attribute() | provenance | Config |
| xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings [List element] | xsltInjection.py:46:17:46:49 | ControlFlowNode for Attribute() | provenance | Decoding-XML |
| xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings [List element] | xsltInjection.py:46:17:46:49 | ControlFlowNode for Attribute() | provenance | MaD:58660 |
nodes
| xslt.py:3:26:3:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
| xslt.py:3:26:3:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
@@ -105,10 +114,12 @@ nodes
| xsltInjection.py:44:17:44:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| xsltInjection.py:44:17:44:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| xsltInjection.py:44:17:44:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| xsltInjection.py:45:5:45:15 | ControlFlowNode for xsltStrings | semmle.label | ControlFlowNode for xsltStrings |
| xsltInjection.py:45:5:45:15 | ControlFlowNode for xsltStrings [List element] | semmle.label | ControlFlowNode for xsltStrings [List element] |
| xsltInjection.py:45:19:45:44 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| xsltInjection.py:45:20:45:28 | ControlFlowNode for xsltQuery | semmle.label | ControlFlowNode for xsltQuery |
| xsltInjection.py:46:5:46:13 | ControlFlowNode for xslt_root | semmle.label | ControlFlowNode for xslt_root |
| xsltInjection.py:46:17:46:49 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings | semmle.label | ControlFlowNode for xsltStrings |
| xsltInjection.py:46:38:46:48 | ControlFlowNode for xsltStrings [List element] | semmle.label | ControlFlowNode for xsltStrings [List element] |
| xsltInjection.py:50:24:50:32 | ControlFlowNode for xslt_root | semmle.label | ControlFlowNode for xslt_root |
subpaths
#select

View File

@@ -32,11 +32,13 @@ edges
| agent_instructions.py:7:5:7:9 | ControlFlowNode for input | agent_instructions.py:9:50:9:89 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:11 |
| agent_instructions.py:7:13:7:19 | ControlFlowNode for request | agent_instructions.py:7:13:7:24 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep |
| agent_instructions.py:7:13:7:24 | ControlFlowNode for Attribute | agent_instructions.py:7:13:7:37 | ControlFlowNode for Attribute() | provenance | dict.get |
| agent_instructions.py:7:13:7:24 | ControlFlowNode for Attribute | agent_instructions.py:7:13:7:37 | ControlFlowNode for Attribute() | provenance | dict.get(input) |
| agent_instructions.py:7:13:7:37 | ControlFlowNode for Attribute() | agent_instructions.py:7:5:7:9 | ControlFlowNode for input | provenance | |
| agent_instructions.py:17:5:17:9 | ControlFlowNode for input | agent_instructions.py:25:28:25:32 | ControlFlowNode for input | provenance | |
| agent_instructions.py:17:5:17:9 | ControlFlowNode for input | agent_instructions.py:35:28:35:32 | ControlFlowNode for input | provenance | |
| agent_instructions.py:17:13:17:19 | ControlFlowNode for request | agent_instructions.py:17:13:17:24 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep |
| agent_instructions.py:17:13:17:24 | ControlFlowNode for Attribute | agent_instructions.py:17:13:17:37 | ControlFlowNode for Attribute() | provenance | dict.get |
| agent_instructions.py:17:13:17:24 | ControlFlowNode for Attribute | agent_instructions.py:17:13:17:37 | ControlFlowNode for Attribute() | provenance | dict.get(input) |
| agent_instructions.py:17:13:17:37 | ControlFlowNode for Attribute() | agent_instructions.py:17:5:17:9 | ControlFlowNode for input | provenance | |
| anthropic_test.py:2:26:2:32 | ControlFlowNode for ImportMember | anthropic_test.py:2:26:2:32 | ControlFlowNode for request | provenance | |
| anthropic_test.py:2:26:2:32 | ControlFlowNode for request | anthropic_test.py:11:15:11:21 | ControlFlowNode for request | provenance | |
@@ -61,7 +63,7 @@ edges
| openai_test.py:2:26:2:32 | ControlFlowNode for request | openai_test.py:13:13:13:19 | ControlFlowNode for request | provenance | |
| openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:17:22:17:46 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:10 |
| openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:22:22:22:46 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:10 |
| openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:23:15:37:9 | ControlFlowNode for List | provenance | Sink:MaD:9 |
| openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:26:28:26:51 | ControlFlowNode for BinaryExpr | provenance | |
| openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:26:28:26:51 | ControlFlowNode for BinaryExpr | provenance | |
| openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:41:22:41:46 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:10 |
| openai_test.py:12:5:12:11 | ControlFlowNode for persona | openai_test.py:63:28:63:51 | ControlFlowNode for BinaryExpr | provenance | Sink:MaD:8 |
@@ -72,7 +74,7 @@ edges
| openai_test.py:12:15:12:26 | ControlFlowNode for Attribute | openai_test.py:12:15:12:41 | ControlFlowNode for Attribute() | provenance | dict.get |
| openai_test.py:12:15:12:41 | ControlFlowNode for Attribute() | openai_test.py:12:5:12:11 | ControlFlowNode for persona | provenance | |
| openai_test.py:13:5:13:9 | ControlFlowNode for query | openai_test.py:18:15:18:19 | ControlFlowNode for query | provenance | Sink:MaD:9 |
| openai_test.py:13:5:13:9 | ControlFlowNode for query | openai_test.py:23:15:37:9 | ControlFlowNode for List | provenance | Sink:MaD:9 |
| openai_test.py:13:5:13:9 | ControlFlowNode for query | openai_test.py:33:33:33:37 | ControlFlowNode for query | provenance | |
| openai_test.py:13:5:13:9 | ControlFlowNode for query | openai_test.py:33:33:33:37 | ControlFlowNode for query | provenance | |
| openai_test.py:13:5:13:9 | ControlFlowNode for query | openai_test.py:42:15:42:19 | ControlFlowNode for query | provenance | Sink:MaD:9 |
| openai_test.py:13:5:13:9 | ControlFlowNode for query | openai_test.py:53:33:53:37 | ControlFlowNode for query | provenance | |
@@ -82,6 +84,14 @@ edges
| openai_test.py:13:13:13:19 | ControlFlowNode for request | openai_test.py:13:13:13:24 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep |
| openai_test.py:13:13:13:24 | ControlFlowNode for Attribute | openai_test.py:13:13:13:37 | ControlFlowNode for Attribute() | provenance | dict.get |
| openai_test.py:13:13:13:37 | ControlFlowNode for Attribute() | openai_test.py:13:5:13:9 | ControlFlowNode for query | provenance | |
| openai_test.py:24:13:27:13 | ControlFlowNode for Dict [Dictionary element at key content] | openai_test.py:23:15:37:9 | ControlFlowNode for List | provenance | Sink:MaD:9 Sink:MaD:9 |
| openai_test.py:26:28:26:51 | ControlFlowNode for BinaryExpr | openai_test.py:24:13:27:13 | ControlFlowNode for Dict [Dictionary element at key content] | provenance | |
| openai_test.py:28:13:36:13 | ControlFlowNode for Dict [Dictionary element at key content, List element, Dictionary element at key text] | openai_test.py:23:15:37:9 | ControlFlowNode for List | provenance | Sink:MaD:9 Sink:MaD:9 |
| openai_test.py:28:13:36:13 | ControlFlowNode for Dict [Dictionary element at key content, List element, Dictionary element at key text] | openai_test.py:23:15:37:9 | ControlFlowNode for List | provenance | Sink:MaD:9 Sink:MaD:9 Sink:MaD:9 |
| openai_test.py:28:13:36:13 | ControlFlowNode for Dict [Dictionary element at key content, List element, Dictionary element at key text] | openai_test.py:23:15:37:9 | ControlFlowNode for List | provenance | Sink:MaD:9 Sink:MaD:9 Sink:MaD:9 Sink:MaD:9 |
| openai_test.py:30:28:35:17 | ControlFlowNode for List [List element, Dictionary element at key text] | openai_test.py:28:13:36:13 | ControlFlowNode for Dict [Dictionary element at key content, List element, Dictionary element at key text] | provenance | |
| openai_test.py:31:21:34:21 | ControlFlowNode for Dict [Dictionary element at key text] | openai_test.py:30:28:35:17 | ControlFlowNode for List [List element, Dictionary element at key text] | provenance | |
| openai_test.py:33:33:33:37 | ControlFlowNode for query | openai_test.py:31:21:34:21 | ControlFlowNode for Dict [Dictionary element at key text] | provenance | |
models
| 1 | Sink: Anthropic; Member[beta].Member[messages].Member[create].Argument[messages:].ListElement.DictionaryElement[content]; prompt-injection |
| 2 | Sink: Anthropic; Member[beta].Member[messages].Member[create].Argument[system:]; prompt-injection |
@@ -140,7 +150,13 @@ nodes
| openai_test.py:18:15:18:19 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
| openai_test.py:22:22:22:46 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| openai_test.py:23:15:37:9 | ControlFlowNode for List | semmle.label | ControlFlowNode for List |
| openai_test.py:24:13:27:13 | ControlFlowNode for Dict [Dictionary element at key content] | semmle.label | ControlFlowNode for Dict [Dictionary element at key content] |
| openai_test.py:26:28:26:51 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| openai_test.py:26:28:26:51 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| openai_test.py:28:13:36:13 | ControlFlowNode for Dict [Dictionary element at key content, List element, Dictionary element at key text] | semmle.label | ControlFlowNode for Dict [Dictionary element at key content, List element, Dictionary element at key text] |
| openai_test.py:30:28:35:17 | ControlFlowNode for List [List element, Dictionary element at key text] | semmle.label | ControlFlowNode for List [List element, Dictionary element at key text] |
| openai_test.py:31:21:34:21 | ControlFlowNode for Dict [Dictionary element at key text] | semmle.label | ControlFlowNode for Dict [Dictionary element at key text] |
| openai_test.py:33:33:33:37 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
| openai_test.py:33:33:33:37 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
| openai_test.py:41:22:41:46 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| openai_test.py:42:15:42:19 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |

View File

@@ -131,6 +131,5 @@ from unknown_settings import password # $ SensitiveDataSource=password
print(password) # $ SensitiveUse=password
_config = {"sleep_timer": 5, "mysql_password": password}
# since we have taint-step from store of `password`, we will consider any item in the
# dictionary to be a password :(
print(_config["sleep_timer"]) # $ SPURIOUS: SensitiveUse=password
# since we have precise dictionary content, other items of the config are not tainted
print(_config["sleep_timer"])

View File

@@ -7,13 +7,9 @@ edges
| summaries.py:36:38:36:38 | ControlFlowNode for x | summaries.py:36:41:36:45 | ControlFlowNode for BinaryExpr | provenance | |
| summaries.py:36:48:36:53 | ControlFlowNode for SOURCE | summaries.py:36:18:36:54 | ControlFlowNode for apply_lambda() | provenance | apply_lambda |
| summaries.py:36:48:36:53 | ControlFlowNode for SOURCE | summaries.py:36:38:36:38 | ControlFlowNode for x | provenance | apply_lambda |
| summaries.py:44:1:44:12 | ControlFlowNode for tainted_list | summaries.py:45:6:45:20 | ControlFlowNode for Subscript | provenance | |
| summaries.py:44:1:44:12 | ControlFlowNode for tainted_list [List element] | summaries.py:45:6:45:17 | ControlFlowNode for tainted_list [List element] | provenance | |
| summaries.py:44:16:44:33 | ControlFlowNode for reversed() | summaries.py:44:1:44:12 | ControlFlowNode for tainted_list | provenance | |
| summaries.py:44:16:44:33 | ControlFlowNode for reversed() [List element] | summaries.py:44:1:44:12 | ControlFlowNode for tainted_list [List element] | provenance | |
| summaries.py:44:25:44:32 | ControlFlowNode for List | summaries.py:44:16:44:33 | ControlFlowNode for reversed() | provenance | builtins.reversed |
| summaries.py:44:25:44:32 | ControlFlowNode for List [List element] | summaries.py:44:16:44:33 | ControlFlowNode for reversed() [List element] | provenance | builtins.reversed |
| summaries.py:44:26:44:31 | ControlFlowNode for SOURCE | summaries.py:44:25:44:32 | ControlFlowNode for List | provenance | |
| summaries.py:44:26:44:31 | ControlFlowNode for SOURCE | summaries.py:44:25:44:32 | ControlFlowNode for List [List element] | provenance | |
| summaries.py:45:6:45:17 | ControlFlowNode for tainted_list [List element] | summaries.py:45:6:45:20 | ControlFlowNode for Subscript | provenance | |
| summaries.py:48:15:48:15 | ControlFlowNode for x | summaries.py:49:12:49:18 | ControlFlowNode for BinaryExpr | provenance | |
@@ -42,6 +38,7 @@ edges
| summaries.py:67:1:67:18 | ControlFlowNode for tainted_resultlist | summaries.py:68:6:68:26 | ControlFlowNode for Subscript | provenance | |
| summaries.py:67:1:67:18 | ControlFlowNode for tainted_resultlist [List element] | summaries.py:68:6:68:23 | ControlFlowNode for tainted_resultlist [List element] | provenance | |
| summaries.py:67:22:67:39 | ControlFlowNode for json_loads() [List element] | summaries.py:67:1:67:18 | ControlFlowNode for tainted_resultlist [List element] | provenance | |
| summaries.py:67:33:67:38 | ControlFlowNode for SOURCE | summaries.py:67:1:67:18 | ControlFlowNode for tainted_resultlist | provenance | |
| summaries.py:67:33:67:38 | ControlFlowNode for SOURCE | summaries.py:67:1:67:18 | ControlFlowNode for tainted_resultlist | provenance | Decoding-JSON |
| summaries.py:67:33:67:38 | ControlFlowNode for SOURCE | summaries.py:67:22:67:39 | ControlFlowNode for json_loads() [List element] | provenance | json.loads |
| summaries.py:68:6:68:23 | ControlFlowNode for tainted_resultlist [List element] | summaries.py:68:6:68:26 | ControlFlowNode for Subscript | provenance | |
@@ -56,11 +53,8 @@ nodes
| summaries.py:36:41:36:45 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| summaries.py:36:48:36:53 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| summaries.py:37:6:37:19 | ControlFlowNode for tainted_lambda | semmle.label | ControlFlowNode for tainted_lambda |
| summaries.py:44:1:44:12 | ControlFlowNode for tainted_list | semmle.label | ControlFlowNode for tainted_list |
| summaries.py:44:1:44:12 | ControlFlowNode for tainted_list [List element] | semmle.label | ControlFlowNode for tainted_list [List element] |
| summaries.py:44:16:44:33 | ControlFlowNode for reversed() | semmle.label | ControlFlowNode for reversed() |
| summaries.py:44:16:44:33 | ControlFlowNode for reversed() [List element] | semmle.label | ControlFlowNode for reversed() [List element] |
| summaries.py:44:25:44:32 | ControlFlowNode for List | semmle.label | ControlFlowNode for List |
| summaries.py:44:25:44:32 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| summaries.py:44:26:44:31 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| summaries.py:45:6:45:17 | ControlFlowNode for tainted_list [List element] | semmle.label | ControlFlowNode for tainted_list [List element] |

View File

@@ -32,7 +32,6 @@ def test_construction():
list(tainted_tuple), # $ tainted
list(tainted_set), # $ tainted
list(tainted_dict.values()), # $ tainted
list(tainted_dict.items()), # $ tainted
tuple(tainted_list), # $ tainted
set(tainted_list), # $ tainted
@@ -41,10 +40,11 @@ def test_construction():
dict(k = tainted_string)["k"], # $ tainted
dict(dict(k = tainted_string))["k"], # $ tainted
dict(["k", tainted_string]), # $ tainted
list(tainted_dict.items()), # $ tainted
)
ensure_not_tainted(
dict(k = tainted_string)["k1"]
dict(k = tainted_string)["k1"],
)
@@ -59,7 +59,7 @@ def test_access(x, y, z):
sorted(tainted_list), # $ tainted
reversed(tainted_list), # $ tainted
iter(tainted_list), # $ tainted
next(iter(tainted_list)), # $ MISSING: tainted
next(iter(tainted_list)), # $ tainted
[i for i in tainted_list], # $ tainted
[tainted_list for _i in [1,2,3]], # $ tainted
)

View File

@@ -53,7 +53,7 @@ def contrived_1():
(a, b, c), (d, e, f) = tainted_list, no_taint_list
ensure_tainted(a, b, c) # $ tainted
ensure_not_tainted(d, e, f) # $ SPURIOUS: tainted
ensure_not_tainted(d, e, f)
def contrived_2():

View File

@@ -3,10 +3,12 @@ edges
| taint_step_test.py:5:12:5:35 | ControlFlowNode for Attribute() | taint_step_test.py:5:5:5:8 | ControlFlowNode for path | provenance | |
| taint_step_test.py:6:5:6:8 | ControlFlowNode for file | taint_step_test.py:19:48:19:51 | ControlFlowNode for file | provenance | |
| taint_step_test.py:6:12:6:35 | ControlFlowNode for Attribute() | taint_step_test.py:6:5:6:8 | ControlFlowNode for file | provenance | |
| taint_step_test.py:11:18:11:21 | ControlFlowNode for path | taint_step_test.py:12:9:12:16 | ControlFlowNode for filepath | provenance | |
| taint_step_test.py:11:18:11:21 | ControlFlowNode for path | taint_step_test.py:12:9:12:16 | ControlFlowNode for filepath | provenance | AdditionalTaintStep |
| taint_step_test.py:11:18:11:21 | ControlFlowNode for path | taint_step_test.py:12:33:12:36 | ControlFlowNode for path | provenance | |
| taint_step_test.py:11:24:11:27 | ControlFlowNode for file | taint_step_test.py:12:9:12:16 | ControlFlowNode for filepath | provenance | AdditionalTaintStep |
| taint_step_test.py:12:9:12:16 | ControlFlowNode for filepath | taint_step_test.py:13:19:13:26 | ControlFlowNode for filepath | provenance | |
| taint_step_test.py:12:20:12:43 | ControlFlowNode for Attribute() | taint_step_test.py:12:9:12:16 | ControlFlowNode for filepath | provenance | |
| taint_step_test.py:12:33:12:36 | ControlFlowNode for path | taint_step_test.py:12:20:12:43 | ControlFlowNode for Attribute() | provenance | str.join |
| taint_step_test.py:19:43:19:46 | ControlFlowNode for path | taint_step_test.py:11:18:11:21 | ControlFlowNode for path | provenance | AdditionalTaintStep |
| taint_step_test.py:19:48:19:51 | ControlFlowNode for file | taint_step_test.py:11:24:11:27 | ControlFlowNode for file | provenance | AdditionalTaintStep |
nodes
@@ -17,6 +19,8 @@ nodes
| taint_step_test.py:11:18:11:21 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| taint_step_test.py:11:24:11:27 | ControlFlowNode for file | semmle.label | ControlFlowNode for file |
| taint_step_test.py:12:9:12:16 | ControlFlowNode for filepath | semmle.label | ControlFlowNode for filepath |
| taint_step_test.py:12:20:12:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| taint_step_test.py:12:33:12:36 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| taint_step_test.py:13:19:13:26 | ControlFlowNode for filepath | semmle.label | ControlFlowNode for filepath |
| taint_step_test.py:19:43:19:46 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| taint_step_test.py:19:48:19:51 | ControlFlowNode for file | semmle.label | ControlFlowNode for file |

View File

@@ -5,5 +5,51 @@ cursor = conn.cursor()
cursor.execute("some sql", (42,)) # $ getSql="some sql"
cursor.executemany("some sql", (42,)) # $ getSql="some sql"
cursor.close()
# ---------------------------------------------------------------------------
# Connection stored in a class attribute and accessed via various patterns
# ---------------------------------------------------------------------------
class WrapperA:
def __init__(self):
self._conn = dbapi.connect(address="hostname", port=300, user="username", pass_arg="testpass")
def get_connection(self):
return self._conn
# Getter called on a fresh constructor result
conn_a1 = WrapperA().get_connection()
cursor_a1 = conn_a1.cursor()
cursor_a1.execute("some sql", (42,)) # $ MISSING: getSql="some sql"
# Getter called via a stored wrapper instance
wrapper_instance = WrapperA()
conn_a2 = wrapper_instance.get_connection()
cursor_a2 = conn_a2.cursor()
cursor_a2.execute("some sql", (42,)) # $ MISSING: getSql="some sql"
# Direct attribute access on a fresh constructor result
conn_b = WrapperA()._conn
cursor_b = conn_b.cursor()
cursor_b.execute("some sql", (42,)) # $ MISSING: getSql="some sql"
class WrapperB:
"""Stores the connection under a different attribute name."""
def __init__(self):
self._hana = dbapi.connect(address="hostname", port=300, user="username", pass_arg="testpass")
def cursor(self):
return self._hana.cursor()
# Direct attribute access on a stored instance (mirrors hdb_con3 in the issue)
conn_c = WrapperB()._hana
cursor_c = conn_c.cursor()
cursor_c.execute("some sql", (42,)) # $ MISSING: getSql="some sql"

View File

@@ -6,16 +6,16 @@ pat = ... # some pattern
compiled_pat = re.compile(pat)
# see https://docs.python.org/3/library/re.html#functions
ensure_not_tainted(
# returns Match object, which is tested properly below. (note: with the flow summary
# modeling, objects containing tainted values are not themselves tainted).
re.search(pat, ts),
re.match(pat, ts),
re.fullmatch(pat, ts),
ensure_tainted(
# returns Match object, which is tested properly below. (note: the match objects contain
# tainted values but are not themselves tainted - this test relies on implicit reads at sinks).
re.search(pat, ts), # $ tainted
re.match(pat, ts), # $ tainted
re.fullmatch(pat, ts), # $ tainted
compiled_pat.search(ts),
compiled_pat.match(ts),
compiled_pat.fullmatch(ts),
compiled_pat.search(ts), # $ tainted
compiled_pat.match(ts), # $ tainted
compiled_pat.fullmatch(ts), # $ tainted
)
# Match object
@@ -80,9 +80,9 @@ ensure_tainted(
)
ensure_not_tainted(
re.subn(pat, repl="safe", string=ts),
re.subn(pat, repl="safe", string=ts)[1], # // the number of substitutions made
)
ensure_tainted(
re.subn(pat, repl="safe", string=ts), # $ tainted // implicit read at sink
re.subn(pat, repl="safe", string=ts)[0], # $ tainted // the string
)

View File

@@ -63,7 +63,8 @@ class TaintTest(tornado.web.RequestHandler):
request.headers["header-name"], # $ tainted
request.headers.get_list("header-name"), # $ tainted
request.headers.get_all(), # $ tainted
[(k, v) for (k, v) in request.headers.get_all()], # $ tainted
[(k, v) for (k, v) in request.headers.get_all()][0], # $ tainted
list([(k, v) for (k, v) in request.headers.get_all()])[0], # $ tainted
# Dict[str, http.cookies.Morsel]
request.cookies, # $ tainted
@@ -71,6 +72,11 @@ class TaintTest(tornado.web.RequestHandler):
request.cookies["cookie-name"].key, # $ tainted
request.cookies["cookie-name"].value, # $ tainted
request.cookies["cookie-name"].coded_value, # $ tainted
# The comprehension is not tainted, only the elements, but this passes due to implicit reads at sinks
[(k, v) for (k, v) in request.headers.get_all()], # $ tainted
# The list is not tainted, only the elements, but this passes due to implicit reads at sinks
list([(k, v) for (k, v) in request.headers.get_all()]), # $ tainted
)

View File

@@ -11,10 +11,13 @@
edges
| BindToAllInterfaces_test.py:5:9:5:17 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:5:9:5:24 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
| BindToAllInterfaces_test.py:9:9:9:10 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:9:9:9:16 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
| BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
| BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | BindToAllInterfaces_test.py:20:1:20:3 | ControlFlowNode for tup | provenance | |
| BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | BindToAllInterfaces_test.py:17:9:17:18 | ControlFlowNode for ALL_LOCALS | provenance | |
| BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | BindToAllInterfaces_test.py:20:8:20:17 | ControlFlowNode for ALL_LOCALS | provenance | |
| BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | provenance | |
| BindToAllInterfaces_test.py:20:1:20:3 | ControlFlowNode for tup | BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | provenance | Sink:MaD:63 |
| BindToAllInterfaces_test.py:17:9:17:18 | ControlFlowNode for ALL_LOCALS | BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
| BindToAllInterfaces_test.py:20:1:20:3 | ControlFlowNode for tup [Tuple element at index 0] | BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | provenance | Sink:MaD:63 |
| BindToAllInterfaces_test.py:20:8:20:17 | ControlFlowNode for ALL_LOCALS | BindToAllInterfaces_test.py:20:8:20:23 | ControlFlowNode for Tuple [Tuple element at index 0] | provenance | |
| BindToAllInterfaces_test.py:20:8:20:23 | ControlFlowNode for Tuple [Tuple element at index 0] | BindToAllInterfaces_test.py:20:1:20:3 | ControlFlowNode for tup [Tuple element at index 0] | provenance | |
| BindToAllInterfaces_test.py:26:9:26:12 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:26:9:26:18 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
| BindToAllInterfaces_test.py:33:18:33:21 | ControlFlowNode for self [Return] [Attribute bind_addr] | BindToAllInterfaces_test.py:41:10:41:17 | ControlFlowNode for Server() [Attribute bind_addr] | provenance | |
| BindToAllInterfaces_test.py:34:9:34:12 | [post] ControlFlowNode for self [Attribute bind_addr] | BindToAllInterfaces_test.py:33:18:33:21 | ControlFlowNode for self [Return] [Attribute bind_addr] | provenance | |
@@ -25,9 +28,10 @@ edges
| BindToAllInterfaces_test.py:41:1:41:6 | ControlFlowNode for server [Attribute bind_addr] | BindToAllInterfaces_test.py:42:1:42:6 | ControlFlowNode for server [Attribute bind_addr] | provenance | |
| BindToAllInterfaces_test.py:41:10:41:17 | ControlFlowNode for Server() [Attribute bind_addr] | BindToAllInterfaces_test.py:41:1:41:6 | ControlFlowNode for server [Attribute bind_addr] | provenance | |
| BindToAllInterfaces_test.py:42:1:42:6 | ControlFlowNode for server [Attribute bind_addr] | BindToAllInterfaces_test.py:37:15:37:18 | ControlFlowNode for self [Attribute bind_addr] | provenance | |
| BindToAllInterfaces_test.py:46:1:46:4 | ControlFlowNode for host | BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
| BindToAllInterfaces_test.py:46:1:46:4 | ControlFlowNode for host | BindToAllInterfaces_test.py:48:9:48:12 | ControlFlowNode for host | provenance | |
| BindToAllInterfaces_test.py:46:8:46:44 | ControlFlowNode for Attribute() | BindToAllInterfaces_test.py:46:1:46:4 | ControlFlowNode for host | provenance | |
| BindToAllInterfaces_test.py:46:35:46:43 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:46:8:46:44 | ControlFlowNode for Attribute() | provenance | dict.get |
| BindToAllInterfaces_test.py:48:9:48:12 | ControlFlowNode for host | BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
| BindToAllInterfaces_test.py:53:10:53:18 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:53:10:53:25 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
| BindToAllInterfaces_test.py:58:10:58:18 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:58:10:58:25 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
nodes
@@ -37,8 +41,11 @@ nodes
| BindToAllInterfaces_test.py:9:9:9:16 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
| BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | semmle.label | ControlFlowNode for ALL_LOCALS |
| BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
| BindToAllInterfaces_test.py:17:9:17:18 | ControlFlowNode for ALL_LOCALS | semmle.label | ControlFlowNode for ALL_LOCALS |
| BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
| BindToAllInterfaces_test.py:20:1:20:3 | ControlFlowNode for tup | semmle.label | ControlFlowNode for tup |
| BindToAllInterfaces_test.py:20:1:20:3 | ControlFlowNode for tup [Tuple element at index 0] | semmle.label | ControlFlowNode for tup [Tuple element at index 0] |
| BindToAllInterfaces_test.py:20:8:20:17 | ControlFlowNode for ALL_LOCALS | semmle.label | ControlFlowNode for ALL_LOCALS |
| BindToAllInterfaces_test.py:20:8:20:23 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] |
| BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | semmle.label | ControlFlowNode for tup |
| BindToAllInterfaces_test.py:26:9:26:12 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
| BindToAllInterfaces_test.py:26:9:26:18 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
@@ -55,6 +62,7 @@ nodes
| BindToAllInterfaces_test.py:46:1:46:4 | ControlFlowNode for host | semmle.label | ControlFlowNode for host |
| BindToAllInterfaces_test.py:46:8:46:44 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| BindToAllInterfaces_test.py:46:35:46:43 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
| BindToAllInterfaces_test.py:48:9:48:12 | ControlFlowNode for host | semmle.label | ControlFlowNode for host |
| BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
| BindToAllInterfaces_test.py:53:10:53:18 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
| BindToAllInterfaces_test.py:53:10:53:25 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |

View File

@@ -5,11 +5,13 @@ edges
| test.py:5:26:5:32 | ControlFlowNode for request | test.py:34:12:34:18 | ControlFlowNode for request | provenance | |
| test.py:5:26:5:32 | ControlFlowNode for request | test.py:42:12:42:18 | ControlFlowNode for request | provenance | |
| test.py:5:26:5:32 | ControlFlowNode for request | test.py:54:12:54:18 | ControlFlowNode for request | provenance | |
| test.py:13:5:13:12 | ControlFlowNode for data_raw | test.py:14:5:14:8 | ControlFlowNode for data | provenance | |
| test.py:13:5:13:12 | ControlFlowNode for data_raw | test.py:14:5:14:8 | ControlFlowNode for data | provenance | Decoding-Base64 |
| test.py:13:16:13:22 | ControlFlowNode for request | test.py:13:16:13:27 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep |
| test.py:13:16:13:27 | ControlFlowNode for Attribute | test.py:13:16:13:39 | ControlFlowNode for Attribute() | provenance | dict.get |
| test.py:13:16:13:39 | ControlFlowNode for Attribute() | test.py:13:5:13:12 | ControlFlowNode for data_raw | provenance | |
| test.py:14:5:14:8 | ControlFlowNode for data | test.py:15:36:15:39 | ControlFlowNode for data | provenance | |
| test.py:23:5:23:12 | ControlFlowNode for data_raw | test.py:24:5:24:8 | ControlFlowNode for data | provenance | |
| test.py:23:5:23:12 | ControlFlowNode for data_raw | test.py:24:5:24:8 | ControlFlowNode for data | provenance | Decoding-Base64 |
| test.py:23:16:23:22 | ControlFlowNode for request | test.py:23:16:23:27 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep |
| test.py:23:16:23:27 | ControlFlowNode for Attribute | test.py:23:16:23:39 | ControlFlowNode for Attribute() | provenance | dict.get |

View File

@@ -1,10 +1,13 @@
edges
| src/unsafe_shell_test.py:4:22:4:25 | ControlFlowNode for name | src/unsafe_shell_test.py:5:25:5:28 | ControlFlowNode for name | provenance | |
| src/unsafe_shell_test.py:4:22:4:25 | ControlFlowNode for name | src/unsafe_shell_test.py:8:23:8:26 | ControlFlowNode for name | provenance | |
| src/unsafe_shell_test.py:4:22:4:25 | ControlFlowNode for name | src/unsafe_shell_test.py:11:25:11:38 | ControlFlowNode for Attribute() | provenance | |
| src/unsafe_shell_test.py:4:22:4:25 | ControlFlowNode for name | src/unsafe_shell_test.py:14:25:14:40 | ControlFlowNode for Attribute() | provenance | |
| src/unsafe_shell_test.py:4:22:4:25 | ControlFlowNode for name | src/unsafe_shell_test.py:11:34:11:37 | ControlFlowNode for name | provenance | |
| src/unsafe_shell_test.py:4:22:4:25 | ControlFlowNode for name | src/unsafe_shell_test.py:14:35:14:38 | ControlFlowNode for name | provenance | |
| src/unsafe_shell_test.py:4:22:4:25 | ControlFlowNode for name | src/unsafe_shell_test.py:17:32:17:35 | ControlFlowNode for name | provenance | |
| src/unsafe_shell_test.py:4:22:4:25 | ControlFlowNode for name | src/unsafe_shell_test.py:20:27:20:30 | ControlFlowNode for name | provenance | |
| src/unsafe_shell_test.py:11:34:11:37 | ControlFlowNode for name | src/unsafe_shell_test.py:11:25:11:38 | ControlFlowNode for Attribute() | provenance | str.join |
| src/unsafe_shell_test.py:14:34:14:39 | ControlFlowNode for List [List element] | src/unsafe_shell_test.py:14:25:14:40 | ControlFlowNode for Attribute() | provenance | str.join |
| src/unsafe_shell_test.py:14:35:14:38 | ControlFlowNode for name | src/unsafe_shell_test.py:14:34:14:39 | ControlFlowNode for List [List element] | provenance | |
| src/unsafe_shell_test.py:26:20:26:23 | ControlFlowNode for name | src/unsafe_shell_test.py:29:30:29:33 | ControlFlowNode for name | provenance | |
| src/unsafe_shell_test.py:36:22:36:25 | ControlFlowNode for name | src/unsafe_shell_test.py:39:30:39:33 | ControlFlowNode for name | provenance | |
| src/unsafe_shell_test.py:36:22:36:25 | ControlFlowNode for name | src/unsafe_shell_test.py:44:20:44:23 | ControlFlowNode for name | provenance | |
@@ -15,7 +18,10 @@ nodes
| src/unsafe_shell_test.py:5:25:5:28 | ControlFlowNode for name | semmle.label | ControlFlowNode for name |
| src/unsafe_shell_test.py:8:23:8:26 | ControlFlowNode for name | semmle.label | ControlFlowNode for name |
| src/unsafe_shell_test.py:11:25:11:38 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| src/unsafe_shell_test.py:11:34:11:37 | ControlFlowNode for name | semmle.label | ControlFlowNode for name |
| src/unsafe_shell_test.py:14:25:14:40 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| src/unsafe_shell_test.py:14:34:14:39 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] |
| src/unsafe_shell_test.py:14:35:14:38 | ControlFlowNode for name | semmle.label | ControlFlowNode for name |
| src/unsafe_shell_test.py:17:32:17:35 | ControlFlowNode for name | semmle.label | ControlFlowNode for name |
| src/unsafe_shell_test.py:20:27:20:30 | ControlFlowNode for name | semmle.label | ControlFlowNode for name |
| src/unsafe_shell_test.py:26:20:26:23 | ControlFlowNode for name | semmle.label | ControlFlowNode for name |

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