attackmap 0.6.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- attackmap/__init__.py +2 -0
- attackmap/analyzer.py +449 -0
- attackmap/analyzer_contracts.py +194 -0
- attackmap/analyzers.py +1003 -0
- attackmap/anomalies.py +612 -0
- attackmap/asset_model.py +245 -0
- attackmap/attack_taxonomy.py +133 -0
- attackmap/auth_protocol.py +702 -0
- attackmap/authz.py +1695 -0
- attackmap/bench.py +467 -0
- attackmap/cli.py +1474 -0
- attackmap/config_scanner.py +389 -0
- attackmap/context_pack.py +82 -0
- attackmap/contracts.py +201 -0
- attackmap/control_model.py +280 -0
- attackmap/crossrepo.py +356 -0
- attackmap/crypto.py +240 -0
- attackmap/cve.py +717 -0
- attackmap/defensive_review.py +647 -0
- attackmap/detection_opportunities.py +1221 -0
- attackmap/detections/__init__.py +491 -0
- attackmap/detections/bola.yml +57 -0
- attackmap/detections/cloud.yml +609 -0
- attackmap/detections/injection.yml +167 -0
- attackmap/detections/secrets.yml +48 -0
- attackmap/detections/sigma.py +511 -0
- attackmap/detections/ssrf.yml +98 -0
- attackmap/detections/weakness.yml +62 -0
- attackmap/detections/webhook.yml +45 -0
- attackmap/detections/workflow.yml +121 -0
- attackmap/diagrams.py +237 -0
- attackmap/diff.py +301 -0
- attackmap/exploitability.py +493 -0
- attackmap/fingerprint.py +91 -0
- attackmap/fleet.py +370 -0
- attackmap/gitref.py +129 -0
- attackmap/graph.py +26 -0
- attackmap/handler_auth.py +639 -0
- attackmap/handler_span.py +62 -0
- attackmap/hunt_harness.py +505 -0
- attackmap/insights.py +701 -0
- attackmap/llm_review.py +846 -0
- attackmap/lockfiles.py +521 -0
- attackmap/mass_assignment.py +543 -0
- attackmap/md.py +175 -0
- attackmap/merge.py +333 -0
- attackmap/models.py +1284 -0
- attackmap/plugins_lock.py +114 -0
- attackmap/popular_packages.py +193 -0
- attackmap/progress.py +258 -0
- attackmap/recon_models.py +31 -0
- attackmap/recon_to_analysis.py +149 -0
- attackmap/redact.py +220 -0
- attackmap/report.py +424 -0
- attackmap/review_eval.py +335 -0
- attackmap/review_json.py +308 -0
- attackmap/review_prompts.py +796 -0
- attackmap/route_auth_fusion.py +474 -0
- attackmap/safe_fs.py +285 -0
- attackmap/sarif.py +373 -0
- attackmap/sbom.py +418 -0
- attackmap/scanner.py +1379 -0
- attackmap/sdk/__init__.py +278 -0
- attackmap/sdk/contracts.py +17 -0
- attackmap/sdk/fs.py +156 -0
- attackmap/sdk/models.py +59 -0
- attackmap/secrets_history.py +161 -0
- attackmap/security_overlay.py +71 -0
- attackmap/srcpaths.py +301 -0
- attackmap/suggest.py +394 -0
- attackmap/supply_chain.py +688 -0
- attackmap/suppress.py +740 -0
- attackmap/taint.py +1540 -0
- attackmap/taint_flow.py +1419 -0
- attackmap/taint_sinks.py +431 -0
- attackmap/taint_sinks.yaml +308 -0
- attackmap/taint_sources.py +396 -0
- attackmap/taxonomy.py +465 -0
- attackmap/threat_model.py +3441 -0
- attackmap/topology.py +316 -0
- attackmap/triage.py +151 -0
- attackmap/weaknesses.py +365 -0
- attackmap/webhardening.py +479 -0
- attackmap/webhook_verification.py +1067 -0
- attackmap/workflow_scanner.py +964 -0
- attackmap-0.6.4.dist-info/METADATA +226 -0
- attackmap-0.6.4.dist-info/RECORD +91 -0
- attackmap-0.6.4.dist-info/WHEEL +5 -0
- attackmap-0.6.4.dist-info/entry_points.txt +2 -0
- attackmap-0.6.4.dist-info/licenses/LICENSE +21 -0
- attackmap-0.6.4.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
# Declarative taint sink registry (#240).
|
|
2
|
+
#
|
|
3
|
+
# Loaded once at import by attackmap.taint_sinks and validated there (an
|
|
4
|
+
# invalid entry fails the import for this file; a plugin's invalid entry is
|
|
5
|
+
# skipped with a warning). Analyzer plugins add entries through the
|
|
6
|
+
# `attackmap.taint_sinks` entry-point group (see attackmap.sdk).
|
|
7
|
+
#
|
|
8
|
+
# Entry fields:
|
|
9
|
+
# id unique slug (plugins: prefix with the plugin name)
|
|
10
|
+
# kind a sink kind from `kinds:` below
|
|
11
|
+
# langs languages: python, js, go, php, java, csharp, ruby
|
|
12
|
+
# regex the sink signature (Python `re`; must scale linearly — every
|
|
13
|
+
# pattern is run through tests/test_regex_budget.py)
|
|
14
|
+
# cwe primary CWE id (int) — REQUIRED for every sink
|
|
15
|
+
# gate any — dangerous regardless of the argument; fires on reach
|
|
16
|
+
# tainted — fires only when request input reaches `args`: a
|
|
17
|
+
# request-container token in the call (`token_gate`,
|
|
18
|
+
# default true) or a traced intra-procedural flow (#239)
|
|
19
|
+
# args dangerous argument(s): list of positional indexes (default [0]),
|
|
20
|
+
# "all", "receiver" (`url.openStream()`), or "rest" (the rest of
|
|
21
|
+
# the statement, for keyword/assignment sinks)
|
|
22
|
+
# when only fire when the call's arguments match this regex
|
|
23
|
+
# unless never fire when the call's arguments match this regex
|
|
24
|
+
# receiver_unless
|
|
25
|
+
# never fire when the receiver of the matched `.method(` call
|
|
26
|
+
# matches this regex: the expression before the `.` with call
|
|
27
|
+
# arguments elided and whitespace dropped (`a.b()` for
|
|
28
|
+
# `a.b(x)\n .m(`), or `name=<rhs>` for a bare name and its
|
|
29
|
+
# nearest declarator (`taint_sinks.call_receiver`). Anchor with
|
|
30
|
+
# `$` to test the receiver's own last call.
|
|
31
|
+
# requires only consider files whose content matches this regex
|
|
32
|
+
# flags optional: [ignorecase, dotall]
|
|
33
|
+
# base_score optional exploitability override for this entry
|
|
34
|
+
# note free text
|
|
35
|
+
#
|
|
36
|
+
# Single-quoted YAML scalars keep backslashes literal: write regexes as-is.
|
|
37
|
+
|
|
38
|
+
kinds:
|
|
39
|
+
sql_execute: {label: "database (SQL execute)", cwe: 89, base_score: 35}
|
|
40
|
+
subprocess_shell: {label: "command execution", cwe: 78, base_score: 35}
|
|
41
|
+
eval: {label: "code eval", cwe: 95, base_score: 35}
|
|
42
|
+
exec: {label: "code exec", cwe: 94, base_score: 35}
|
|
43
|
+
dynamic_open: {label: "filesystem open", cwe: 22, base_score: 22, alias_of: path_traversal}
|
|
44
|
+
path_traversal: {label: "filesystem path", cwe: 22, base_score: 22}
|
|
45
|
+
zip_slip: {label: "archive extraction", cwe: 22, base_score: 30}
|
|
46
|
+
unsafe_deserialization: {label: "unsafe deserialization", cwe: 502, base_score: 35}
|
|
47
|
+
ssti: {label: "template injection", cwe: 1336, base_score: 30}
|
|
48
|
+
ssrf: {label: "outbound request (SSRF)", cwe: 918, base_score: 20}
|
|
49
|
+
nosql_injection: {label: "NoSQL query", cwe: 943, base_score: 25}
|
|
50
|
+
open_redirect: {label: "redirect target", cwe: 601, base_score: 15}
|
|
51
|
+
code_injection: {label: "dynamic code / dispatch", cwe: 94, base_score: 35}
|
|
52
|
+
expression_injection: {label: "expression language (SpEL/OGNL/MVEL/script)", cwe: 917, base_score: 35}
|
|
53
|
+
jndi_injection: {label: "JNDI lookup", cwe: 74, base_score: 35}
|
|
54
|
+
ldap_injection: {label: "LDAP filter", cwe: 90, base_score: 25}
|
|
55
|
+
xpath_injection: {label: "XPath expression", cwe: 643, base_score: 22}
|
|
56
|
+
header_injection: {label: "HTTP response header", cwe: 113, base_score: 12}
|
|
57
|
+
regex_injection: {label: "regular expression (ReDoS)", cwe: 1333, base_score: 12}
|
|
58
|
+
|
|
59
|
+
sinks:
|
|
60
|
+
# --- SQL ------------------------------------------------------------------
|
|
61
|
+
- {id: sql-cursor-execute, kind: sql_execute, langs: [python, js, go, php], cwe: 89,
|
|
62
|
+
regex: '\b(?:cursor|conn|connection|db|session|engine|client|pool)\.(?:execute|query|exec_driver_sql)\s*\('}
|
|
63
|
+
- {id: go-sql-query, kind: sql_execute, langs: [python, js, go, php], cwe: 89,
|
|
64
|
+
note: "Go database/sql (#102); title-case methods + db-ish receiver avoid url.Query()",
|
|
65
|
+
regex: '\b(?:db|conn|tx|stmt|dbx|sqlx|pool|database|store|dao)\.(?:Query|QueryRow|Exec)\s*\('}
|
|
66
|
+
- {id: go-sql-query-context, kind: sql_execute, langs: [python, js, go, php], cwe: 89, args: [1],
|
|
67
|
+
regex: '\b(?:db|conn|tx|stmt|dbx|sqlx|pool|database|store|dao)\.(?:QueryContext|QueryRowContext|ExecContext)\s*\('}
|
|
68
|
+
- {id: php-mysqli-query, kind: sql_execute, langs: [python, js, go, php], cwe: 89, args: [1], flags: [ignorecase],
|
|
69
|
+
regex: '\b(?:mysqli_query|pg_query)\s*\('}
|
|
70
|
+
- {id: php-pdo-query, kind: sql_execute, langs: [python, js, go, php], cwe: 89, flags: [ignorecase],
|
|
71
|
+
note: "PDO/db ->query|exec (not ->prepare) and Laravel raw DB:: calls (#103)",
|
|
72
|
+
regex: '\$\w+->(?:query|exec)\s*\(|\bDB::(?:select|statement|insert|update|delete|raw|unprepared)\s*\('}
|
|
73
|
+
- {id: java-jdbc, kind: sql_execute, langs: [java], cwe: 89,
|
|
74
|
+
regex: '\b(?:stmt|statement|st|conn|connection|jdbcTemplate|jdbc|em|entityManager|session)\s*\.\s*(?:executeQuery|executeUpdate|execute|prepareStatement|createQuery|createNativeQuery|query|queryForObject|queryForList|update)\s*\('}
|
|
75
|
+
|
|
76
|
+
# --- OS command execution ------------------------------------------------
|
|
77
|
+
- {id: py-subprocess-shell, kind: subprocess_shell, langs: [python, js, go, php], cwe: 78, flags: [dotall],
|
|
78
|
+
regex: 'subprocess\.(?:run|call|Popen|check_output|check_call)\s*\([^)]*shell\s*=\s*True'}
|
|
79
|
+
- {id: py-os-system, kind: subprocess_shell, langs: [python], cwe: 78,
|
|
80
|
+
regex: '\bos\.(?:system|popen)\s*\('}
|
|
81
|
+
- {id: node-child-process-exec, kind: subprocess_shell, langs: [python, js, go, php], cwe: 78,
|
|
82
|
+
regex: 'child_process\s*\.\s*exec(?:Sync)?\s*\('}
|
|
83
|
+
- {id: node-exec-imported, kind: subprocess_shell, langs: [js], cwe: 78,
|
|
84
|
+
note: "destructured / promisified exec(Sync) in a file that loads child_process",
|
|
85
|
+
requires: '[''"](?:node:)?child_process[''"]',
|
|
86
|
+
regex: '(?<![\w.$])(?:exec|execSync|execAsync)\s*\('}
|
|
87
|
+
- {id: node-spawn-shell, kind: subprocess_shell, langs: [js], cwe: 78, args: all,
|
|
88
|
+
requires: '[''"](?:node:)?child_process[''"]',
|
|
89
|
+
when: '\bshell\s*:\s*true',
|
|
90
|
+
regex: '(?<![\w$])(?:child_process\s*\.\s*)?spawn(?:Sync)?\s*\('}
|
|
91
|
+
- {id: go-exec-command, kind: subprocess_shell, langs: [python, js, go, php], cwe: 78, args: all,
|
|
92
|
+
regex: '\bexec\.Command(?:Context)?\s*\('}
|
|
93
|
+
- {id: php-shell, kind: subprocess_shell, langs: [python, js, go, php], cwe: 78,
|
|
94
|
+
regex: '\b(?:system|shell_exec|passthru|proc_open|popen)\s*\('}
|
|
95
|
+
- {id: php-exec, kind: subprocess_shell, langs: [php], cwe: 78,
|
|
96
|
+
note: "PHP exec() runs a shell command (previously reported as code exec)",
|
|
97
|
+
regex: '(?<![\w>$:])exec\s*\('}
|
|
98
|
+
- {id: java-runtime-exec, kind: subprocess_shell, langs: [java], cwe: 78, args: all,
|
|
99
|
+
regex: '\bgetRuntime\s*\(\s*\)\s*\.\s*exec\s*\(|\bnew\s+ProcessBuilder\s*\('}
|
|
100
|
+
- {id: dotnet-process-start, kind: subprocess_shell, langs: [csharp], cwe: 78, args: all,
|
|
101
|
+
regex: '\bProcess\s*\.\s*Start\s*\(|\bnew\s+ProcessStartInfo\s*\('}
|
|
102
|
+
- {id: ruby-system, kind: subprocess_shell, langs: [ruby], cwe: 78, args: rest,
|
|
103
|
+
note: "the argv form system('cmd', arg, …) bypasses the shell — not flagged",
|
|
104
|
+
unless: '^\s*\(?\s*[''"][^''"#]*[''"]\s*,',
|
|
105
|
+
regex: '(?<![\w.:])(?:system|exec|spawn)\b(?=\s*[(''"])'}
|
|
106
|
+
- {id: ruby-backticks, kind: subprocess_shell, langs: [ruby], cwe: 78, args: rest,
|
|
107
|
+
note: "backtick / %x command strings with interpolation",
|
|
108
|
+
regex: '`[^`\n]*#\{|%x[\[({][^\n]*#\{'}
|
|
109
|
+
- {id: ruby-open3, kind: subprocess_shell, langs: [ruby], cwe: 78, args: all,
|
|
110
|
+
regex: '\bOpen3\s*\.\s*(?:popen3|popen2|popen2e|capture2|capture2e|capture3|pipeline\w*)\b'}
|
|
111
|
+
- {id: ruby-kernel-open, kind: subprocess_shell, langs: [ruby], cwe: 78, gate: tainted,
|
|
112
|
+
note: "Kernel#open with a caller-controlled name spawns a process for '|cmd'",
|
|
113
|
+
regex: '(?<![\w.:])(?:Kernel\s*\.\s*)?open\s*\('}
|
|
114
|
+
|
|
115
|
+
# --- code evaluation / dynamic dispatch ----------------------------------
|
|
116
|
+
- {id: eval, kind: eval, langs: [python, js, go, php, ruby], cwe: 95,
|
|
117
|
+
regex: '(?<![\w.])eval\s*\('}
|
|
118
|
+
- {id: py-exec, kind: exec, langs: [python], cwe: 94,
|
|
119
|
+
regex: '(?<![\w.])exec\s*\('}
|
|
120
|
+
- {id: py-import-module, kind: code_injection, langs: [python], cwe: 94, gate: tainted,
|
|
121
|
+
regex: '\bimportlib\.import_module\s*\(|(?<![\w.])__import__\s*\('}
|
|
122
|
+
- {id: py-getattr-dispatch, kind: code_injection, langs: [python], cwe: 94, gate: tainted, args: [1],
|
|
123
|
+
regex: '(?<![\w.])getattr\s*\('}
|
|
124
|
+
- {id: js-new-function, kind: code_injection, langs: [js], cwe: 94, gate: tainted, args: all,
|
|
125
|
+
regex: '\bnew\s+Function\s*\('}
|
|
126
|
+
- {id: js-vm-run, kind: code_injection, langs: [js], cwe: 94, gate: tainted,
|
|
127
|
+
regex: '\bvm\s*\.\s*(?:runInNewContext|runInThisContext|runInContext|compileFunction)\s*\(|\bnew\s+vm\s*\.\s*Script\s*\('}
|
|
128
|
+
- {id: js-timer-string, kind: code_injection, langs: [js], cwe: 94, gate: tainted,
|
|
129
|
+
note: "setTimeout/setInterval with a string body; function callbacks are ignored",
|
|
130
|
+
unless: '^\s*(?:async\b|function\b|\(|[A-Za-z_$][\w$]*\s*=>)',
|
|
131
|
+
regex: '(?<![\w.])set(?:Timeout|Interval)\s*\('}
|
|
132
|
+
- {id: ruby-send, kind: code_injection, langs: [ruby], cwe: 94, gate: tainted,
|
|
133
|
+
regex: '\.\s*(?:send|public_send|__send__|instance_eval|class_eval|instance_variable_get)\s*\('}
|
|
134
|
+
- {id: ruby-constantize, kind: code_injection, langs: [ruby], cwe: 94,
|
|
135
|
+
regex: '\bparams\s*\[[^\]\n]{1,80}\]\s*\.\s*(?:safe_)?constantize\b'}
|
|
136
|
+
|
|
137
|
+
# --- expression language / JNDI (Java) -----------------------------------
|
|
138
|
+
- {id: java-spel, kind: expression_injection, langs: [java], cwe: 917, gate: tainted,
|
|
139
|
+
regex: '\.\s*parseExpression\s*\('}
|
|
140
|
+
- {id: java-ognl, kind: expression_injection, langs: [java], cwe: 917, gate: tainted,
|
|
141
|
+
regex: '\bOgnl(?:Util)?\s*\.\s*(?:getValue|setValue|parseExpression|compileExpression)\s*\('}
|
|
142
|
+
- {id: java-mvel, kind: expression_injection, langs: [java], cwe: 917, gate: tainted,
|
|
143
|
+
regex: '\bMVEL\s*\.\s*(?:eval|evalToString|compileExpression|executeExpression)\s*\('}
|
|
144
|
+
- {id: java-script-engine, kind: expression_injection, langs: [java], cwe: 917, gate: tainted,
|
|
145
|
+
regex: '\b(?:engine|scriptEngine|jsEngine|nashorn|groovyEngine)\s*\.\s*eval\s*\('}
|
|
146
|
+
- {id: java-jndi-lookup, kind: jndi_injection, langs: [java], cwe: 74, gate: tainted,
|
|
147
|
+
regex: '\b(?:ctx|context|initialContext|initCtx|ic|jndiContext|namingContext)\s*\.\s*lookup\s*\(|\bnew\s+InitialContext\s*\(\s*\)\s*\.\s*lookup\s*\('}
|
|
148
|
+
|
|
149
|
+
# --- LDAP / XPath ----------------------------------------------------------
|
|
150
|
+
- {id: py-ldap-search, kind: ldap_injection, langs: [python], cwe: 90, gate: tainted, args: [2],
|
|
151
|
+
note: "python-ldap search_s(base, scope, filterstr)",
|
|
152
|
+
regex: '\b\w+\s*\.\s*search(?:_s|_st|_ext|_ext_s)\s*\('}
|
|
153
|
+
- {id: py-ldap3-search, kind: ldap_injection, langs: [python], cwe: 90, gate: tainted, args: [1],
|
|
154
|
+
note: "ldap3 Connection.search(search_base, search_filter)",
|
|
155
|
+
regex: '\b(?:conn|connection|ldap_conn|ldap)\s*\.\s*search\s*\('}
|
|
156
|
+
- {id: java-ldap-search, kind: ldap_injection, langs: [java], cwe: 90, gate: tainted, args: [1],
|
|
157
|
+
regex: '\b(?:ctx|context|dirContext|ldapContext|ldapTemplate|ldap)\s*\.\s*search\s*\('}
|
|
158
|
+
- {id: php-ldap-search, kind: ldap_injection, langs: [php], cwe: 90, gate: tainted, args: [2],
|
|
159
|
+
regex: '\bldap_(?:search|list|read)\s*\('}
|
|
160
|
+
- {id: py-lxml-xpath, kind: xpath_injection, langs: [python], cwe: 643, gate: tainted,
|
|
161
|
+
regex: '\.\s*xpath\s*\('}
|
|
162
|
+
- {id: java-xpath, kind: xpath_injection, langs: [java], cwe: 643, gate: tainted,
|
|
163
|
+
regex: '\b(?:xpath|xPath|xp|xpathObj)\s*\.\s*(?:evaluate|compile)\s*\('}
|
|
164
|
+
- {id: js-xpath, kind: xpath_injection, langs: [js], cwe: 643, gate: tainted,
|
|
165
|
+
regex: '\bxpath\s*\.\s*(?:select1?|evaluate|parse)\s*\('}
|
|
166
|
+
|
|
167
|
+
# --- path traversal / file inclusion -------------------------------------
|
|
168
|
+
- {id: py-open, kind: dynamic_open, langs: [python, js, go, php], cwe: 22, gate: tainted,
|
|
169
|
+
regex: '(?<![\w.])open\s*\('}
|
|
170
|
+
- {id: node-fs-read, kind: dynamic_open, langs: [js], cwe: 22, gate: tainted,
|
|
171
|
+
regex: '\bfs\s*\.\s*(?:promises\s*\.\s*)?(?:readFile|readFileSync|createReadStream|writeFile|writeFileSync)\s*\('}
|
|
172
|
+
- {id: go-os-open, kind: dynamic_open, langs: [go], cwe: 22, gate: tainted,
|
|
173
|
+
regex: '\b(?:os\.(?:Open|OpenFile|ReadFile|Create|WriteFile)|ioutil\.ReadFile)\s*\('}
|
|
174
|
+
- {id: php-file-read, kind: dynamic_open, langs: [php], cwe: 22, gate: tainted,
|
|
175
|
+
regex: '\b(?:fopen|file_get_contents|readfile|file_put_contents)\s*\('}
|
|
176
|
+
- {id: java-file, kind: dynamic_open, langs: [java], cwe: 22, gate: tainted, args: all,
|
|
177
|
+
regex: '\bnew\s+(?:File|FileInputStream|FileReader|FileOutputStream|FileWriter|RandomAccessFile)\s*\(|\b(?:Paths\s*\.\s*get|Path\s*\.\s*of)\s*\(|\bFiles\s*\.\s*(?:readAllBytes|readAllLines|readString|newInputStream|newBufferedReader|lines)\s*\('}
|
|
178
|
+
- {id: flask-send-file, kind: path_traversal, langs: [python], cwe: 22, gate: tainted,
|
|
179
|
+
note: "send_from_directory is deliberately absent: it joins with werkzeug safe_join",
|
|
180
|
+
regex: '(?<![\w.])(?:flask\.)?send_file\s*\('}
|
|
181
|
+
- {id: express-send-file, kind: path_traversal, langs: [js], cwe: 22, gate: tainted,
|
|
182
|
+
note: "a `root:` option makes `send` reject ../ — not flagged",
|
|
183
|
+
unless: '\broot\s*:',
|
|
184
|
+
regex: '\bres\s*\.\s*(?:sendFile|download)\s*\('}
|
|
185
|
+
- {id: go-serve-file, kind: path_traversal, langs: [go], cwe: 22, gate: tainted, args: [2],
|
|
186
|
+
regex: '\bhttp\.ServeFile\s*\('}
|
|
187
|
+
- {id: php-include, kind: path_traversal, langs: [php], cwe: 98, gate: tainted, args: rest,
|
|
188
|
+
note: "include/require of a caller-chosen path (LFI/RFI)",
|
|
189
|
+
regex: '\b(?:include|require)(?:_once)?\b'}
|
|
190
|
+
|
|
191
|
+
# --- archive extraction (zip-slip) ----------------------------------------
|
|
192
|
+
- {id: py-tar-extractall, kind: zip_slip, langs: [python], cwe: 22, args: all,
|
|
193
|
+
note: "tarfile without filter= (zipfile.extractall already strips ../)",
|
|
194
|
+
requires: '\btarfile\b',
|
|
195
|
+
unless: '\bfilter\s*=',
|
|
196
|
+
regex: '\b(?:tar|tf|tarball|tar_file|tarf|archive|tar_obj)\s*\.\s*extractall\s*\(|\btarfile\.open\s*\([^)\n]*\)\s*\.\s*extractall\s*\('}
|
|
197
|
+
- {id: node-adm-zip, kind: zip_slip, langs: [js], cwe: 22, args: all,
|
|
198
|
+
regex: '\.\s*extractAllTo(?:Async)?\s*\(|\bunzipper\s*\.\s*Extract\s*\('}
|
|
199
|
+
|
|
200
|
+
# --- unsafe deserialization ------------------------------------------------
|
|
201
|
+
- {id: unserialize, kind: unsafe_deserialization, langs: [python, js, go, php], cwe: 502,
|
|
202
|
+
regex: '\bunserialize\s*\('}
|
|
203
|
+
- {id: py-pickle, kind: unsafe_deserialization, langs: [python, js, go, php], cwe: 502,
|
|
204
|
+
regex: '\b(?:cPickle|pickle)\.loads?\s*\('}
|
|
205
|
+
- {id: py-yaml-load, kind: unsafe_deserialization, langs: [python, js, go, php], cwe: 502,
|
|
206
|
+
note: "yaml.load without a Safe loader in the same call",
|
|
207
|
+
regex: '\byaml\.load\s*\((?![^)]*(?:Safe|Loader\s*=))'}
|
|
208
|
+
- {id: py-yaml-unsafe-load, kind: unsafe_deserialization, langs: [python, js, go, php], cwe: 502,
|
|
209
|
+
regex: '\byaml\.unsafe_load\s*\('}
|
|
210
|
+
- {id: py-marshal, kind: unsafe_deserialization, langs: [python, js, go, php], cwe: 502,
|
|
211
|
+
regex: '\bmarshal\.loads?\s*\('}
|
|
212
|
+
- {id: marshal-ois-unserialize, kind: unsafe_deserialization, langs: [python, js, go, php], cwe: 502,
|
|
213
|
+
regex: '\bMarshal\.load\s*\(|\bObjectInputStream\b|\bunserialize\s*\('}
|
|
214
|
+
- {id: py-jsonpickle-dill, kind: unsafe_deserialization, langs: [python], cwe: 502,
|
|
215
|
+
regex: '\bjsonpickle\.decode\s*\(|\bdill\.loads?\s*\('}
|
|
216
|
+
- {id: py-shelve-open, kind: unsafe_deserialization, langs: [python], cwe: 502, gate: tainted,
|
|
217
|
+
regex: '\bshelve\.open\s*\('}
|
|
218
|
+
- {id: ruby-marshal, kind: unsafe_deserialization, langs: [ruby], cwe: 502,
|
|
219
|
+
regex: '\bMarshal\.load\s*\('}
|
|
220
|
+
- {id: dotnet-binaryformatter, kind: unsafe_deserialization, langs: [csharp], cwe: 502,
|
|
221
|
+
regex: '\bnew\s+(?:BinaryFormatter|LosFormatter|NetDataContractSerializer|SoapFormatter|ObjectStateFormatter)\s*\('}
|
|
222
|
+
- {id: dotnet-typenamehandling, kind: unsafe_deserialization, langs: [csharp], cwe: 502,
|
|
223
|
+
regex: '\bTypeNameHandling\s*=\s*TypeNameHandling\s*\.\s*(?:All|Auto|Objects|Arrays)\b'}
|
|
224
|
+
- {id: java-ois, kind: unsafe_deserialization, langs: [java], cwe: 502,
|
|
225
|
+
regex: '\bnew\s+ObjectInputStream\s*\('}
|
|
226
|
+
- {id: java-jackson-default-typing, kind: unsafe_deserialization, langs: [java], cwe: 502,
|
|
227
|
+
regex: '\.\s*(?:enableDefaultTyping|activateDefaultTyping)\s*\(|\bJsonTypeInfo\s*\.\s*Id\s*\.\s*CLASS\b'}
|
|
228
|
+
- {id: java-snakeyaml, kind: unsafe_deserialization, langs: [java], cwe: 502, args: all,
|
|
229
|
+
unless: 'SafeConstructor',
|
|
230
|
+
regex: '\bnew\s+Yaml\s*\('}
|
|
231
|
+
- {id: java-xstream, kind: unsafe_deserialization, langs: [java], cwe: 502,
|
|
232
|
+
regex: '\b(?:xstream|xStream|XSTREAM)\s*\.\s*fromXML\s*\('}
|
|
233
|
+
|
|
234
|
+
# --- server-side template injection ---------------------------------------
|
|
235
|
+
- {id: flask-render-template-string, kind: ssti, langs: [python, js, go, php], cwe: 1336, gate: tainted,
|
|
236
|
+
regex: '\brender_template_string\s*\('}
|
|
237
|
+
- {id: jinja-template, kind: ssti, langs: [python, js, go, php], cwe: 1336, gate: tainted,
|
|
238
|
+
regex: '\bTemplate\s*\('}
|
|
239
|
+
|
|
240
|
+
# --- SSRF -------------------------------------------------------------------
|
|
241
|
+
- {id: py-requests, kind: ssrf, langs: [python, js, go, php], cwe: 918, gate: tainted,
|
|
242
|
+
regex: '\brequests\.(?:get|post|put|delete|patch|head)\s*\('}
|
|
243
|
+
- {id: py-requests-request, kind: ssrf, langs: [python, js, go, php], cwe: 918, gate: tainted, args: [1],
|
|
244
|
+
regex: '\brequests\.request\s*\('}
|
|
245
|
+
- {id: py-httpx, kind: ssrf, langs: [python, js, go, php], cwe: 918, gate: tainted,
|
|
246
|
+
regex: '\bhttpx\.(?:get|post|put|delete|patch|head|Client)\s*\('}
|
|
247
|
+
- {id: py-httpx-request, kind: ssrf, langs: [python, js, go, php], cwe: 918, gate: tainted, args: [1],
|
|
248
|
+
regex: '\bhttpx\.request\s*\('}
|
|
249
|
+
- {id: py-urlopen, kind: ssrf, langs: [python, js, go, php], cwe: 918, gate: tainted,
|
|
250
|
+
regex: '\b(?:urlopen|urlretrieve)\s*\('}
|
|
251
|
+
- {id: js-http-client, kind: ssrf, langs: [python, js, go, php], cwe: 918, gate: tainted,
|
|
252
|
+
regex: '\b(?:axios\s*\.\s*(?:get|post|put|delete|patch|head|request)|fetch|http\.(?:get|request))\s*\('}
|
|
253
|
+
- {id: go-http-get, kind: ssrf, langs: [go], cwe: 918, gate: tainted,
|
|
254
|
+
regex: '\bhttp\.(?:Get|Head|Post|PostForm)\s*\('}
|
|
255
|
+
- {id: go-http-new-request, kind: ssrf, langs: [go], cwe: 918, gate: tainted, args: [1],
|
|
256
|
+
regex: '\bhttp\.NewRequest\s*\('}
|
|
257
|
+
- {id: go-http-new-request-ctx, kind: ssrf, langs: [go], cwe: 918, gate: tainted, args: [2],
|
|
258
|
+
regex: '\bhttp\.NewRequestWithContext\s*\('}
|
|
259
|
+
- {id: php-curl-init, kind: ssrf, langs: [php], cwe: 918, gate: tainted,
|
|
260
|
+
regex: '\bcurl_init\s*\('}
|
|
261
|
+
- {id: php-curl-url, kind: ssrf, langs: [php], cwe: 918, gate: tainted, args: [2],
|
|
262
|
+
regex: '\bcurl_setopt\s*\(\s*\$\w+\s*,\s*CURLOPT_URL\b'}
|
|
263
|
+
- {id: java-http-client, kind: ssrf, langs: [java], cwe: 918, gate: tainted,
|
|
264
|
+
regex: '\bHttpRequest\s*\.\s*newBuilder\s*\(|\brestTemplate\s*\.\s*(?:getForObject|getForEntity|postForObject|postForEntity|exchange)\s*\('}
|
|
265
|
+
- {id: java-url-open, kind: ssrf, langs: [java], cwe: 918, gate: tainted, args: receiver,
|
|
266
|
+
regex: '\.\s*(?:openConnection|openStream)\s*\(\s*\)'}
|
|
267
|
+
|
|
268
|
+
# --- NoSQL ----------------------------------------------------------------
|
|
269
|
+
- {id: mongo-filter-request, kind: nosql_injection, langs: [python, js, go, php], cwe: 943,
|
|
270
|
+
note: "a raw request object as the filter; a bare .find( is overwhelmingly array iteration",
|
|
271
|
+
regex: '\.(?:find|findOne|findOneAndUpdate|update|updateOne|updateMany|remove|deleteOne|deleteMany|aggregate|count|countDocuments)\s*\(\s*(?:req|request|body|query|params|payload|user_input|user_data|form_data)\s*(?:\.\s*\w|\[)',
|
|
272
|
+
# A hash/HMAC/cipher `.update(req.body)` digests the body; it isn't a query (#330).
|
|
273
|
+
# Only when the receiver's last call (past chained `.update()`s) builds the digest.
|
|
274
|
+
receiver_unless: '(?:\bcreate(?:Hmac|Hash|Cipheriv|Decipheriv|Cipher|Decipher|Sign|Verify)|\bhashlib\.\w{1,40}|\bhmac\.new|\bCryptoJS\.[\w.]{1,80}|\bforge\.(?:md|hmac)\.[\w.]{1,80})\(\)(?:\.update\(\)){0,8}$'}
|
|
275
|
+
- {id: mongo-where, kind: nosql_injection, langs: [python, js, go, php], cwe: 943,
|
|
276
|
+
regex: '\$where'}
|
|
277
|
+
|
|
278
|
+
# --- open redirect ----------------------------------------------------------
|
|
279
|
+
- {id: redirect, kind: open_redirect, langs: [python, js, go, php], cwe: 601, gate: tainted,
|
|
280
|
+
regex: '\bredirect\s*\('}
|
|
281
|
+
- {id: express-redirect, kind: open_redirect, langs: [python, js, go, php], cwe: 601, gate: tainted, args: all,
|
|
282
|
+
regex: '\bres\s*\.\s*(?:redirect|location)\s*\('}
|
|
283
|
+
|
|
284
|
+
# --- HTTP response headers (CRLF / header value control) ---------------
|
|
285
|
+
- {id: py-response-header-assign, kind: header_injection, langs: [python], cwe: 113, gate: tainted, args: rest,
|
|
286
|
+
regex: '\b(?:response|resp|res|r)\s*\.\s*headers\s*\[[^\]\n]{1,200}\]\s*=(?!=)'}
|
|
287
|
+
- {id: py-set-header, kind: header_injection, langs: [python], cwe: 113, gate: tainted, args: [1],
|
|
288
|
+
regex: '\.\s*(?:set_header|add_header)\s*\('}
|
|
289
|
+
- {id: express-set-header, kind: header_injection, langs: [js], cwe: 113, gate: tainted, args: [1],
|
|
290
|
+
regex: '\bres\s*\.\s*(?:setHeader|header|set|append)\s*\('}
|
|
291
|
+
- {id: go-header-set, kind: header_injection, langs: [go], cwe: 113, gate: tainted, args: [1],
|
|
292
|
+
regex: '\.\s*Header\s*\(\s*\)\s*\.\s*(?:Set|Add)\s*\('}
|
|
293
|
+
- {id: php-header, kind: header_injection, langs: [php], cwe: 113, gate: tainted,
|
|
294
|
+
regex: '(?<![\w>$:])header\s*\('}
|
|
295
|
+
- {id: java-set-header, kind: header_injection, langs: [java], cwe: 113, gate: tainted, args: [1],
|
|
296
|
+
regex: '\b(?:response|resp|res|httpResponse|servletResponse)\s*\.\s*(?:setHeader|addHeader)\s*\('}
|
|
297
|
+
|
|
298
|
+
# --- user-controlled regular expressions (ReDoS) --------------------------
|
|
299
|
+
- {id: py-re-compile, kind: regex_injection, langs: [python], cwe: 1333, gate: tainted,
|
|
300
|
+
regex: '\bre\.(?:compile|search|match|fullmatch|findall|finditer|split|sub|subn)\s*\('}
|
|
301
|
+
- {id: js-regexp, kind: regex_injection, langs: [js], cwe: 1333, gate: tainted,
|
|
302
|
+
regex: '\bnew\s+RegExp\s*\(|(?<![\w.$])RegExp\s*\('}
|
|
303
|
+
- {id: go-regexp, kind: regex_injection, langs: [go], cwe: 1333, gate: tainted,
|
|
304
|
+
regex: '\bregexp\.(?:Compile|MustCompile|CompilePOSIX|MustCompilePOSIX|MatchString)\s*\('}
|
|
305
|
+
- {id: java-pattern, kind: regex_injection, langs: [java], cwe: 1333, gate: tainted,
|
|
306
|
+
regex: '\bPattern\s*\.\s*(?:compile|matches)\s*\('}
|
|
307
|
+
- {id: php-preg, kind: regex_injection, langs: [php], cwe: 1333, gate: tainted,
|
|
308
|
+
regex: '\bpreg_(?:match|match_all|replace|replace_callback|split|grep)\s*\('}
|