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
attackmap/taxonomy.py
ADDED
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
"""Per-detector taxonomy registry (#250): CWE, OWASP, ASVS and ATT&CK ids
|
|
2
|
+
keyed by stable rule id (#223).
|
|
3
|
+
|
|
4
|
+
Taxonomy is looked up by ``Finding.rule_id``. It is never inferred from a
|
|
5
|
+
finding's title or evidence text. Every id in ``threat_model.rule_catalog()``
|
|
6
|
+
must be registered here with at least one CWE and one OWASP category;
|
|
7
|
+
``tests/test_taxonomy.py`` fails when a rule is missing, so a new detector
|
|
8
|
+
cannot ship without a mapping.
|
|
9
|
+
|
|
10
|
+
Registering a new rule
|
|
11
|
+
----------------------
|
|
12
|
+
Add one line to ``RULE_TAXONOMY``::
|
|
13
|
+
|
|
14
|
+
"my-new-rule": RuleTaxonomy(cwe=(918,), owasp=("A10:2021", "API7:2023"),
|
|
15
|
+
asvs=("V12.6.1",), attack=("T1190",)),
|
|
16
|
+
|
|
17
|
+
- ``cwe``: CWE ids as ints, most specific first. The first one is the
|
|
18
|
+
primary CWE: it becomes the SARIF ``helpUri``. Add any new id and its
|
|
19
|
+
official name to ``CWE_NAMES``.
|
|
20
|
+
- ``owasp``: OWASP Top 10 2021 (``A01:2021``…``A10:2021``), API Security
|
|
21
|
+
Top 10 2023 (``API1:2023``…``API10:2023``) or LLM Top 10 2025 ids, as
|
|
22
|
+
listed in ``OWASP_CATEGORIES``.
|
|
23
|
+
- ``asvs``: optional ASVS 4.0.3 requirement ids (``V5.3.4``).
|
|
24
|
+
- ``attack``: optional ATT&CK Enterprise technique or sub-technique ids.
|
|
25
|
+
Add new ones to ``ATTACK_TECHNIQUES`` with their name and tactic. When
|
|
26
|
+
set, these replace whatever ``attack_techniques`` the detector passed.
|
|
27
|
+
|
|
28
|
+
``speculative-<rule>`` (recall mode) ids inherit their base rule's entry.
|
|
29
|
+
Rules that flag no weakness at all go in ``INFORMATIONAL_RULES`` instead.
|
|
30
|
+
|
|
31
|
+
Verify ids against the source, not memory: cwe.mitre.org (CWE view 1000),
|
|
32
|
+
owasp.org/Top10, owasp.org/API-Security, the ASVS 4.0.3 JSON release and
|
|
33
|
+
the MITRE ATT&CK STIX bundle. The names below were checked against CWE
|
|
34
|
+
4.x view 1000, OWASP Top 10:2021, OWASP API Top 10:2023, OWASP LLM Top
|
|
35
|
+
10:2025, ASVS 4.0.3 and Enterprise ATT&CK 19.2.
|
|
36
|
+
|
|
37
|
+
This module has no package-internal imports, so ``models`` can use it.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
from __future__ import annotations
|
|
41
|
+
|
|
42
|
+
import re
|
|
43
|
+
from dataclasses import dataclass
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass(frozen=True)
|
|
47
|
+
class RuleTaxonomy:
|
|
48
|
+
cwe: tuple[int, ...]
|
|
49
|
+
owasp: tuple[str, ...]
|
|
50
|
+
asvs: tuple[str, ...] = ()
|
|
51
|
+
attack: tuple[str, ...] = ()
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def cwe_ids(self) -> list[str]:
|
|
55
|
+
return [f"CWE-{n}" for n in self.cwe]
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# CWE names (CWE view 1000, "Research Concepts").
|
|
59
|
+
CWE_NAMES: dict[int, str] = {
|
|
60
|
+
15: "External Control of System or Configuration Setting",
|
|
61
|
+
20: "Improper Input Validation",
|
|
62
|
+
22: "Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')",
|
|
63
|
+
74: "Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection')",
|
|
64
|
+
78: "Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')",
|
|
65
|
+
79: "Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')",
|
|
66
|
+
89: "Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')",
|
|
67
|
+
90: "Improper Neutralization of Special Elements used in an LDAP Query ('LDAP Injection')",
|
|
68
|
+
94: "Improper Control of Generation of Code ('Code Injection')",
|
|
69
|
+
95: "Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')",
|
|
70
|
+
98: "Improper Control of Filename for Include/Require Statement in PHP Program ('PHP Remote File Inclusion')",
|
|
71
|
+
113: "Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP Request/Response Splitting')",
|
|
72
|
+
114: "Process Control",
|
|
73
|
+
120: "Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')",
|
|
74
|
+
121: "Stack-based Buffer Overflow",
|
|
75
|
+
134: "Use of Externally-Controlled Format String",
|
|
76
|
+
190: "Integer Overflow or Wraparound",
|
|
77
|
+
200: "Exposure of Sensitive Information to an Unauthorized Actor",
|
|
78
|
+
208: "Observable Timing Discrepancy",
|
|
79
|
+
214: "Invocation of Process Using Visible Sensitive Information",
|
|
80
|
+
215: "Insertion of Sensitive Information Into Debugging Code",
|
|
81
|
+
242: "Use of Inherently Dangerous Function",
|
|
82
|
+
250: "Execution with Unnecessary Privileges",
|
|
83
|
+
269: "Improper Privilege Management",
|
|
84
|
+
284: "Improper Access Control",
|
|
85
|
+
285: "Improper Authorization",
|
|
86
|
+
287: "Improper Authentication",
|
|
87
|
+
294: "Authentication Bypass by Capture-replay",
|
|
88
|
+
295: "Improper Certificate Validation",
|
|
89
|
+
306: "Missing Authentication for Critical Function",
|
|
90
|
+
307: "Improper Restriction of Excessive Authentication Attempts",
|
|
91
|
+
311: "Missing Encryption of Sensitive Data",
|
|
92
|
+
312: "Cleartext Storage of Sensitive Information",
|
|
93
|
+
319: "Cleartext Transmission of Sensitive Information",
|
|
94
|
+
326: "Inadequate Encryption Strength",
|
|
95
|
+
327: "Use of a Broken or Risky Cryptographic Algorithm",
|
|
96
|
+
328: "Use of Weak Hash",
|
|
97
|
+
338: "Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)",
|
|
98
|
+
345: "Insufficient Verification of Data Authenticity",
|
|
99
|
+
346: "Origin Validation Error",
|
|
100
|
+
347: "Improper Verification of Cryptographic Signature",
|
|
101
|
+
349: "Acceptance of Extraneous Untrusted Data With Trusted Data",
|
|
102
|
+
352: "Cross-Site Request Forgery (CSRF)",
|
|
103
|
+
353: "Missing Support for Integrity Check",
|
|
104
|
+
384: "Session Fixation",
|
|
105
|
+
427: "Uncontrolled Search Path Element",
|
|
106
|
+
434: "Unrestricted Upload of File with Dangerous Type",
|
|
107
|
+
470: "Use of Externally-Controlled Input to Select Classes or Code ('Unsafe Reflection')",
|
|
108
|
+
489: "Active Debug Code",
|
|
109
|
+
494: "Download of Code Without Integrity Check",
|
|
110
|
+
501: "Trust Boundary Violation",
|
|
111
|
+
502: "Deserialization of Untrusted Data",
|
|
112
|
+
522: "Insufficiently Protected Credentials",
|
|
113
|
+
526: "Cleartext Storage of Sensitive Information in an Environment Variable",
|
|
114
|
+
532: "Insertion of Sensitive Information into Log File",
|
|
115
|
+
540: "Inclusion of Sensitive Information in Source Code",
|
|
116
|
+
601: "URL Redirection to Untrusted Site ('Open Redirect')",
|
|
117
|
+
611: "Improper Restriction of XML External Entity Reference",
|
|
118
|
+
613: "Insufficient Session Expiration",
|
|
119
|
+
614: "Sensitive Cookie in HTTPS Session Without 'Secure' Attribute",
|
|
120
|
+
639: "Authorization Bypass Through User-Controlled Key",
|
|
121
|
+
643: "Improper Neutralization of Data within XPath Expressions ('XPath Injection')",
|
|
122
|
+
668: "Exposure of Resource to Wrong Sphere",
|
|
123
|
+
680: "Integer Overflow to Buffer Overflow",
|
|
124
|
+
693: "Protection Mechanism Failure",
|
|
125
|
+
732: "Incorrect Permission Assignment for Critical Resource",
|
|
126
|
+
749: "Exposed Dangerous Method or Function",
|
|
127
|
+
760: "Use of a One-Way Hash with a Predictable Salt",
|
|
128
|
+
770: "Allocation of Resources Without Limits or Throttling",
|
|
129
|
+
787: "Out-of-bounds Write",
|
|
130
|
+
798: "Use of Hard-coded Credentials",
|
|
131
|
+
805: "Buffer Access with Incorrect Length Value",
|
|
132
|
+
829: "Inclusion of Functionality from Untrusted Control Sphere",
|
|
133
|
+
862: "Missing Authorization",
|
|
134
|
+
915: "Improperly Controlled Modification of Dynamically-Determined Object Attributes",
|
|
135
|
+
916: "Use of Password Hash With Insufficient Computational Effort",
|
|
136
|
+
917: "Improper Neutralization of Special Elements used in an Expression Language Statement ('Expression Language Injection')",
|
|
137
|
+
918: "Server-Side Request Forgery (SSRF)",
|
|
138
|
+
922: "Insecure Storage of Sensitive Information",
|
|
139
|
+
939: "Improper Authorization in Handler for Custom URL Scheme",
|
|
140
|
+
942: "Permissive Cross-domain Security Policy with Untrusted Domains",
|
|
141
|
+
943: "Improper Neutralization of Special Elements in Data Query Logic",
|
|
142
|
+
1004: "Sensitive Cookie Without 'HttpOnly' Flag",
|
|
143
|
+
1188: "Initialization of a Resource with an Insecure Default",
|
|
144
|
+
1204: "Generation of Weak Initialization Vector (IV)",
|
|
145
|
+
1321: "Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')",
|
|
146
|
+
1333: "Inefficient Regular Expression Complexity",
|
|
147
|
+
1336: "Improper Neutralization of Special Elements Used in a Template Engine",
|
|
148
|
+
1357: "Reliance on Insufficiently Trustworthy Component",
|
|
149
|
+
1395: "Dependency on Vulnerable Third-Party Component",
|
|
150
|
+
1427: "Improper Neutralization of Input Used for LLM Prompting",
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
OWASP_CATEGORIES: dict[str, str] = {
|
|
154
|
+
"A01:2021": "Broken Access Control",
|
|
155
|
+
"A02:2021": "Cryptographic Failures",
|
|
156
|
+
"A03:2021": "Injection",
|
|
157
|
+
"A04:2021": "Insecure Design",
|
|
158
|
+
"A05:2021": "Security Misconfiguration",
|
|
159
|
+
"A06:2021": "Vulnerable and Outdated Components",
|
|
160
|
+
"A07:2021": "Identification and Authentication Failures",
|
|
161
|
+
"A08:2021": "Software and Data Integrity Failures",
|
|
162
|
+
"A09:2021": "Security Logging and Monitoring Failures",
|
|
163
|
+
"A10:2021": "Server-Side Request Forgery (SSRF)",
|
|
164
|
+
"API1:2023": "Broken Object Level Authorization",
|
|
165
|
+
"API2:2023": "Broken Authentication",
|
|
166
|
+
"API3:2023": "Broken Object Property Level Authorization",
|
|
167
|
+
"API4:2023": "Unrestricted Resource Consumption",
|
|
168
|
+
"API5:2023": "Broken Function Level Authorization",
|
|
169
|
+
"API6:2023": "Unrestricted Access to Sensitive Business Flows",
|
|
170
|
+
"API7:2023": "Server Side Request Forgery",
|
|
171
|
+
"API8:2023": "Security Misconfiguration",
|
|
172
|
+
"API9:2023": "Improper Inventory Management",
|
|
173
|
+
"API10:2023": "Unsafe Consumption of APIs",
|
|
174
|
+
"LLM01:2025": "Prompt Injection",
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
# ATT&CK Enterprise techniques: id -> (name, tactic(s)). Sub-technique
|
|
178
|
+
# names are "Parent: Sub". Tactic names follow Enterprise ATT&CK 19.
|
|
179
|
+
ATTACK_TECHNIQUES: dict[str, tuple[str, str]] = {
|
|
180
|
+
"T1027": ("Obfuscated Files or Information", "Stealth"),
|
|
181
|
+
"T1041": ("Exfiltration Over C2 Channel", "Exfiltration"),
|
|
182
|
+
"T1055": ("Process Injection", "Stealth / Privilege Escalation"),
|
|
183
|
+
"T1059": ("Command and Scripting Interpreter", "Execution"),
|
|
184
|
+
"T1059.004": ("Command and Scripting Interpreter: Unix Shell", "Execution"),
|
|
185
|
+
"T1059.007": ("Command and Scripting Interpreter: JavaScript", "Execution"),
|
|
186
|
+
"T1068": ("Exploitation for Privilege Escalation", "Privilege Escalation"),
|
|
187
|
+
"T1071": ("Application Layer Protocol", "Command and Control"),
|
|
188
|
+
"T1078": ("Valid Accounts", "Stealth / Persistence / Privilege Escalation / Initial Access"),
|
|
189
|
+
"T1078.004": ("Valid Accounts: Cloud Accounts", "Stealth / Persistence / Privilege Escalation / Initial Access"),
|
|
190
|
+
"T1098": ("Account Manipulation", "Persistence / Privilege Escalation"),
|
|
191
|
+
"T1105": ("Ingress Tool Transfer", "Command and Control"),
|
|
192
|
+
"T1110": ("Brute Force", "Credential Access"),
|
|
193
|
+
"T1110.002": ("Brute Force: Password Cracking", "Credential Access"),
|
|
194
|
+
"T1115": ("Clipboard Data", "Collection"),
|
|
195
|
+
"T1129": ("Shared Modules", "Execution"),
|
|
196
|
+
"T1133": ("External Remote Services", "Persistence / Initial Access"),
|
|
197
|
+
"T1190": ("Exploit Public-Facing Application", "Initial Access"),
|
|
198
|
+
"T1195.001": ("Supply Chain Compromise: Compromise Software Dependencies and Development Tools", "Initial Access"),
|
|
199
|
+
"T1195.002": ("Supply Chain Compromise: Compromise Software Supply Chain", "Initial Access"),
|
|
200
|
+
"T1199": ("Trusted Relationship", "Initial Access"),
|
|
201
|
+
"T1204.001": ("User Execution: Malicious Link", "Execution"),
|
|
202
|
+
"T1212": ("Exploitation for Credential Access", "Credential Access"),
|
|
203
|
+
"T1485": ("Data Destruction", "Impact"),
|
|
204
|
+
"T1499.003": ("Endpoint Denial of Service: Application Exhaustion Flood", "Impact"),
|
|
205
|
+
"T1499.004": ("Endpoint Denial of Service: Application or System Exploitation", "Impact"),
|
|
206
|
+
"T1505.003": ("Server Software Component: Web Shell", "Persistence"),
|
|
207
|
+
"T1548.001": ("Abuse Elevation Control Mechanism: Setuid and Setgid", "Privilege Escalation / Stealth"),
|
|
208
|
+
"T1528": ("Steal Application Access Token", "Credential Access"),
|
|
209
|
+
"T1530": ("Data from Cloud Storage", "Collection"),
|
|
210
|
+
"T1550.001": ("Use Alternate Authentication Material: Application Access Token", "Lateral Movement"),
|
|
211
|
+
"T1539": ("Steal Web Session Cookie", "Credential Access"),
|
|
212
|
+
"T1552": ("Unsecured Credentials", "Credential Access"),
|
|
213
|
+
"T1552.001": ("Unsecured Credentials: Credentials In Files", "Credential Access"),
|
|
214
|
+
"T1552.005": ("Unsecured Credentials: Cloud Instance Metadata API", "Credential Access"),
|
|
215
|
+
"T1552.007": ("Unsecured Credentials: Container API", "Credential Access"),
|
|
216
|
+
"T1556": ("Modify Authentication Process", "Defense Impairment / Persistence / Credential Access"),
|
|
217
|
+
"T1557": ("Adversary-in-the-Middle", "Credential Access / Collection"),
|
|
218
|
+
"T1565": ("Data Manipulation", "Impact"),
|
|
219
|
+
"T1566.002": ("Phishing: Spearphishing Link", "Initial Access"),
|
|
220
|
+
"T1574": ("Hijack Execution Flow", "Stealth / Execution"),
|
|
221
|
+
"T1584.004": ("Compromise Infrastructure: Server", "Resource Development"),
|
|
222
|
+
"T1600": ("Weaken Encryption", "Defense Impairment"),
|
|
223
|
+
"T1606": ("Forge Web Credentials", "Credential Access"),
|
|
224
|
+
"T1609": ("Container Administration Command", "Execution"),
|
|
225
|
+
"T1611": ("Escape to Host", "Privilege Escalation"),
|
|
226
|
+
"T1685": ("Disable or Modify Tools", "Defense Impairment"),
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def attack_url(technique_id: str) -> str:
|
|
231
|
+
return f"https://attack.mitre.org/techniques/{technique_id.replace('.', '/')}/"
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def cwe_tag(cwe: int) -> str:
|
|
235
|
+
"""CodeQL-style CWE tag (``external/cwe/cwe-078``) that GitHub Code
|
|
236
|
+
Scanning links to the CWE entry."""
|
|
237
|
+
return f"external/cwe/cwe-{cwe:03d}"
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def cwe_url(cwe: int) -> str:
|
|
241
|
+
return f"https://cwe.mitre.org/data/definitions/{cwe}.html"
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
# Rules that report no weakness (nothing to map).
|
|
245
|
+
INFORMATIONAL_RULES: frozenset[str] = frozenset({"limited-surface"})
|
|
246
|
+
|
|
247
|
+
RULE_TAXONOMY: dict[str, RuleTaxonomy] = {
|
|
248
|
+
# Route / surface heuristics
|
|
249
|
+
"public-webhook": RuleTaxonomy(cwe=(345,), owasp=("A08:2021",), asvs=("V13.2.6",), attack=("T1190", "T1199")),
|
|
250
|
+
"webhook-weak-verification": RuleTaxonomy(cwe=(208, 294, 345), owasp=("A08:2021",), asvs=("V13.2.6",), attack=("T1190", "T1199")),
|
|
251
|
+
"exposed-admin-route": RuleTaxonomy(cwe=(285,), owasp=("A01:2021", "API5:2023"), asvs=("V4.1.3",), attack=("T1078", "T1068", "T1098")),
|
|
252
|
+
"upload-route": RuleTaxonomy(cwe=(434,), owasp=("A04:2021",), asvs=("V12.2.1", "V12.5.2"), attack=("T1190", "T1505.003")),
|
|
253
|
+
"weak-auth-route": RuleTaxonomy(cwe=(287, 307), owasp=("A07:2021", "API2:2023"), asvs=("V2.2.1",), attack=("T1110", "T1078")),
|
|
254
|
+
"unauth-outbound-integration": RuleTaxonomy(cwe=(306,), owasp=("A07:2021", "API10:2023"), asvs=("V1.2.2",), attack=("T1190", "T1199")),
|
|
255
|
+
"hardcoded-secret": RuleTaxonomy(cwe=(798,), owasp=("A07:2021",), asvs=("V2.10.4", "V6.4.1"), attack=("T1552.001",)),
|
|
256
|
+
"secret-in-git-history": RuleTaxonomy(cwe=(798, 540), owasp=("A07:2021", "A02:2021"), asvs=("V2.10.4", "V6.4.1"), attack=("T1552.001",)),
|
|
257
|
+
"secret-env-reference": RuleTaxonomy(cwe=(526,), owasp=("A05:2021",), asvs=("V6.4.1",), attack=("T1552",)),
|
|
258
|
+
"public-data-route": RuleTaxonomy(cwe=(284, 200), owasp=("A01:2021",), asvs=("V1.4.4", "V8.3.4"), attack=("T1190",)),
|
|
259
|
+
"atproto-trust-chain": RuleTaxonomy(cwe=(501,), owasp=("A04:2021", "API10:2023"), attack=("T1199", "T1190")),
|
|
260
|
+
"service-trust-chain": RuleTaxonomy(cwe=(501,), owasp=("A04:2021", "API10:2023"), asvs=("V1.2.2",), attack=("T1199", "T1190")),
|
|
261
|
+
"framework-sink-chain": RuleTaxonomy(cwe=(20,), owasp=("A03:2021",), asvs=("V5.1.3",), attack=("T1190",)),
|
|
262
|
+
"vulnerable-dependency": RuleTaxonomy(cwe=(1395,), owasp=("A06:2021",), asvs=("V14.2.1",), attack=("T1190", "T1195.001")),
|
|
263
|
+
"bola-modify": RuleTaxonomy(cwe=(639,), owasp=("A01:2021", "API1:2023"), asvs=("V4.2.1",), attack=("T1190",)),
|
|
264
|
+
"bola-read": RuleTaxonomy(cwe=(639,), owasp=("A01:2021", "API1:2023"), asvs=("V4.2.1",), attack=("T1190",)),
|
|
265
|
+
"unauth-state-change": RuleTaxonomy(cwe=(306,), owasp=("A07:2021", "API2:2023"), asvs=("V1.2.2", "V3.7.1"), attack=("T1190",)),
|
|
266
|
+
"bfla-privileged-route": RuleTaxonomy(cwe=(285,), owasp=("A01:2021", "API5:2023"), asvs=("V4.1.3",), attack=("T1068",)),
|
|
267
|
+
# Taint sinks (#68); speculative-<kind> inherits these
|
|
268
|
+
"subprocess-shell": RuleTaxonomy(cwe=(78,), owasp=("A03:2021",), asvs=("V5.3.8",), attack=("T1059", "T1190")),
|
|
269
|
+
"eval": RuleTaxonomy(cwe=(95, 94), owasp=("A03:2021",), asvs=("V5.2.4",), attack=("T1059", "T1190")),
|
|
270
|
+
"exec": RuleTaxonomy(cwe=(94,), owasp=("A03:2021",), asvs=("V5.2.4",), attack=("T1059", "T1190")),
|
|
271
|
+
"unsafe-deserialization": RuleTaxonomy(cwe=(502,), owasp=("A08:2021",), asvs=("V5.5.3", "V1.5.2"), attack=("T1059", "T1190")),
|
|
272
|
+
"ssti": RuleTaxonomy(cwe=(1336, 94), owasp=("A03:2021",), asvs=("V5.2.5",), attack=("T1059", "T1190")),
|
|
273
|
+
"ssrf": RuleTaxonomy(cwe=(918,), owasp=("A10:2021", "API7:2023"), asvs=("V5.2.6", "V12.6.1"), attack=("T1190", "T1552.005")),
|
|
274
|
+
"nosql-injection": RuleTaxonomy(cwe=(943,), owasp=("A03:2021",), asvs=("V5.3.4",), attack=("T1190",)),
|
|
275
|
+
# Sink catalog expansion (#240)
|
|
276
|
+
"zip-slip": RuleTaxonomy(cwe=(22,), owasp=("A01:2021",), asvs=("V12.3.1",), attack=("T1190",)),
|
|
277
|
+
"code-injection": RuleTaxonomy(cwe=(94,), owasp=("A03:2021",), asvs=("V5.2.4",), attack=("T1059", "T1190")),
|
|
278
|
+
"expression-injection": RuleTaxonomy(cwe=(917, 94), owasp=("A03:2021",), attack=("T1059", "T1190")),
|
|
279
|
+
"jndi-injection": RuleTaxonomy(cwe=(74, 917), owasp=("A03:2021",), attack=("T1059", "T1190")),
|
|
280
|
+
"ldap-injection": RuleTaxonomy(cwe=(90,), owasp=("A03:2021",), asvs=("V5.3.7",), attack=("T1190",)),
|
|
281
|
+
"xpath-injection": RuleTaxonomy(cwe=(643,), owasp=("A03:2021",), asvs=("V5.3.10",), attack=("T1190",)),
|
|
282
|
+
"header-injection": RuleTaxonomy(cwe=(113,), owasp=("A03:2021",), attack=("T1190",)),
|
|
283
|
+
"regex-injection": RuleTaxonomy(cwe=(1333,), owasp=("A03:2021",), attack=("T1499.004",)),
|
|
284
|
+
# Flow-confirmed taint findings (#239)
|
|
285
|
+
"sql-injection": RuleTaxonomy(cwe=(89,), owasp=("A03:2021",), asvs=("V5.3.4", "V5.3.5"), attack=("T1190",)),
|
|
286
|
+
"path-traversal": RuleTaxonomy(cwe=(22,), owasp=("A01:2021",), asvs=("V12.3.1",), attack=("T1190",)),
|
|
287
|
+
"open-redirect": RuleTaxonomy(cwe=(601,), owasp=("A01:2021",), asvs=("V5.1.5",), attack=("T1204.001", "T1566.002")),
|
|
288
|
+
# Crypto (#70)
|
|
289
|
+
"weak-password-hash": RuleTaxonomy(cwe=(916, 328), owasp=("A02:2021",), asvs=("V2.4.1",), attack=("T1110.002",)),
|
|
290
|
+
"weak-cipher": RuleTaxonomy(cwe=(327,), owasp=("A02:2021",), asvs=("V6.2.2", "V6.2.5"), attack=("T1600",)),
|
|
291
|
+
"ecb-mode": RuleTaxonomy(cwe=(327,), owasp=("A02:2021",), asvs=("V6.2.5",), attack=("T1600",)),
|
|
292
|
+
"static-iv-salt": RuleTaxonomy(cwe=(1204, 760), owasp=("A02:2021",), attack=("T1600",)),
|
|
293
|
+
"insecure-random": RuleTaxonomy(cwe=(338,), owasp=("A02:2021",), asvs=("V6.3.1",), attack=("T1600",)),
|
|
294
|
+
"insecure-tls": RuleTaxonomy(cwe=(295,), owasp=("A07:2021", "A02:2021"), asvs=("V9.2.1",), attack=("T1557",)),
|
|
295
|
+
# Web hardening (#71)
|
|
296
|
+
"cors-wildcard-credentials": RuleTaxonomy(cwe=(942,), owasp=("A05:2021", "API8:2023"), asvs=("V14.5.3",), attack=("T1539",)),
|
|
297
|
+
"cors-wildcard-origin": RuleTaxonomy(cwe=(942,), owasp=("A05:2021", "API8:2023"), asvs=("V14.5.3",), attack=("T1190",)),
|
|
298
|
+
"cors-untrusted-origin": RuleTaxonomy(cwe=(346, 942), owasp=("A05:2021", "API8:2023"), asvs=("V14.5.3",), attack=("T1539",)),
|
|
299
|
+
"csrf-unprotected-session": RuleTaxonomy(cwe=(352,), owasp=("A01:2021",), asvs=("V4.2.2", "V3.4.3", "V13.2.3"), attack=("T1190",)),
|
|
300
|
+
"csrf-disabled": RuleTaxonomy(cwe=(352,), owasp=("A01:2021",), asvs=("V4.2.2", "V13.2.3"), attack=("T1190",)),
|
|
301
|
+
"insecure-cookie": RuleTaxonomy(cwe=(614, 1004), owasp=("A05:2021",), asvs=("V3.4.1", "V3.4.2"), attack=("T1539",)),
|
|
302
|
+
"weak-csp": RuleTaxonomy(cwe=(693,), owasp=("A05:2021",), asvs=("V14.4.3",), attack=("T1190", "T1059.007")),
|
|
303
|
+
"debug-enabled": RuleTaxonomy(cwe=(489, 215), owasp=("A05:2021", "API8:2023"), asvs=("V14.3.2",), attack=("T1190",)),
|
|
304
|
+
# Code weaknesses (#77)
|
|
305
|
+
"prototype-pollution": RuleTaxonomy(cwe=(1321,), owasp=("A08:2021",), attack=("T1190", "T1059.007")),
|
|
306
|
+
"mass-assignment": RuleTaxonomy(cwe=(915,), owasp=("A08:2021", "API3:2023"), asvs=("V5.1.2",), attack=("T1190",)),
|
|
307
|
+
"jwt-weakness": RuleTaxonomy(cwe=(347,), owasp=("A02:2021", "API2:2023"), asvs=("V3.5.3",), attack=("T1190", "T1606")),
|
|
308
|
+
"jwt-alg-confusion": RuleTaxonomy(cwe=(347, 327), owasp=("A02:2021", "API2:2023"), asvs=("V3.5.3",), attack=("T1606",)),
|
|
309
|
+
"jwt-unverified-decode": RuleTaxonomy(cwe=(345, 347), owasp=("A07:2021", "API2:2023"), asvs=("V3.5.3",), attack=("T1606",)),
|
|
310
|
+
"jwt-claims-unchecked": RuleTaxonomy(cwe=(613,), owasp=("A07:2021", "API2:2023"), asvs=("V3.5.3", "V3.3.1"), attack=("T1550.001",)),
|
|
311
|
+
"jwt-header-trust": RuleTaxonomy(cwe=(345, 22, 89, 918), owasp=("A07:2021", "API2:2023"), asvs=("V3.5.3",), attack=("T1606",)),
|
|
312
|
+
"jwt-weak-secret": RuleTaxonomy(cwe=(798, 326), owasp=("A02:2021", "API2:2023"), asvs=("V3.5.2", "V2.10.4"), attack=("T1606", "T1110.002")),
|
|
313
|
+
"oauth-missing-state": RuleTaxonomy(cwe=(352,), owasp=("A01:2021", "API2:2023"), attack=("T1528",)),
|
|
314
|
+
"oauth-implicit-flow": RuleTaxonomy(cwe=(522,), owasp=("A07:2021", "API2:2023"), attack=("T1528",)),
|
|
315
|
+
"oauth-redirect-uri-loose": RuleTaxonomy(cwe=(601, 346), owasp=("A07:2021", "API2:2023"), attack=("T1528",)),
|
|
316
|
+
"oauth-missing-pkce": RuleTaxonomy(cwe=(345,), owasp=("A07:2021", "API2:2023"), attack=("T1528",)),
|
|
317
|
+
"session-fixation": RuleTaxonomy(cwe=(384,), owasp=("A07:2021",), asvs=("V3.2.1",), attack=("T1539",)),
|
|
318
|
+
"session-weak-secret": RuleTaxonomy(cwe=(798, 326), owasp=("A02:2021", "A07:2021"), attack=("T1606", "T1110.002")),
|
|
319
|
+
"xxe": RuleTaxonomy(cwe=(611,), owasp=("A05:2021",), asvs=("V5.5.2",), attack=("T1190",)),
|
|
320
|
+
"redos": RuleTaxonomy(cwe=(1333,), owasp=("API4:2023",), attack=("T1499.004",)),
|
|
321
|
+
"insecure-upload": RuleTaxonomy(cwe=(22, 434), owasp=("A01:2021", "A04:2021"), asvs=("V12.3.1", "V12.2.1"), attack=("T1190", "T1505.003")),
|
|
322
|
+
"graphql-exposure": RuleTaxonomy(cwe=(200,), owasp=("A05:2021", "API8:2023"), attack=("T1190",)),
|
|
323
|
+
"graphql-no-query-limits": RuleTaxonomy(cwe=(770,), owasp=("API4:2023",), asvs=("V13.4.1",), attack=("T1499.003",)),
|
|
324
|
+
"graphql-batching": RuleTaxonomy(cwe=(770, 307), owasp=("API4:2023", "API2:2023"), asvs=("V13.4.1", "V2.2.1"), attack=("T1110", "T1499.003")),
|
|
325
|
+
"prompt-injection-attempt": RuleTaxonomy(cwe=(1427,), owasp=("LLM01:2025",), attack=("T1027",)),
|
|
326
|
+
# Native C/C++ sinks (#189). The OWASP Top 10 has no memory-safety
|
|
327
|
+
# category; A03 (Injection, which carries CWE-20 improper input
|
|
328
|
+
# validation) is the closest fit. ASVS V5.4 is "Memory, String, and
|
|
329
|
+
# Unmanaged Code".
|
|
330
|
+
"unbounded-copy": RuleTaxonomy(cwe=(120, 121, 242), owasp=("A03:2021",), asvs=("V5.4.1",), attack=("T1190", "T1068")),
|
|
331
|
+
"format-string": RuleTaxonomy(cwe=(134,), owasp=("A03:2021",), asvs=("V5.4.2",), attack=("T1190", "T1068")),
|
|
332
|
+
"native-command-exec": RuleTaxonomy(cwe=(78,), owasp=("A03:2021",), asvs=("V5.3.8",), attack=("T1059.004", "T1190")),
|
|
333
|
+
"tainted-copy-length": RuleTaxonomy(cwe=(805, 787), owasp=("A03:2021",), asvs=("V5.4.1",), attack=("T1190", "T1068")),
|
|
334
|
+
"alloc-size-overflow": RuleTaxonomy(cwe=(680, 190), owasp=("A03:2021",), asvs=("V5.4.3",), attack=("T1190", "T1068")),
|
|
335
|
+
# CI workflows (#142)
|
|
336
|
+
"script-injection": RuleTaxonomy(cwe=(78, 94), owasp=("A03:2021", "A08:2021"), attack=("T1059.004", "T1195.002")),
|
|
337
|
+
"pr-target-checkout": RuleTaxonomy(cwe=(829,), owasp=("A08:2021",), asvs=("V12.3.6",), attack=("T1195.002",)),
|
|
338
|
+
"unpinned-action": RuleTaxonomy(cwe=(829, 1357), owasp=("A08:2021",), asvs=("V14.2.4",), attack=("T1195.001",)),
|
|
339
|
+
"secret-in-run": RuleTaxonomy(cwe=(532, 214), owasp=("A09:2021",), asvs=("V7.1.1",), attack=("T1552",)),
|
|
340
|
+
"broad-permissions": RuleTaxonomy(cwe=(250,), owasp=("A01:2021",), attack=("T1078",)),
|
|
341
|
+
"self-hosted-pr": RuleTaxonomy(cwe=(829,), owasp=("A08:2021",), attack=("T1195.002", "T1584.004")),
|
|
342
|
+
# CI workflows, round 2 (#246)
|
|
343
|
+
"workflow-run-artifact-poisoning": RuleTaxonomy(cwe=(829,), owasp=("A08:2021",), asvs=("V10.3.2", "V12.3.6"), attack=("T1195.002",)),
|
|
344
|
+
"issue-comment-pr-checkout": RuleTaxonomy(cwe=(829,), owasp=("A08:2021",), asvs=("V12.3.6",), attack=("T1195.002",)),
|
|
345
|
+
"github-script-injection": RuleTaxonomy(cwe=(94,), owasp=("A03:2021", "A08:2021"), asvs=("V5.2.4",), attack=("T1059.007", "T1195.002")),
|
|
346
|
+
"github-env-injection": RuleTaxonomy(cwe=(94, 15), owasp=("A03:2021", "A08:2021"), attack=("T1574", "T1195.002")),
|
|
347
|
+
"default-token-permissions": RuleTaxonomy(cwe=(250,), owasp=("A01:2021",), attack=("T1078",)),
|
|
348
|
+
"oidc-on-untrusted-trigger": RuleTaxonomy(cwe=(250,), owasp=("A01:2021",), attack=("T1078.004",)),
|
|
349
|
+
"secrets-inherit": RuleTaxonomy(cwe=(250,), owasp=("A01:2021",), attack=("T1552",)),
|
|
350
|
+
"checkout-persist-credentials": RuleTaxonomy(cwe=(522,), owasp=("A04:2021",), attack=("T1552.001",)),
|
|
351
|
+
"cache-poisoning-pr-target": RuleTaxonomy(cwe=(349,), owasp=("A08:2021",), attack=("T1195.002",)),
|
|
352
|
+
"docker-action-unpinned": RuleTaxonomy(cwe=(829, 1357), owasp=("A08:2021",), asvs=("V14.2.4",), attack=("T1195.001",)),
|
|
353
|
+
"curl-pipe-shell": RuleTaxonomy(cwe=(494,), owasp=("A08:2021",), asvs=("V10.3.2",), attack=("T1105", "T1195.002")),
|
|
354
|
+
# Dependency supply-chain risk (#247).
|
|
355
|
+
"dependency-confusion": RuleTaxonomy(cwe=(427, 829), owasp=("A08:2021", "A06:2021"), asvs=("V14.2.4",), attack=("T1195.001",)),
|
|
356
|
+
"typosquat-candidate": RuleTaxonomy(cwe=(1357, 829), owasp=("A06:2021", "A08:2021"), asvs=("V14.2.4",), attack=("T1195.001",)),
|
|
357
|
+
"mutable-vcs-dependency": RuleTaxonomy(cwe=(494, 829), owasp=("A08:2021", "A06:2021"), asvs=("V14.2.4",), attack=("T1195.001",)),
|
|
358
|
+
"install-script": RuleTaxonomy(cwe=(829, 494), owasp=("A08:2021",), attack=("T1195.001", "T1059")),
|
|
359
|
+
"unlocked-manifest": RuleTaxonomy(cwe=(353, 494), owasp=("A08:2021", "A06:2021"), asvs=("V14.2.4",), attack=("T1195.001",)),
|
|
360
|
+
"insecure-registry": RuleTaxonomy(cwe=(319, 295, 494), owasp=("A02:2021", "A08:2021"), attack=("T1557", "T1195.001")),
|
|
361
|
+
# Cloud / IaC / container misconfigurations (terraform#4, iac#1).
|
|
362
|
+
"iac-module-unpinned": RuleTaxonomy(cwe=(829, 494), owasp=("A08:2021",), asvs=("V14.2.4",), attack=("T1195.001",)),
|
|
363
|
+
"public-network-access": RuleTaxonomy(cwe=(668, 284), owasp=("A05:2021", "A01:2021"), attack=("T1190", "T1133")),
|
|
364
|
+
"public-cluster-endpoint": RuleTaxonomy(cwe=(668, 284), owasp=("A05:2021",), attack=("T1133", "T1190")),
|
|
365
|
+
"plaintext-listener": RuleTaxonomy(cwe=(319,), owasp=("A02:2021",), asvs=("V9.1.1",), attack=("T1557",)),
|
|
366
|
+
"api-no-authorizer": RuleTaxonomy(cwe=(306,), owasp=("A07:2021", "API2:2023"), attack=("T1190",)),
|
|
367
|
+
"unencrypted-storage": RuleTaxonomy(cwe=(311,), owasp=("A02:2021",), asvs=("V6.1.1",), attack=("T1530",)),
|
|
368
|
+
"public-data-access": RuleTaxonomy(cwe=(732, 200), owasp=("A01:2021",), attack=("T1530",)),
|
|
369
|
+
"public-invoker": RuleTaxonomy(cwe=(284, 306), owasp=("A01:2021",), attack=("T1190",)),
|
|
370
|
+
"privileged-container": RuleTaxonomy(cwe=(250,), owasp=("A05:2021",), attack=("T1611",)),
|
|
371
|
+
"privilege-escalation-allowed": RuleTaxonomy(cwe=(269, 250), owasp=("A05:2021",), attack=("T1548.001",)),
|
|
372
|
+
"container-runs-as-root": RuleTaxonomy(cwe=(250,), owasp=("A05:2021",), attack=("T1611",)),
|
|
373
|
+
"missing-security-context": RuleTaxonomy(cwe=(1188, 250), owasp=("A05:2021",), attack=("T1611",)),
|
|
374
|
+
"host-path-mount": RuleTaxonomy(cwe=(668, 250), owasp=("A05:2021",), attack=("T1611",)),
|
|
375
|
+
"host-namespace-shared": RuleTaxonomy(cwe=(668, 250), owasp=("A05:2021",), attack=("T1611",)),
|
|
376
|
+
"dangerous-capability": RuleTaxonomy(cwe=(250,), owasp=("A05:2021",), attack=("T1611",)),
|
|
377
|
+
"security-profile-disabled": RuleTaxonomy(cwe=(693,), owasp=("A05:2021",), attack=("T1611",)),
|
|
378
|
+
"exposed-service": RuleTaxonomy(cwe=(668,), owasp=("A05:2021",), attack=("T1190", "T1133")),
|
|
379
|
+
"unpinned-container-image": RuleTaxonomy(cwe=(829, 494), owasp=("A08:2021", "A06:2021"), attack=("T1195.002",)),
|
|
380
|
+
"dockerfile-remote-add": RuleTaxonomy(cwe=(494,), owasp=("A08:2021",), asvs=("V10.3.2",), attack=("T1105", "T1195.002")),
|
|
381
|
+
"dockerfile-curl-pipe-shell": RuleTaxonomy(cwe=(494,), owasp=("A08:2021",), asvs=("V10.3.2",), attack=("T1105", "T1195.002")),
|
|
382
|
+
"rbac-wildcard": RuleTaxonomy(cwe=(269, 732), owasp=("A01:2021",), attack=("T1078", "T1068")),
|
|
383
|
+
"rbac-escalation": RuleTaxonomy(cwe=(269,), owasp=("A01:2021",), attack=("T1098", "T1068", "T1609")),
|
|
384
|
+
"rbac-secret-access": RuleTaxonomy(cwe=(522, 732), owasp=("A01:2021",), attack=("T1552.007",)),
|
|
385
|
+
"cluster-admin-binding": RuleTaxonomy(cwe=(269, 250), owasp=("A01:2021",), attack=("T1078", "T1098")),
|
|
386
|
+
# App attack surface from platform plugins (#188, #190)
|
|
387
|
+
"apple-ats-insecure-loads": RuleTaxonomy(cwe=(319,), owasp=("A02:2021",), asvs=("V9.1.1",), attack=("T1557",)),
|
|
388
|
+
"apple-custom-url-scheme": RuleTaxonomy(cwe=(939,), owasp=("A01:2021",), attack=("T1204.001",)),
|
|
389
|
+
"apple-webview-js-injection": RuleTaxonomy(cwe=(94, 79), owasp=("A03:2021",), asvs=("V5.3.3",), attack=("T1059.007",)),
|
|
390
|
+
"apple-insecure-secret-storage": RuleTaxonomy(cwe=(312, 922), owasp=("A04:2021",), attack=("T1552.001",)),
|
|
391
|
+
"apple-pasteboard-secret": RuleTaxonomy(cwe=(200,), owasp=("A01:2021",), attack=("T1115",)),
|
|
392
|
+
"apple-hardened-runtime-exception": RuleTaxonomy(cwe=(693, 114), owasp=("A05:2021",), attack=("T1574",)),
|
|
393
|
+
"apple-debuggable-entitlement": RuleTaxonomy(cwe=(489,), owasp=("A05:2021",), attack=("T1055",)),
|
|
394
|
+
"apple-xpc-unvalidated-peer": RuleTaxonomy(cwe=(306, 284), owasp=("A07:2021", "A01:2021"), attack=("T1068",)),
|
|
395
|
+
"apple-dynamic-dispatch": RuleTaxonomy(cwe=(470, 114), owasp=("A03:2021",), attack=("T1129",)),
|
|
396
|
+
# Anomalies (#78)
|
|
397
|
+
"auth-outlier": RuleTaxonomy(cwe=(862,), owasp=("A01:2021", "API5:2023"), asvs=("V4.1.3", "V13.1.4"), attack=("T1190",)),
|
|
398
|
+
"validation-outlier": RuleTaxonomy(cwe=(20,), owasp=("A03:2021",), asvs=("V5.1.3",), attack=("T1190",)),
|
|
399
|
+
"method-outlier": RuleTaxonomy(cwe=(749,), owasp=("A01:2021", "API5:2023"), asvs=("V13.2.1",), attack=("T1190",)),
|
|
400
|
+
"invariant-violation": RuleTaxonomy(cwe=(693,), owasp=("A04:2021",), attack=("T1190",)),
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
_SPECULATIVE = "speculative-"
|
|
404
|
+
_ASVS_ID = re.compile(r"V\d{1,2}\.\d{1,2}\.\d{1,2}")
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def taxonomy_for(rule_id: str | None) -> RuleTaxonomy | None:
|
|
408
|
+
"""The registered taxonomy for ``rule_id``, or ``None``. A
|
|
409
|
+
``speculative-<rule>`` id resolves to its base rule."""
|
|
410
|
+
if not rule_id:
|
|
411
|
+
return None
|
|
412
|
+
entry = RULE_TAXONOMY.get(rule_id)
|
|
413
|
+
if entry is None and rule_id.startswith(_SPECULATIVE):
|
|
414
|
+
entry = RULE_TAXONOMY.get(rule_id[len(_SPECULATIVE):])
|
|
415
|
+
return entry
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
def register(rule_id: str, entry: RuleTaxonomy) -> None:
|
|
419
|
+
"""Register (or replace) a rule's taxonomy at runtime, for plugins that
|
|
420
|
+
emit their own rule ids. Validates the ids against the catalogs here."""
|
|
421
|
+
problems = validate_entry(entry)
|
|
422
|
+
if problems:
|
|
423
|
+
raise ValueError(f"invalid taxonomy for {rule_id!r}: {'; '.join(problems)}")
|
|
424
|
+
RULE_TAXONOMY[rule_id] = entry
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
def validate_entry(entry: RuleTaxonomy) -> list[str]:
|
|
428
|
+
"""Problems with an entry: missing CWE/OWASP, or ids unknown to the
|
|
429
|
+
catalogs above (add the id and its name there first)."""
|
|
430
|
+
problems: list[str] = []
|
|
431
|
+
if not entry.cwe:
|
|
432
|
+
problems.append("no CWE")
|
|
433
|
+
if not entry.owasp:
|
|
434
|
+
problems.append("no OWASP category")
|
|
435
|
+
problems += [f"CWE-{c} not in CWE_NAMES" for c in entry.cwe if c not in CWE_NAMES]
|
|
436
|
+
problems += [f"{o} not in OWASP_CATEGORIES" for o in entry.owasp if o not in OWASP_CATEGORIES]
|
|
437
|
+
problems += [f"{t} not in ATTACK_TECHNIQUES" for t in entry.attack if t not in ATTACK_TECHNIQUES]
|
|
438
|
+
problems += [f"malformed ASVS id {a}" for a in entry.asvs if not _ASVS_ID.fullmatch(a)]
|
|
439
|
+
return problems
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
def taxonomy_label(rule_id: str | None) -> str:
|
|
443
|
+
"""Short inline label for Markdown, e.g. ``CWE-918 · A10:2021 · API7:2023``.
|
|
444
|
+
Empty when the rule is unregistered."""
|
|
445
|
+
entry = taxonomy_for(rule_id)
|
|
446
|
+
if entry is None:
|
|
447
|
+
return ""
|
|
448
|
+
return " · ".join([*entry.cwe_ids[:2], *entry.owasp[:2]])
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
__all__ = [
|
|
452
|
+
"ATTACK_TECHNIQUES",
|
|
453
|
+
"CWE_NAMES",
|
|
454
|
+
"INFORMATIONAL_RULES",
|
|
455
|
+
"OWASP_CATEGORIES",
|
|
456
|
+
"RULE_TAXONOMY",
|
|
457
|
+
"RuleTaxonomy",
|
|
458
|
+
"attack_url",
|
|
459
|
+
"cwe_tag",
|
|
460
|
+
"cwe_url",
|
|
461
|
+
"register",
|
|
462
|
+
"taxonomy_for",
|
|
463
|
+
"taxonomy_label",
|
|
464
|
+
"validate_entry",
|
|
465
|
+
]
|