@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,180 @@
|
|
|
1
|
+
# PLAYBOOK — Report Templates and Workflow
|
|
2
|
+
|
|
3
|
+
## End-of-engagement workflow
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
# 1. All cluster 1-4 scans have run; findings are in engagements/<id>/findings/
|
|
7
|
+
|
|
8
|
+
# 2. (Optional) Map findings to OWASP Top 10
|
|
9
|
+
python3 plugins/security/penetration-tester/skills/mapping-findings-to-owasp-top10/scripts/map_owasp.py \
|
|
10
|
+
engagements/acme-2026-q2/
|
|
11
|
+
|
|
12
|
+
# 3. Compose the vulnerability report
|
|
13
|
+
python3 ./scripts/compose_report.py engagements/acme-2026-q2/
|
|
14
|
+
|
|
15
|
+
# 4. Generate the executive summary
|
|
16
|
+
python3 plugins/security/penetration-tester/skills/generating-executive-summary/scripts/exec_summary.py \
|
|
17
|
+
engagements/acme-2026-q2/
|
|
18
|
+
|
|
19
|
+
# 5. Record the engagement (chain of custody)
|
|
20
|
+
python3 plugins/security/penetration-tester/skills/recording-pentest-engagement/scripts/record_engagement.py \
|
|
21
|
+
engagements/acme-2026-q2/ --sign --tar engagements/archives/acme-2026-q2.tar.gz
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Report-template variants per audience
|
|
25
|
+
|
|
26
|
+
### Technical (default — what the skill emits)
|
|
27
|
+
|
|
28
|
+
Everything: per-finding detail, remediation steps, evidence,
|
|
29
|
+
references. Audience: customer's security engineer or external
|
|
30
|
+
auditor.
|
|
31
|
+
|
|
32
|
+
### Manager-style (use `--min-severity high`)
|
|
33
|
+
|
|
34
|
+
Only HIGH and CRITICAL findings shown. Body of the report is the
|
|
35
|
+
same per-finding format but the customer's manager doesn't have
|
|
36
|
+
to scroll past medium / low findings.
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
python3 ./scripts/compose_report.py engagements/acme-2026-q2/ \
|
|
40
|
+
--min-severity high \
|
|
41
|
+
--report-output engagements/acme-2026-q2/reports/manager-brief.md
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Compliance-evidence (use `--include-info`)
|
|
45
|
+
|
|
46
|
+
Includes the INFO-severity operational records (scan ran cleanly,
|
|
47
|
+
no findings in this target, etc.). Audience: SOC2 / ISO 27001
|
|
48
|
+
auditors who want documented evidence the scan ran even where
|
|
49
|
+
nothing was found.
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
python3 ./scripts/compose_report.py engagements/acme-2026-q2/ \
|
|
53
|
+
--include-info \
|
|
54
|
+
--report-output engagements/acme-2026-q2/reports/compliance-evidence.md
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Per-finding remediation phrasing patterns
|
|
58
|
+
|
|
59
|
+
The skill emits each finding's `remediation` field verbatim from
|
|
60
|
+
the source. Cluster 1-4 skills construct these as numbered lists
|
|
61
|
+
with imperative voice:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
1. Run `npm audit fix` in the project root.
|
|
65
|
+
2. If the fix requires a semver-major bump, evaluate the breaking changes.
|
|
66
|
+
3. Commit the updated package-lock.json.
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Patterns to maintain when authoring remediation:
|
|
70
|
+
|
|
71
|
+
- **Imperative voice.** "Run X" not "You should run X" not "It is recommended to run X."
|
|
72
|
+
- **Numbered list when there are >1 steps.** Bullets blur the order.
|
|
73
|
+
- **Concrete commands when possible.** "Apply security patch" is unactionable; "`apt-get update && apt-get upgrade libssl3`" is actionable.
|
|
74
|
+
- **Decision points called out.** "If X, do Y; otherwise do Z" makes the operator's choice explicit.
|
|
75
|
+
|
|
76
|
+
## Evidence-redaction for distributed reports
|
|
77
|
+
|
|
78
|
+
A pentest report sometimes needs distribution beyond the immediate
|
|
79
|
+
customer — to their auditor, their insurance carrier, their board.
|
|
80
|
+
Some evidence shouldn't leave the original engagement: leaked
|
|
81
|
+
credentials, full request/response bodies containing PII, screenshots
|
|
82
|
+
showing customer data.
|
|
83
|
+
|
|
84
|
+
The skill doesn't auto-redact. The pattern for human-controlled
|
|
85
|
+
redaction:
|
|
86
|
+
|
|
87
|
+
1. Generate the full report with this skill.
|
|
88
|
+
2. Use a separate redaction pass to:
|
|
89
|
+
- Replace leaked-secret values with `[REDACTED]` while keeping
|
|
90
|
+
finding context.
|
|
91
|
+
- Blur or remove customer-data screenshots.
|
|
92
|
+
- Replace user-identifying URLs with `<USER>/path/...` placeholders.
|
|
93
|
+
3. Distribute the redacted version. Keep the unredacted version in
|
|
94
|
+
the engagement archive.
|
|
95
|
+
|
|
96
|
+
The skill could be extended with a `--redact PATTERN` flag if this
|
|
97
|
+
becomes a frequent enough pattern.
|
|
98
|
+
|
|
99
|
+
## Cross-reference protocol with OWASP-mapping + exec-summary
|
|
100
|
+
|
|
101
|
+
The next two cluster 6 skills consume this report's findings file
|
|
102
|
+
(JSON output of THIS skill's findings → not the rendered markdown).
|
|
103
|
+
The protocol:
|
|
104
|
+
|
|
105
|
+
1. **Findings producer:** cluster 1-4 skills emit per-skill findings JSONLs
|
|
106
|
+
2. **Vulnerability report composer (this skill):** composes a single
|
|
107
|
+
vulnerability-report.md AND can output a unified findings JSONL
|
|
108
|
+
3. **OWASP mapping:** reads the unified JSONL, adds `owasp_category`
|
|
109
|
+
field to each finding, writes back
|
|
110
|
+
4. **Exec summary:** reads the (potentially OWASP-enriched) unified
|
|
111
|
+
JSONL, produces the executive-summary.md
|
|
112
|
+
|
|
113
|
+
The order can be either:
|
|
114
|
+
|
|
115
|
+
- A: cluster-1-4 → OWASP → compose → exec-summary
|
|
116
|
+
- B: cluster-1-4 → compose → OWASP → re-compose → exec-summary
|
|
117
|
+
|
|
118
|
+
Pattern B regenerates the report after enrichment. Pattern A only
|
|
119
|
+
composes once. Both are valid; the choice depends on whether the
|
|
120
|
+
operator wants the OWASP tags visible in the report's per-finding
|
|
121
|
+
sections.
|
|
122
|
+
|
|
123
|
+
## Common composition mistakes
|
|
124
|
+
|
|
125
|
+
| Mistake | Consequence | Fix |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| Findings without `target` field | Findings dropped from report; HIGH op-finding | Ensure all source skills emit `target` |
|
|
128
|
+
| Mixed findings + opfindings in source file | Report contains operational noise | Separate skill output and operational output |
|
|
129
|
+
| Identical findings with different IDs | Dedup fails | Ensure source skills use consistent `Finding.fingerprint()` |
|
|
130
|
+
| Re-running with new sources but old report path | Old report overwritten silently | Use timestamped `--report-output` paths for interim reports |
|
|
131
|
+
|
|
132
|
+
## Per-engagement directory layout (canonical)
|
|
133
|
+
|
|
134
|
+
The skill assumes:
|
|
135
|
+
|
|
136
|
+
- `engagement/findings/*.json[l]` — source findings
|
|
137
|
+
- `engagement/reports/` — output reports (auto-created if missing)
|
|
138
|
+
- `engagement/roe.yaml` — has `engagement_id:` for header
|
|
139
|
+
|
|
140
|
+
Deviations are supported via flags:
|
|
141
|
+
|
|
142
|
+
- `--source FILE` — bypass auto-discovery
|
|
143
|
+
- `--report-output PATH` — write report anywhere
|
|
144
|
+
- `--engagement-id ID` — override ROE detection
|
|
145
|
+
|
|
146
|
+
## Integration with cluster 1-4 skills
|
|
147
|
+
|
|
148
|
+
The cluster 1-4 scan skills all emit findings via `report.emit()`
|
|
149
|
+
(in `lib/report.py`) which can write JSON / JSONL / Markdown.
|
|
150
|
+
For composition workflow, each scan should run with
|
|
151
|
+
`--format jsonl --output engagement/findings/<skill>-<date>.jsonl`:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
python3 plugins/security/penetration-tester/skills/checking-http-security-headers/scripts/check_headers.py \
|
|
155
|
+
https://app.acme.example --format jsonl \
|
|
156
|
+
--output engagements/acme-2026-q2/findings/headers-$(date +%Y%m%d).jsonl
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
The skill then picks up every file under `findings/` by default.
|
|
160
|
+
|
|
161
|
+
## Stable-rendering verification
|
|
162
|
+
|
|
163
|
+
To verify the report is rendering stably (same input → same output
|
|
164
|
+
except timestamp):
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
# Render twice
|
|
168
|
+
python3 ./scripts/compose_report.py engagements/acme-2026-q2/ \
|
|
169
|
+
--report-output /tmp/report-1.md
|
|
170
|
+
sleep 2
|
|
171
|
+
python3 ./scripts/compose_report.py engagements/acme-2026-q2/ \
|
|
172
|
+
--report-output /tmp/report-2.md
|
|
173
|
+
|
|
174
|
+
# Diff ignoring the timestamp line
|
|
175
|
+
diff <(grep -v "Generated by" /tmp/report-1.md) \
|
|
176
|
+
<(grep -v "Generated by" /tmp/report-2.md)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The diff should be empty. If it isn't, file an issue — stable
|
|
180
|
+
rendering is a contract this skill maintains.
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# THEORY — Vulnerability Report Structure
|
|
2
|
+
|
|
3
|
+
## What a customer actually reads
|
|
4
|
+
|
|
5
|
+
A pentest vulnerability report is read by three different people
|
|
6
|
+
in three different ways:
|
|
7
|
+
|
|
8
|
+
1. **The customer's security engineer** — reads end to end, in
|
|
9
|
+
order, looking for specific technical detail per finding.
|
|
10
|
+
2. **The customer's manager** — reads the summary table, then
|
|
11
|
+
skims headlines of critical / high findings, then trusts the
|
|
12
|
+
security engineer's recommendation.
|
|
13
|
+
3. **A future reader during compliance audit** — reads to verify
|
|
14
|
+
the finding existed and the remediation was documented.
|
|
15
|
+
|
|
16
|
+
The report has to serve all three audiences without trying too
|
|
17
|
+
hard. The structure this skill emits is the result of trial and
|
|
18
|
+
error against those three readers:
|
|
19
|
+
|
|
20
|
+
- Top: short header identifying engagement, generation time,
|
|
21
|
+
sources.
|
|
22
|
+
- Below: summary table — counts by severity.
|
|
23
|
+
- Then: severity-ordered finding sections, CRITICAL first.
|
|
24
|
+
- Each finding: title, severity, target, detail, remediation,
|
|
25
|
+
evidence, references — in that order. Always.
|
|
26
|
+
|
|
27
|
+
The shape is boring on purpose. Surprise in report structure is
|
|
28
|
+
not a feature; the reader should be able to predict where a piece
|
|
29
|
+
of information lives without searching.
|
|
30
|
+
|
|
31
|
+
## Why CVSS v3.1 (not CVSS v4 or CWE-only)
|
|
32
|
+
|
|
33
|
+
CVSS v3.1 (June 2019) is the de facto industry standard severity
|
|
34
|
+
vector. NVD scores every CVE with CVSS v3.1. SOC2 / ISO 27001 /
|
|
35
|
+
PCI auditors expect to see CVSS scores.
|
|
36
|
+
|
|
37
|
+
CVSS v4.0 was published in November 2023. It addresses real
|
|
38
|
+
problems with v3.1 (better handling of supply-chain attacks,
|
|
39
|
+
clearer attack-vector semantics). Adoption has been slow because
|
|
40
|
+
the existing tooling chain is v3.1-shaped. As of 2026 the practical
|
|
41
|
+
choice is still v3.1.
|
|
42
|
+
|
|
43
|
+
CWE alone is a different axis — what KIND of weakness, not how
|
|
44
|
+
SEVERE. Reports include CWE as enrichment when available but use
|
|
45
|
+
CVSS for the severity decision.
|
|
46
|
+
|
|
47
|
+
## CVSS vector composition (when the skill derives one)
|
|
48
|
+
|
|
49
|
+
When a finding arrives without a CVSS score, the skill does NOT
|
|
50
|
+
guess a precise numeric score (that would falsely imply NVD-level
|
|
51
|
+
authority). Instead it maps severity → severity band, retaining
|
|
52
|
+
the explicit "derived" label so the report's reader knows the score
|
|
53
|
+
isn't NVD-blessed.
|
|
54
|
+
|
|
55
|
+
| Severity | Implied CVSS band | Note |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| CRITICAL | 9.0 - 10.0 | implied by mapping; not authoritative |
|
|
58
|
+
| HIGH | 7.0 - 8.9 | implied |
|
|
59
|
+
| MEDIUM | 4.0 - 6.9 | implied |
|
|
60
|
+
| LOW | 0.1 - 3.9 | implied |
|
|
61
|
+
| INFO | n/a | no score emitted |
|
|
62
|
+
|
|
63
|
+
Findings that arrived WITH a CVSS score keep their original value
|
|
64
|
+
unchanged. This is important: a finding with `cvss_score: 7.5`
|
|
65
|
+
from `auditing-python-dependencies` (which extracts it from OSV)
|
|
66
|
+
must not be overwritten by this skill's heuristic.
|
|
67
|
+
|
|
68
|
+
## Why fingerprint-based deduplication
|
|
69
|
+
|
|
70
|
+
`lib/finding.py` defines `Finding.fingerprint()` as a stable hash
|
|
71
|
+
of `(skill_id, title, target)`. Two findings with the same
|
|
72
|
+
fingerprint are the same finding from the same source about the
|
|
73
|
+
same target, regardless of which scan run produced them.
|
|
74
|
+
|
|
75
|
+
The alternative — title-based dedup — fails when:
|
|
76
|
+
|
|
77
|
+
- Same skill is run twice (the second invocation produces
|
|
78
|
+
identical findings)
|
|
79
|
+
- Two different skills produce findings with the same title but
|
|
80
|
+
different targets (legitimate distinct findings)
|
|
81
|
+
- A skill produces findings with parameterized titles (the
|
|
82
|
+
title varies but the substance is the same)
|
|
83
|
+
|
|
84
|
+
Fingerprint-based dedup is the right primitive. The trade-off:
|
|
85
|
+
fingerprints don't catch SEMANTICALLY-equivalent findings from
|
|
86
|
+
different skills. If `auditing-npm-dependencies` and an external
|
|
87
|
+
tool both surface the same CVE, the fingerprints differ (different
|
|
88
|
+
skill_id). Cross-tool semantic dedup is a separate problem — this
|
|
89
|
+
skill handles within-skill dedup correctly.
|
|
90
|
+
|
|
91
|
+
## NIST SP 800-115 vs PTES vs OWASP Testing Guide
|
|
92
|
+
|
|
93
|
+
Three frameworks define what a pentest report should contain:
|
|
94
|
+
|
|
95
|
+
| Framework | Strengths | Weaknesses |
|
|
96
|
+
|---|---|---|
|
|
97
|
+
| NIST SP 800-115 (US gov-flavored) | Definitive, well-structured | Network-focused; app-pentest sections are thin |
|
|
98
|
+
| PTES | Defines the workflow end-to-end | Report structure is one of many topics; less prescriptive |
|
|
99
|
+
| OWASP Testing Guide (WSTG) | Best on web-app vulnerability classification | Doesn't prescribe report structure deeply |
|
|
100
|
+
|
|
101
|
+
The skill's output format is informed by all three but doesn't
|
|
102
|
+
claim conformance to any. The structure is pragmatic: what works
|
|
103
|
+
in real customer engagements as of 2026.
|
|
104
|
+
|
|
105
|
+
## Severity-grouping rationale
|
|
106
|
+
|
|
107
|
+
The skill groups findings by severity, NOT by skill or by target.
|
|
108
|
+
Reasons:
|
|
109
|
+
|
|
110
|
+
- Customers care about severity first. A CRITICAL CVE in
|
|
111
|
+
dependency-vuln scan and a CRITICAL TLS misconfig and a
|
|
112
|
+
CRITICAL secret in source are all the same severity to the
|
|
113
|
+
reader; they should be co-located.
|
|
114
|
+
- Per-severity grouping makes remediation prioritization
|
|
115
|
+
trivially visual.
|
|
116
|
+
- Per-skill grouping would hide cross-skill patterns ("multiple
|
|
117
|
+
high findings in the same target" becomes invisible).
|
|
118
|
+
|
|
119
|
+
If the customer specifically wants per-skill grouping (some prefer
|
|
120
|
+
it), this skill's output is structured Markdown that a downstream
|
|
121
|
+
tool can re-group. The skill emits the canonical form; consumers
|
|
122
|
+
re-shape if needed.
|
|
123
|
+
|
|
124
|
+
## Stable anchors for cross-reference
|
|
125
|
+
|
|
126
|
+
Each finding subsection in the report has a stable HTML anchor
|
|
127
|
+
based on the fingerprint:
|
|
128
|
+
|
|
129
|
+
```html
|
|
130
|
+
<a id="finding-a1b2c3d4e5f6"></a>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
The executive-summary skill and the OWASP-mapping skill reference
|
|
134
|
+
findings by this anchor:
|
|
135
|
+
|
|
136
|
+
```markdown
|
|
137
|
+
[See finding](vulnerability-report.md#finding-a1b2c3d4e5f6)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
The anchor is stable across regenerations of the report (because
|
|
141
|
+
the fingerprint is stable). If the report is regenerated after
|
|
142
|
+
adding new findings, existing finding anchors don't change —
|
|
143
|
+
only new anchors are added.
|
|
144
|
+
|
|
145
|
+
## Required-field policy
|
|
146
|
+
|
|
147
|
+
The skill refuses to include findings missing any of `title`,
|
|
148
|
+
`severity`, `target`, `detail`, `remediation`. The dropped finding
|
|
149
|
+
becomes a HIGH operational finding from this skill itself,
|
|
150
|
+
surfacing the problem to the operator without silently swallowing
|
|
151
|
+
the broken record.
|
|
152
|
+
|
|
153
|
+
This is conservative on purpose. A pentest report that includes
|
|
154
|
+
malformed findings is unprofessional and undermines the engagement.
|
|
155
|
+
Better to surface the problem with a loud error than to ship
|
|
156
|
+
broken records.
|
|
157
|
+
|
|
158
|
+
## Why include-info defaults to off
|
|
159
|
+
|
|
160
|
+
INFO-severity findings are operational chatter (no vulnerabilities
|
|
161
|
+
found, scanner ran cleanly, etc.). Customer reports should NOT
|
|
162
|
+
include them in the main severity sections — the customer cares
|
|
163
|
+
about findings, not about confirmation that the scan ran.
|
|
164
|
+
|
|
165
|
+
`--include-info` adds an INFO section at the bottom of the report
|
|
166
|
+
for operational transparency. Useful for SOC2 evidence packages
|
|
167
|
+
where auditors want to confirm every scan ran.
|
|
168
|
+
|
|
169
|
+
## Generation timestamp + reproducibility
|
|
170
|
+
|
|
171
|
+
The header includes the generation timestamp in ISO-8601. The
|
|
172
|
+
report is reproducible from the same source findings: if you
|
|
173
|
+
re-run with the same inputs, the report content is byte-identical
|
|
174
|
+
except for the timestamp.
|
|
175
|
+
|
|
176
|
+
This matters for evidence: the customer's audit team needs to
|
|
177
|
+
verify "report-as-shipped" against "report-from-source-now."
|
|
178
|
+
Stable rendering = trustable comparison.
|