@intentsolutionsio/penetration-tester 2.0.0 → 3.0.4
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.
- package/.claude-plugin/plugin.json +8 -3
- package/README.md +8 -0
- package/commands/pentest.md +5 -0
- package/package.json +8 -3
- package/skills/analyzing-tls-config/SKILL.md +221 -0
- package/skills/analyzing-tls-config/references/AUTHORIZATION.md +133 -0
- package/skills/analyzing-tls-config/references/PLAYBOOK.md +267 -0
- package/skills/analyzing-tls-config/references/THEORY.md +128 -0
- package/skills/analyzing-tls-config/scripts/analyze_tls.py +415 -0
- package/skills/auditing-cors-policy/SKILL.md +186 -0
- package/skills/auditing-cors-policy/references/PLAYBOOK.md +220 -0
- package/skills/auditing-cors-policy/references/THEORY.md +142 -0
- package/skills/auditing-cors-policy/scripts/audit_cors.py +350 -0
- package/skills/auditing-npm-dependencies/SKILL.md +254 -0
- package/skills/auditing-npm-dependencies/references/PLAYBOOK.md +175 -0
- package/skills/auditing-npm-dependencies/references/THEORY.md +122 -0
- package/skills/auditing-npm-dependencies/scripts/audit_npm.py +408 -0
- package/skills/auditing-python-dependencies/SKILL.md +251 -0
- package/skills/auditing-python-dependencies/references/PLAYBOOK.md +193 -0
- package/skills/auditing-python-dependencies/references/THEORY.md +122 -0
- package/skills/auditing-python-dependencies/scripts/audit_python.py +459 -0
- package/skills/checking-http-security-headers/SKILL.md +176 -0
- package/skills/checking-http-security-headers/references/PLAYBOOK.md +212 -0
- package/skills/checking-http-security-headers/references/THEORY.md +137 -0
- package/skills/checking-http-security-headers/scripts/check_headers.py +362 -0
- package/skills/checking-license-compliance/SKILL.md +225 -0
- package/skills/checking-license-compliance/references/PLAYBOOK.md +161 -0
- package/skills/checking-license-compliance/references/THEORY.md +152 -0
- package/skills/checking-license-compliance/scripts/check_licenses.py +461 -0
- package/skills/composing-vulnerability-report/SKILL.md +212 -0
- package/skills/composing-vulnerability-report/references/PLAYBOOK.md +180 -0
- package/skills/composing-vulnerability-report/references/THEORY.md +178 -0
- package/skills/composing-vulnerability-report/scripts/compose_report.py +396 -0
- package/skills/confirming-pentest-authorization/SKILL.md +247 -0
- package/skills/confirming-pentest-authorization/references/PLAYBOOK.md +189 -0
- package/skills/confirming-pentest-authorization/references/THEORY.md +167 -0
- package/skills/confirming-pentest-authorization/scripts/check_authorization.py +457 -0
- package/skills/defining-pentest-scope/SKILL.md +227 -0
- package/skills/defining-pentest-scope/references/PLAYBOOK.md +238 -0
- package/skills/defining-pentest-scope/references/THEORY.md +170 -0
- package/skills/defining-pentest-scope/scripts/define_scope.py +472 -0
- package/skills/detecting-command-injection-patterns/SKILL.md +144 -0
- package/skills/detecting-command-injection-patterns/references/PLAYBOOK.md +302 -0
- package/skills/detecting-command-injection-patterns/references/THEORY.md +206 -0
- package/skills/detecting-command-injection-patterns/scripts/scan_cmdi.py +290 -0
- package/skills/detecting-debug-endpoints/SKILL.md +207 -0
- package/skills/detecting-debug-endpoints/references/PLAYBOOK.md +402 -0
- package/skills/detecting-debug-endpoints/references/THEORY.md +218 -0
- package/skills/detecting-debug-endpoints/scripts/probe_debug.py +518 -0
- package/skills/detecting-directory-listing/SKILL.md +206 -0
- package/skills/detecting-directory-listing/references/PLAYBOOK.md +277 -0
- package/skills/detecting-directory-listing/references/THEORY.md +203 -0
- package/skills/detecting-directory-listing/scripts/probe_directory_listing.py +180 -0
- package/skills/detecting-eval-exec-usage/SKILL.md +128 -0
- package/skills/detecting-eval-exec-usage/references/PLAYBOOK.md +306 -0
- package/skills/detecting-eval-exec-usage/references/THEORY.md +159 -0
- package/skills/detecting-eval-exec-usage/scripts/scan_eval.py +223 -0
- package/skills/detecting-exposed-secrets-files/SKILL.md +179 -0
- package/skills/detecting-exposed-secrets-files/references/PLAYBOOK.md +274 -0
- package/skills/detecting-exposed-secrets-files/references/THEORY.md +174 -0
- package/skills/detecting-exposed-secrets-files/scripts/probe_secrets.py +207 -0
- package/skills/detecting-insecure-deserialization/SKILL.md +148 -0
- package/skills/detecting-insecure-deserialization/references/PLAYBOOK.md +333 -0
- package/skills/detecting-insecure-deserialization/references/THEORY.md +199 -0
- package/skills/detecting-insecure-deserialization/scripts/scan_deserialization.py +250 -0
- package/skills/detecting-sql-injection-patterns/SKILL.md +161 -0
- package/skills/detecting-sql-injection-patterns/references/PLAYBOOK.md +317 -0
- package/skills/detecting-sql-injection-patterns/references/THEORY.md +261 -0
- package/skills/detecting-sql-injection-patterns/scripts/scan_sqli.py +354 -0
- package/skills/detecting-ssl-cert-issues/SKILL.md +182 -0
- package/skills/detecting-ssl-cert-issues/references/PLAYBOOK.md +203 -0
- package/skills/detecting-ssl-cert-issues/references/THEORY.md +133 -0
- package/skills/detecting-ssl-cert-issues/scripts/check_cert_chain.py +481 -0
- package/skills/detecting-weak-cryptography/SKILL.md +147 -0
- package/skills/detecting-weak-cryptography/references/PLAYBOOK.md +466 -0
- package/skills/detecting-weak-cryptography/references/THEORY.md +194 -0
- package/skills/detecting-weak-cryptography/scripts/scan_weak_crypto.py +417 -0
- package/skills/fingerprinting-server-software/SKILL.md +191 -0
- package/skills/fingerprinting-server-software/references/PLAYBOOK.md +337 -0
- package/skills/fingerprinting-server-software/references/THEORY.md +183 -0
- package/skills/fingerprinting-server-software/scripts/fingerprint_server.py +347 -0
- package/skills/generating-executive-summary/SKILL.md +261 -0
- package/skills/generating-executive-summary/references/PLAYBOOK.md +201 -0
- package/skills/generating-executive-summary/references/THEORY.md +195 -0
- package/skills/generating-executive-summary/scripts/exec_summary.py +538 -0
- package/skills/mapping-findings-to-owasp-top10/SKILL.md +235 -0
- package/skills/mapping-findings-to-owasp-top10/references/PLAYBOOK.md +193 -0
- package/skills/mapping-findings-to-owasp-top10/references/THEORY.md +160 -0
- package/skills/mapping-findings-to-owasp-top10/scripts/map_owasp.py +540 -0
- package/skills/performing-penetration-testing/SKILL.md +282 -190
- package/skills/performing-penetration-testing/references/OWASP_TOP_10.md +22 -0
- package/skills/performing-penetration-testing/references/REMEDIATION_PLAYBOOK.md +46 -0
- package/skills/performing-penetration-testing/references/SECURITY_HEADERS.md +41 -0
- package/skills/performing-penetration-testing/scripts/code_security_scanner.py +144 -79
- package/skills/performing-penetration-testing/scripts/dependency_auditor.py +116 -93
- package/skills/performing-penetration-testing/scripts/security_scanner.py +574 -446
- package/skills/probing-dangerous-http-methods/SKILL.md +182 -0
- package/skills/probing-dangerous-http-methods/references/PLAYBOOK.md +234 -0
- package/skills/probing-dangerous-http-methods/references/THEORY.md +145 -0
- package/skills/probing-dangerous-http-methods/scripts/probe_methods.py +263 -0
- package/skills/recording-pentest-engagement/SKILL.md +253 -0
- package/skills/recording-pentest-engagement/references/PLAYBOOK.md +203 -0
- package/skills/recording-pentest-engagement/references/THEORY.md +195 -0
- package/skills/recording-pentest-engagement/scripts/record_engagement.py +461 -0
- package/skills/scanning-for-hardcoded-secrets/SKILL.md +215 -0
- package/skills/scanning-for-hardcoded-secrets/references/PLAYBOOK.md +325 -0
- package/skills/scanning-for-hardcoded-secrets/references/THEORY.md +175 -0
- package/skills/scanning-for-hardcoded-secrets/scripts/scan_secrets.py +395 -0
- package/skills/tracing-transitive-vulnerabilities/SKILL.md +235 -0
- package/skills/tracing-transitive-vulnerabilities/references/PLAYBOOK.md +233 -0
- package/skills/tracing-transitive-vulnerabilities/references/THEORY.md +138 -0
- package/skills/tracing-transitive-vulnerabilities/scripts/trace_vulns.py +484 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mapping-findings-to-owasp-top10
|
|
3
|
+
description: |
|
|
4
|
+
Annotate every pentest finding with its OWASP Top 10 (2021)
|
|
5
|
+
category by applying a deterministic rule table keyed on source
|
|
6
|
+
skill, finding category, detail keywords, and CWE identifier when
|
|
7
|
+
present. Produces an enriched findings JSONL plus a per-category
|
|
8
|
+
rollup report showing how findings distribute across A01 through
|
|
9
|
+
A10. Required for customer-facing OWASP coverage sections and
|
|
10
|
+
compliance contexts (PCI DSS 6.5, SOC2 CC7, ISO 27001 A.14.2).
|
|
11
|
+
Use when: enriching findings after cluster 1-4 scans, regenerating
|
|
12
|
+
the report with OWASP tags, producing the OWASP coverage section
|
|
13
|
+
for an exec summary, or auditing engagement OWASP coverage.
|
|
14
|
+
Threshold: unclassifiable findings emitted as INFO with UNMAPPED
|
|
15
|
+
category for operator review.
|
|
16
|
+
Trigger with: "map to OWASP", "owasp top 10 mapping",
|
|
17
|
+
"annotate owasp categories", "owasp coverage check".
|
|
18
|
+
allowed-tools:
|
|
19
|
+
- Read
|
|
20
|
+
- Write
|
|
21
|
+
- Bash(python3:*)
|
|
22
|
+
- Glob
|
|
23
|
+
disallowed-tools:
|
|
24
|
+
- Bash(rm:*)
|
|
25
|
+
- Bash(curl:*)
|
|
26
|
+
- Bash(wget:*)
|
|
27
|
+
- Write(.env)
|
|
28
|
+
- Edit(.env)
|
|
29
|
+
version: 3.0.0-dev
|
|
30
|
+
author: Jeremy Longshore <jeremy@intentsolutions.io>
|
|
31
|
+
license: MIT
|
|
32
|
+
compatibility: Designed for Claude Code
|
|
33
|
+
tags:
|
|
34
|
+
- security
|
|
35
|
+
- reporting
|
|
36
|
+
- owasp
|
|
37
|
+
- top10
|
|
38
|
+
- pentest
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
# Mapping Findings to OWASP Top 10
|
|
42
|
+
|
|
43
|
+
## Overview
|
|
44
|
+
|
|
45
|
+
OWASP Top 10 is the canonical taxonomy of web-application risk
|
|
46
|
+
categories. Every customer-facing pentest report has an "OWASP
|
|
47
|
+
coverage" section because customers, auditors, and insurers
|
|
48
|
+
expect to see findings mapped against the Top 10. Without the
|
|
49
|
+
mapping, a long list of CVEs and misconfigurations reads as
|
|
50
|
+
noise; with the mapping, it reads as a structured assessment.
|
|
51
|
+
|
|
52
|
+
This skill applies a deterministic rule table to annotate each
|
|
53
|
+
finding with its OWASP category. Rules are keyed on:
|
|
54
|
+
|
|
55
|
+
1. **Source skill ID** (a finding from `auditing-npm-dependencies`
|
|
56
|
+
is almost always A06 — Vulnerable and Outdated Components).
|
|
57
|
+
2. **Finding category** (the per-skill category tag, e.g.
|
|
58
|
+
`dependency-vulnerability`, `engagement-scope`).
|
|
59
|
+
3. **CWE identifier** if present (CWE → OWASP is a well-trodden
|
|
60
|
+
mapping; OWASP themselves publish the cross-walk).
|
|
61
|
+
4. **Detail keywords** as a fallback when the above don't
|
|
62
|
+
determine a category.
|
|
63
|
+
|
|
64
|
+
Output is an enriched JSONL (each finding gets an `owasp_category`
|
|
65
|
+
field) plus a coverage report showing how the engagement's
|
|
66
|
+
findings distribute across A01-A10. UNMAPPED findings are
|
|
67
|
+
surfaced for human review — extend the rule table or accept the
|
|
68
|
+
finding as cross-cutting (some findings genuinely don't fit a
|
|
69
|
+
single A0X bucket).
|
|
70
|
+
|
|
71
|
+
## When the skill produces findings
|
|
72
|
+
|
|
73
|
+
| Finding | Severity | Threshold | Affected control |
|
|
74
|
+
|---|---|---|---|
|
|
75
|
+
| Finding unmapped after rule application | **INFO** | No rule matched the finding | (operational) |
|
|
76
|
+
| Source JSONL unparseable | **HIGH** | Standard JSONL parse error | (operational) |
|
|
77
|
+
| Annotation written back successfully | **INFO** | Confirmation per source file | (informational) |
|
|
78
|
+
| Coverage report generated | **INFO** | Coverage report path emitted | (informational) |
|
|
79
|
+
| Engagement covers all 10 categories | **INFO** | At least one finding in each A01-A10 bucket | (positive observation) |
|
|
80
|
+
| Engagement covers <5 of 10 categories | **MEDIUM** | Suggests scope may have been narrow | (informational) |
|
|
81
|
+
|
|
82
|
+
## OWASP Top 10 (2021) reference
|
|
83
|
+
|
|
84
|
+
| Category | Description |
|
|
85
|
+
|---|---|
|
|
86
|
+
| A01:2021 | Broken Access Control |
|
|
87
|
+
| A02:2021 | Cryptographic Failures |
|
|
88
|
+
| A03:2021 | Injection |
|
|
89
|
+
| A04:2021 | Insecure Design |
|
|
90
|
+
| A05:2021 | Security Misconfiguration |
|
|
91
|
+
| A06:2021 | Vulnerable and Outdated Components |
|
|
92
|
+
| A07:2021 | Identification and Authentication Failures |
|
|
93
|
+
| A08:2021 | Software and Data Integrity Failures |
|
|
94
|
+
| A09:2021 | Security Logging and Monitoring Failures |
|
|
95
|
+
| A10:2021 | Server-Side Request Forgery |
|
|
96
|
+
|
|
97
|
+
## Prerequisites
|
|
98
|
+
|
|
99
|
+
- Python 3.9+
|
|
100
|
+
- One or more cluster 1-4 findings files
|
|
101
|
+
- Optional `.owasp-overrides.yaml` for engagement-specific
|
|
102
|
+
classification rules
|
|
103
|
+
|
|
104
|
+
## Instructions
|
|
105
|
+
|
|
106
|
+
### Step 1 — Identify findings sources
|
|
107
|
+
|
|
108
|
+
Default: every file under `engagement/findings/*.json[l]`.
|
|
109
|
+
Override with `--source FILE` (repeatable).
|
|
110
|
+
|
|
111
|
+
### Step 2 — Run the mapper
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
python3 ./scripts/map_owasp.py engagements/acme-2026-q2/
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Options:
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
Usage: map_owasp.py PATH [OPTIONS]
|
|
121
|
+
|
|
122
|
+
Options:
|
|
123
|
+
--source FILE Specific findings file (repeatable)
|
|
124
|
+
--enrich-output FILE Write annotated findings JSONL here
|
|
125
|
+
(default: PATH/findings/all-with-owasp.jsonl)
|
|
126
|
+
--coverage-output FILE Coverage report path
|
|
127
|
+
(default: PATH/reports/owasp-coverage.md)
|
|
128
|
+
--overrides FILE Optional rule-overrides YAML
|
|
129
|
+
--output FILE Operational findings output
|
|
130
|
+
--format FMT json | jsonl | markdown (default: markdown)
|
|
131
|
+
--min-severity SEV default info
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Step 3 — Review unmapped findings
|
|
135
|
+
|
|
136
|
+
UNMAPPED findings are surfaced as INFO. For each:
|
|
137
|
+
|
|
138
|
+
1. Check whether a CWE was present; if so, the canonical CWE →
|
|
139
|
+
OWASP cross-walk should have caught it. Extend the rule table.
|
|
140
|
+
2. Check whether the finding's source skill ID is in the rule
|
|
141
|
+
table; if not, add a skill-level default.
|
|
142
|
+
3. If the finding genuinely doesn't fit a single A0X bucket,
|
|
143
|
+
accept UNMAPPED and document in the engagement notes.
|
|
144
|
+
|
|
145
|
+
### Step 4 — Read the coverage report
|
|
146
|
+
|
|
147
|
+
The coverage report lists each A0X category with:
|
|
148
|
+
|
|
149
|
+
- Count of findings mapped to that category
|
|
150
|
+
- Severity breakdown within the category
|
|
151
|
+
- Pointer to specific findings
|
|
152
|
+
|
|
153
|
+
For an engagement intended as broad-coverage testing, all ten
|
|
154
|
+
categories should have at least one entry. Categories with zero
|
|
155
|
+
findings either reflect scope ("we didn't test for this") or
|
|
156
|
+
clean results ("we tested and found nothing").
|
|
157
|
+
|
|
158
|
+
## Examples
|
|
159
|
+
|
|
160
|
+
### Example 1 — End-of-engagement enrichment
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
python3 ./scripts/map_owasp.py engagements/acme-2026-q2/
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Produces `engagements/acme-2026-q2/findings/all-with-owasp.jsonl`
|
|
167
|
+
(enriched findings) and `engagements/acme-2026-q2/reports/owasp-coverage.md`
|
|
168
|
+
(coverage report).
|
|
169
|
+
|
|
170
|
+
### Example 2 — Apply engagement-specific overrides
|
|
171
|
+
|
|
172
|
+
```yaml
|
|
173
|
+
# .owasp-overrides.yaml — engagement-specific classifications
|
|
174
|
+
- skill_id: auditing-cors-policy
|
|
175
|
+
owasp_category: A05:2021 — Security Misconfiguration
|
|
176
|
+
reason: customer treats CORS as misconfig, not access-control
|
|
177
|
+
- skill_id: scanning-for-hardcoded-secrets
|
|
178
|
+
detail_contains: ".env"
|
|
179
|
+
owasp_category: A02:2021 — Cryptographic Failures
|
|
180
|
+
reason: env-file leaks treated as crypto failure for this engagement
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
python3 ./scripts/map_owasp.py engagements/acme-2026-q2/ \
|
|
185
|
+
--overrides engagements/acme-2026-q2/.owasp-overrides.yaml
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Example 3 — Coverage audit (no enrichment write-back)
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
python3 ./scripts/map_owasp.py engagements/acme-2026-q2/ \
|
|
192
|
+
--enrich-output /dev/null \
|
|
193
|
+
--coverage-output /tmp/coverage.md
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Produces the coverage report without modifying findings files.
|
|
197
|
+
|
|
198
|
+
## Output
|
|
199
|
+
|
|
200
|
+
JSON / JSONL / Markdown per `lib/report.py` for operational
|
|
201
|
+
findings. PRIMARY outputs:
|
|
202
|
+
|
|
203
|
+
1. **Enriched findings JSONL** at `--enrich-output` — every
|
|
204
|
+
finding from the sources has an `owasp_category` field added.
|
|
205
|
+
2. **Coverage report markdown** at `--coverage-output` — per-
|
|
206
|
+
category rollup.
|
|
207
|
+
|
|
208
|
+
Each operational Finding includes:
|
|
209
|
+
|
|
210
|
+
- `id` — `owasp::<issue>::<finding-fingerprint>`
|
|
211
|
+
- `severity` — INFO mostly; HIGH for parse errors
|
|
212
|
+
- `category` — `owasp-mapping`
|
|
213
|
+
- `summary` — what happened to the finding
|
|
214
|
+
- `evidence` — original finding fingerprint, derived OWASP
|
|
215
|
+
category, rule that matched
|
|
216
|
+
|
|
217
|
+
## Error Handling
|
|
218
|
+
|
|
219
|
+
- **PATH missing** → CRITICAL operational finding, exits 1.
|
|
220
|
+
- **Source file unparseable** → HIGH op finding, skip file.
|
|
221
|
+
- **No sources found** → HIGH op finding, exits 1.
|
|
222
|
+
- **Override YAML unparseable** → HIGH op finding, falls back to
|
|
223
|
+
default rules.
|
|
224
|
+
- **Enriched output path not writable** → HIGH op finding, exits 1.
|
|
225
|
+
|
|
226
|
+
## Resources
|
|
227
|
+
|
|
228
|
+
- `references/THEORY.md` — OWASP Top 10 history and 2021 changes,
|
|
229
|
+
CWE → OWASP cross-walk, rule-table design rationale, when a
|
|
230
|
+
finding genuinely doesn't fit, OWASP A0X precision tradeoffs
|
|
231
|
+
(broad categories vs specific findings)
|
|
232
|
+
- `references/PLAYBOOK.md` — Default rule table per cluster 1-4
|
|
233
|
+
skill, override YAML format, coverage-audit interpretation,
|
|
234
|
+
customer-specific category preferences, integration with
|
|
235
|
+
PCI DSS 6.5 / NIST 800-53 control mapping
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# PLAYBOOK — Mapping Rules and Workflow
|
|
2
|
+
|
|
3
|
+
## Default skill → OWASP mappings (reference table)
|
|
4
|
+
|
|
5
|
+
| Cluster | Skill | OWASP | Reason |
|
|
6
|
+
|---|---|---|---|
|
|
7
|
+
| 1 | analyzing-tls-config | A02 | Cryptographic Failures |
|
|
8
|
+
| 1 | detecting-ssl-cert-issues | A02 | Cryptographic Failures |
|
|
9
|
+
| 1 | auditing-cors-policy | A01 | Broken Access Control |
|
|
10
|
+
| 1 | checking-http-security-headers | A05 | Security Misconfiguration |
|
|
11
|
+
| 1 | probing-dangerous-http-methods | A05 | Security Misconfiguration |
|
|
12
|
+
| 2 | detecting-exposed-secrets-files | A02 | Cryptographic Failures (.env, .git exposures) |
|
|
13
|
+
| 2 | detecting-debug-endpoints | A05 | Misconfiguration |
|
|
14
|
+
| 2 | fingerprinting-server-software | A06 | Outdated components signal |
|
|
15
|
+
| 2 | detecting-directory-listing | A05 | Misconfiguration |
|
|
16
|
+
| 3 | scanning-for-hardcoded-secrets | A02 | Hardcoded credentials |
|
|
17
|
+
| 3 | detecting-sql-injection-patterns | A03 | Injection |
|
|
18
|
+
| 3 | detecting-command-injection-patterns | A03 | Injection |
|
|
19
|
+
| 3 | detecting-eval-exec-usage | A03 | Injection (code execution) |
|
|
20
|
+
| 3 | detecting-insecure-deserialization | A08 | Integrity Failures |
|
|
21
|
+
| 3 | detecting-weak-cryptography | A02 | Crypto failures |
|
|
22
|
+
| 4 | auditing-npm-dependencies | A06 | Vulnerable Components |
|
|
23
|
+
| 4 | auditing-python-dependencies | A06 | Vulnerable Components |
|
|
24
|
+
| 4 | checking-license-compliance | A06 | Components hygiene |
|
|
25
|
+
| 4 | tracing-transitive-vulnerabilities | A06 | Vulnerable Components |
|
|
26
|
+
| 5 | confirming-pentest-authorization | A04 | Insecure Design |
|
|
27
|
+
| 5 | defining-pentest-scope | A04 | Insecure Design |
|
|
28
|
+
| 5 | recording-pentest-engagement | A09 | Logging / Monitoring |
|
|
29
|
+
|
|
30
|
+
Cluster 5 (governance) findings aren't technical application
|
|
31
|
+
vulnerabilities; the A04 / A09 mapping is for COVERAGE-REPORTING
|
|
32
|
+
purposes (so engagement-governance findings show up somewhere
|
|
33
|
+
in the OWASP narrative rather than being invisible).
|
|
34
|
+
|
|
35
|
+
## Overrides YAML format
|
|
36
|
+
|
|
37
|
+
```yaml
|
|
38
|
+
# .owasp-overrides.yaml
|
|
39
|
+
- skill_id: auditing-cors-policy
|
|
40
|
+
owasp_category: A05:2021 — Security Misconfiguration
|
|
41
|
+
reason: customer treats CORS as misconfig, not access-control
|
|
42
|
+
|
|
43
|
+
- skill_id: scanning-for-hardcoded-secrets
|
|
44
|
+
detail_contains: ".env"
|
|
45
|
+
owasp_category: A02:2021 — Cryptographic Failures
|
|
46
|
+
reason: .env leaks treated as crypto failure for this customer
|
|
47
|
+
|
|
48
|
+
- skill_id: tracing-transitive-vulnerabilities
|
|
49
|
+
detail_contains: "deep"
|
|
50
|
+
owasp_category: A08:2021 — Software and Data Integrity Failures
|
|
51
|
+
reason: deep-transitive vulns treated as integrity concern for this customer
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
An override applies when:
|
|
55
|
+
|
|
56
|
+
- `skill_id` matches AND
|
|
57
|
+
- `detail_contains` matches (if specified — substring match)
|
|
58
|
+
|
|
59
|
+
The `owasp_category` must be one of the canonical strings (e.g.
|
|
60
|
+
"A05:2021 — Security Misconfiguration"). The skill parses the
|
|
61
|
+
leading code (`A05`) for table lookup.
|
|
62
|
+
|
|
63
|
+
Add a `reason` field on every override. Reasons become part of
|
|
64
|
+
the engagement archive's audit trail.
|
|
65
|
+
|
|
66
|
+
## Coverage-report interpretation
|
|
67
|
+
|
|
68
|
+
### "All 10 categories covered"
|
|
69
|
+
|
|
70
|
+
Customer report's OWASP section can claim "the engagement evaluated
|
|
71
|
+
all 10 OWASP Top 10 categories." This is the strongest possible
|
|
72
|
+
coverage claim and what most customers want.
|
|
73
|
+
|
|
74
|
+
### "8 of 10 categories covered"
|
|
75
|
+
|
|
76
|
+
Customer report should explicitly note which categories had no
|
|
77
|
+
findings AND whether each "no findings" reflects clean results
|
|
78
|
+
or out-of-scope testing. Phrasing template:
|
|
79
|
+
|
|
80
|
+
> The engagement covered 8 of the 10 OWASP Top 10 (2021)
|
|
81
|
+
> categories. A04 (Insecure Design) and A10 (Server-Side Request
|
|
82
|
+
> Forgery) had no findings within this engagement's scope.
|
|
83
|
+
|
|
84
|
+
### "3 of 10 categories covered"
|
|
85
|
+
|
|
86
|
+
Either a deliberately narrow scope or a rule-table coverage gap.
|
|
87
|
+
Investigate before shipping the report:
|
|
88
|
+
|
|
89
|
+
1. Check the unmapped findings list. Are findings falling into the
|
|
90
|
+
"no rule matched" bucket?
|
|
91
|
+
2. Check the scope. Did the engagement explicitly include only
|
|
92
|
+
network testing (which would naturally cover A02 + A05 + A06)?
|
|
93
|
+
3. If the narrow coverage is intentional, document it in the
|
|
94
|
+
engagement summary's scope section.
|
|
95
|
+
|
|
96
|
+
## Per-customer category-emphasis patterns
|
|
97
|
+
|
|
98
|
+
### PCI DSS customers
|
|
99
|
+
|
|
100
|
+
PCI DSS Req 6.5 lists specific vulnerability classes that must be
|
|
101
|
+
addressed. The skill's standard A0X mapping covers most of these.
|
|
102
|
+
Recommend including a "PCI DSS Req 6.5 coverage" section in the
|
|
103
|
+
report that cross-references A0X findings to specific Req 6.5
|
|
104
|
+
items. Out of scope for this skill (separate mapping).
|
|
105
|
+
|
|
106
|
+
### HIPAA customers
|
|
107
|
+
|
|
108
|
+
A02 (Crypto) and A09 (Logging) get the most scrutiny. Recommend
|
|
109
|
+
running A02 + A09 specifically (auditing-tls-config + checking
|
|
110
|
+
for security logging + monitoring failures) regardless of
|
|
111
|
+
broader scope.
|
|
112
|
+
|
|
113
|
+
### SOC2 customers
|
|
114
|
+
|
|
115
|
+
CC7 (System Operations) maps loosely to A06 + A09. CC8 (Change
|
|
116
|
+
Management) maps to A04 + A08. The full coverage report supports
|
|
117
|
+
the SOC2 audit narrative.
|
|
118
|
+
|
|
119
|
+
### ISO 27001 customers
|
|
120
|
+
|
|
121
|
+
Annex A.14.2 (Security in Development) maps to A04 + A08. Annex
|
|
122
|
+
A.12.6 (Vulnerability Management) maps to A06. The full coverage
|
|
123
|
+
report supports the ISO 27001 audit narrative.
|
|
124
|
+
|
|
125
|
+
## Workflow patterns
|
|
126
|
+
|
|
127
|
+
### Standalone enrichment
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
python3 ./scripts/map_owasp.py engagements/acme-2026-q2/
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Enriched JSONL at `findings/all-with-owasp.jsonl`.
|
|
134
|
+
Coverage report at `reports/owasp-coverage.md`.
|
|
135
|
+
|
|
136
|
+
### Enrichment with overrides
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
python3 ./scripts/map_owasp.py engagements/acme-2026-q2/ \
|
|
140
|
+
--overrides engagements/acme-2026-q2/.owasp-overrides.yaml
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Coverage audit only (no enrichment)
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
python3 ./scripts/map_owasp.py engagements/acme-2026-q2/ \
|
|
147
|
+
--enrich-output /dev/null \
|
|
148
|
+
--coverage-output /tmp/coverage.md
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Re-compose vulnerability report after enrichment
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# Step 1: enrich
|
|
155
|
+
python3 ./scripts/map_owasp.py engagements/acme-2026-q2/
|
|
156
|
+
|
|
157
|
+
# Step 2: re-compose report from enriched findings
|
|
158
|
+
python3 plugins/security/penetration-tester/skills/composing-vulnerability-report/scripts/compose_report.py \
|
|
159
|
+
engagements/acme-2026-q2/ \
|
|
160
|
+
--source engagements/acme-2026-q2/findings/all-with-owasp.jsonl \
|
|
161
|
+
--report-output engagements/acme-2026-q2/reports/vulnerability-report-v2.md
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## When to extend the rule table
|
|
165
|
+
|
|
166
|
+
Add a new entry to `SKILL_TO_OWASP` when:
|
|
167
|
+
|
|
168
|
+
- A new cluster 1-4 skill is added to the pack.
|
|
169
|
+
- A skill's default classification proves consistently wrong in
|
|
170
|
+
practice.
|
|
171
|
+
- A new CWE → OWASP mapping is needed (extend `CWE_TO_OWASP`).
|
|
172
|
+
|
|
173
|
+
Add a new entry to `DETAIL_KEYWORDS` when:
|
|
174
|
+
|
|
175
|
+
- An UNMAPPED-finding pattern is recognizable by detail keywords
|
|
176
|
+
that no current rule catches.
|
|
177
|
+
- A detail-keyword rule is sometimes a useful fallback for
|
|
178
|
+
third-party tools whose output passes through this skill.
|
|
179
|
+
|
|
180
|
+
Don't add overrides as rule-table extensions — overrides are
|
|
181
|
+
engagement-specific by design. Rule-table changes are global.
|
|
182
|
+
|
|
183
|
+
## Integration with executive-summary
|
|
184
|
+
|
|
185
|
+
The exec-summary skill consumes the enriched findings JSONL plus
|
|
186
|
+
the coverage report. The exec summary's "OWASP coverage" section
|
|
187
|
+
quotes per-category counts from the coverage report and risk
|
|
188
|
+
score from the unified findings.
|
|
189
|
+
|
|
190
|
+
Order of operations: cluster 1-4 → this skill → exec summary.
|
|
191
|
+
Optionally re-run compose-vulnerability-report between this skill
|
|
192
|
+
and exec-summary so the OWASP tags appear in the main report's
|
|
193
|
+
per-finding sections.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# THEORY — OWASP Top 10 Mapping
|
|
2
|
+
|
|
3
|
+
## What the OWASP Top 10 actually is
|
|
4
|
+
|
|
5
|
+
The OWASP Top 10 is a community-curated list of the most critical
|
|
6
|
+
web application security risks, updated every 3-4 years. The
|
|
7
|
+
current version is the 2021 edition. The Top 10 is NOT a complete
|
|
8
|
+
taxonomy of all possible vulnerabilities — it's a prioritization
|
|
9
|
+
framework. Findings outside the Top 10 still matter; they just
|
|
10
|
+
don't get their own A0X slot.
|
|
11
|
+
|
|
12
|
+
The 2021 edition's categories (with their derivation from 2017
|
|
13
|
+
predecessors):
|
|
14
|
+
|
|
15
|
+
| 2021 | Notes |
|
|
16
|
+
|---|---|
|
|
17
|
+
| A01 Broken Access Control | Promoted from A05 (2017); broadest category, includes path traversal + IDOR |
|
|
18
|
+
| A02 Cryptographic Failures | Renamed from A03 "Sensitive Data Exposure"; emphasizes the failure modes not the data |
|
|
19
|
+
| A03 Injection | Demoted from A01 (2017); XSS folded in here |
|
|
20
|
+
| A04 Insecure Design | NEW; threat-modeling-failure findings |
|
|
21
|
+
| A05 Security Misconfiguration | Includes XML External Entities (was A04 in 2017) |
|
|
22
|
+
| A06 Vulnerable and Outdated Components | Promoted from A09 (2017) |
|
|
23
|
+
| A07 Identification and Authentication Failures | Renamed from A02 "Broken Authentication" |
|
|
24
|
+
| A08 Software and Data Integrity Failures | NEW; supply-chain-attack-shaped |
|
|
25
|
+
| A09 Security Logging and Monitoring Failures | Renamed from A10 (2017) |
|
|
26
|
+
| A10 Server-Side Request Forgery | NEW as a Top 10 entry |
|
|
27
|
+
|
|
28
|
+
The 2025 edition is in draft as of this skill's authorship. When
|
|
29
|
+
it ships, this skill's mapping table should be reviewed against
|
|
30
|
+
the new category set.
|
|
31
|
+
|
|
32
|
+
## CWE → OWASP cross-walk
|
|
33
|
+
|
|
34
|
+
OWASP publishes an authoritative mapping from CWE identifiers to
|
|
35
|
+
OWASP categories at https://owasp.org/Top10/A0X_2021-<name>/. The
|
|
36
|
+
mapping is one-to-many in both directions: a single CWE can map
|
|
37
|
+
to multiple OWASP categories depending on context, and a single
|
|
38
|
+
OWASP category encompasses many CWEs.
|
|
39
|
+
|
|
40
|
+
This skill's `CWE_TO_OWASP` table captures the most common
|
|
41
|
+
mappings deterministically. Edge cases:
|
|
42
|
+
|
|
43
|
+
- CWE-200 (Information Exposure) — typically A01 but can map to
|
|
44
|
+
A05 or A09 depending on context.
|
|
45
|
+
- CWE-352 (CSRF) — included in A01 in 2021 (was A08 in 2017).
|
|
46
|
+
- CWE-89 (SQL Injection) — A03, no ambiguity.
|
|
47
|
+
|
|
48
|
+
When a CWE has multiple plausible mappings, the skill picks the
|
|
49
|
+
most common one in practice. Override via the engagement-specific
|
|
50
|
+
overrides YAML for cases where the customer expects a different
|
|
51
|
+
classification.
|
|
52
|
+
|
|
53
|
+
## Why deterministic rules, not LLM classification
|
|
54
|
+
|
|
55
|
+
It's tempting to feed each finding to an LLM and ask "which OWASP
|
|
56
|
+
category fits best?" Two problems:
|
|
57
|
+
|
|
58
|
+
1. **Reproducibility.** A pentest report claims to be the result
|
|
59
|
+
of a defined methodology. An LLM-classified report changes
|
|
60
|
+
slightly on every regeneration (model temperature, prompt
|
|
61
|
+
variation, training-data drift). Auditors hate this.
|
|
62
|
+
|
|
63
|
+
2. **Explainability.** A finding's mapping needs a defensible
|
|
64
|
+
reason ("this is A06 because the source skill is
|
|
65
|
+
`auditing-npm-dependencies` which detects vulnerable
|
|
66
|
+
third-party components" is defensible; "the LLM said so" is
|
|
67
|
+
not).
|
|
68
|
+
|
|
69
|
+
The skill uses a deterministic rule table. Rules are auditable.
|
|
70
|
+
The classifier can be wrong, but it's wrong consistently — and
|
|
71
|
+
the operator can extend the table to fix patterns.
|
|
72
|
+
|
|
73
|
+
## Rule precedence
|
|
74
|
+
|
|
75
|
+
The skill applies rules in this order:
|
|
76
|
+
|
|
77
|
+
1. **Engagement-specific overrides** (from `--overrides FILE`).
|
|
78
|
+
Highest precedence; lets customers express their own
|
|
79
|
+
classification preferences.
|
|
80
|
+
2. **CWE-based mapping** when the finding has a `cwe_id`.
|
|
81
|
+
3. **Skill-ID default** when no CWE is present or matches.
|
|
82
|
+
4. **Detail-keyword fallback** as a last-resort heuristic.
|
|
83
|
+
|
|
84
|
+
Each successful classification records WHICH rule matched in the
|
|
85
|
+
operational Finding. Operators can see the reasoning chain when
|
|
86
|
+
debugging unexpected classifications.
|
|
87
|
+
|
|
88
|
+
## Coverage interpretation
|
|
89
|
+
|
|
90
|
+
The coverage report shows count per A0X category. Interpretation:
|
|
91
|
+
|
|
92
|
+
| Pattern | What it usually means |
|
|
93
|
+
|---|---|
|
|
94
|
+
| All 10 categories have findings | Broad-coverage engagement, comprehensive scope |
|
|
95
|
+
| 6-9 categories | Typical engagement; some categories not in scope |
|
|
96
|
+
| 1-5 categories | Narrow scope OR rule table missed mappings |
|
|
97
|
+
| 0 categories with HIGH/CRITICAL | Either remarkably clean target OR scans didn't run |
|
|
98
|
+
|
|
99
|
+
The skill flags fewer-than-5 categories as MEDIUM. The operator
|
|
100
|
+
should determine whether the narrow coverage is intentional (and
|
|
101
|
+
document so) or a sign of incomplete testing.
|
|
102
|
+
|
|
103
|
+
## When a finding genuinely doesn't fit a single category
|
|
104
|
+
|
|
105
|
+
Some findings are cross-cutting:
|
|
106
|
+
|
|
107
|
+
- A misconfigured database cluster (A05 Misconfiguration + A09
|
|
108
|
+
Logging + A02 Crypto-at-rest) — could legitimately appear in
|
|
109
|
+
three categories.
|
|
110
|
+
- A supply-chain compromise (A06 Components + A08 Software Integrity)
|
|
111
|
+
— both apply.
|
|
112
|
+
- An authentication bypass via path traversal (A07 + A01).
|
|
113
|
+
|
|
114
|
+
The Top 10 doesn't tolerate multi-category findings. The convention
|
|
115
|
+
is to pick the PRIMARY category (the failure mode that most
|
|
116
|
+
directly causes exploitation) and accept that the finding will be
|
|
117
|
+
reported under one A0X bucket. Cross-references in the report body
|
|
118
|
+
can point to the secondary category.
|
|
119
|
+
|
|
120
|
+
## Customer-specific category preferences
|
|
121
|
+
|
|
122
|
+
Some customers care about specific A0X categories for compliance
|
|
123
|
+
reasons:
|
|
124
|
+
|
|
125
|
+
- **PCI DSS** customers care about A02 (Crypto) and A07 (Auth).
|
|
126
|
+
- **Healthcare (HIPAA)** customers care about A02 + A09 (Logging).
|
|
127
|
+
- **SOC2 CC7** customers want broad coverage across all categories.
|
|
128
|
+
|
|
129
|
+
The skill's overrides YAML is the mechanism for capturing these
|
|
130
|
+
preferences. An override re-classifies a finding's category for
|
|
131
|
+
the specific engagement without changing the default rule table.
|
|
132
|
+
|
|
133
|
+
## OWASP Top 10 vs ASVS
|
|
134
|
+
|
|
135
|
+
The OWASP Application Security Verification Standard (ASVS) is a
|
|
136
|
+
much more granular framework — 286 verification requirements across
|
|
137
|
+
14 chapters. Some engagements demand ASVS coverage instead of (or
|
|
138
|
+
in addition to) Top 10 coverage. This skill maps Top 10 only;
|
|
139
|
+
ASVS mapping would be a separate skill (or extension to this one)
|
|
140
|
+
because the rule table is differently shaped.
|
|
141
|
+
|
|
142
|
+
## Mapping precision tradeoffs
|
|
143
|
+
|
|
144
|
+
The skill optimizes for:
|
|
145
|
+
|
|
146
|
+
- **Coverage** — every finding gets a mapping if at all possible.
|
|
147
|
+
- **Reproducibility** — same input → same output, always.
|
|
148
|
+
- **Auditability** — the rule that matched is recorded.
|
|
149
|
+
- **Extensibility** — operators can add overrides without code changes.
|
|
150
|
+
|
|
151
|
+
It does NOT optimize for:
|
|
152
|
+
|
|
153
|
+
- **Per-finding precision** — a finding might fit two categories;
|
|
154
|
+
the skill picks one deterministically.
|
|
155
|
+
- **2025-edition forward compatibility** — when OWASP 2025
|
|
156
|
+
finalizes, the table needs review.
|
|
157
|
+
- **ASVS coverage** — out of scope.
|
|
158
|
+
|
|
159
|
+
These tradeoffs are deliberate. The skill is a triage tool, not a
|
|
160
|
+
substitute for human judgment on contested classifications.
|