Read findings JSONL files from cluster 1-4 skills, deduplicate by fingerprint, group by severity, and compose a deliverable- grade markdown vulnerability report with per-finding sections (title, severity, target, detail, remediation, evidence) and a top-level summary table. The canonical written artifact a customer receives at engagement close; precise, reproducible, machine- checkable against source findings. Use when: closing an engagement, generating an interim report, regenerating after C...
Scanned 9/2/2026
Install to Claude Code
npx -y skills add jeremylongshore/tons-of-skills-marketplace --skill composing-vulnerability-report --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Composing Vulnerability Report?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/jeremylongshore-composing-vulnerability-report-tons-of-skills-marketplace)More formats (shields.io, HTML) on the badges page.
---
name: composing-vulnerability-report
description: |
Read findings JSONL files from cluster 1-4 skills, deduplicate
by fingerprint, group by severity, and compose a deliverable-
grade markdown vulnerability report with per-finding sections
(title, severity, target, detail, remediation, evidence) and a
top-level summary table. The canonical written artifact a customer
receives at engagement close; precise, reproducible, machine-
checkable against source findings.
Use when: closing an engagement, generating an interim report,
regenerating after CVE or OWASP enrichment, or producing the
input for generating-executive-summary.
Threshold: findings missing required fields are dropped. HIGH
and CRITICAL findings highlighted in the summary section.
Trigger with: "compose vuln report", "write pentest report",
"generate vulnerability deliverable", "render findings to report".
allowed-tools:
- Read
- Write
- Bash(python3:*)
- Glob
disallowed-tools:
- Bash(rm:*)
- Bash(curl:*)
- Bash(wget:*)
- Write(.env)
- Edit(.env)
version: 3.30.0
author: Jeremy Longshore <jeremy@intentsolutions.io>
license: MIT
compatibility: Designed for Claude Code
tags:
- security
- reporting
- vulnerability-report
- cvss
- pentest
---
# Composing Vulnerability Report
## Overview
After cluster 1-4 scan skills run, each one produces a Findings
file. A typical engagement ends up with eight to twenty such files
across the different skill categories. The customer wants ONE
vulnerability report — comprehensive, deduplicated, organized by
severity, with each finding cross-referenced to its source skill
and target.
This skill consumes one or more findings files (JSONL preferred,
JSON list also accepted), deduplicates entries by the canonical
fingerprint defined in `lib/finding.py`, enriches each finding
with a CVSS v3.1 vector when one isn't present (using a deterministic
heuristic based on severity + category — explicitly noted as
"derived, not assigned by NVD" in the output), and emits a single
markdown report with per-finding sections plus a top-level
summary table.
The report has a defined structure that downstream tools (next
two skills in cluster 6) consume:
1. **Header** — engagement ID, generation timestamp, source files
2. **Summary table** — finding count by severity
3. **Per-severity sections** — CRITICAL first, then HIGH, MEDIUM,
LOW, INFO
4. **Per-finding subsections** — title, severity, target, detail,
remediation, evidence, references
## When the skill produces findings
| Finding | Severity | Threshold | Affected control |
|---|---|---|---|
| Source file unparseable | **HIGH** | JSON/JSONL parse fails | (operational) |
| Finding missing required field | **HIGH** | A finding record is missing title, severity, target, detail, or remediation | (operational) |
| Duplicate fingerprint across files | **INFO** | Same finding appears in N>1 sources; reported as deduplication count | (informational) |
| Source file has zero findings | **INFO** | Empty or all-info-only file; reported but not an error | (informational) |
| Report generated cleanly | **INFO** | Positive confirmation | (informational) |
## Prerequisites
- Python 3.9+
- One or more findings files in JSON or JSONL format produced by
any cluster 1-4 scan skill (which all share `lib/finding.py`
schema)
## Instructions
### Step 1 — Gather findings sources
By default the skill reads every file matching
`engagement/findings/*.json` and `engagement/findings/*.jsonl`.
Override with `--source FILE` (repeatable).
### Step 2 — Run the composer
```bash
python3 ./scripts/compose_report.py engagements/acme-2026-q2/
```
Options:
```
Usage: compose_report.py PATH [OPTIONS]
Options:
--source FILE Specific findings file (repeatable; overrides default glob)
--report-output FILE Write the composed report here (default:
PATH/reports/vulnerability-report.md)
--engagement-id ID Override the engagement ID (default: parse from PATH/roe.yaml)
--output FILE Operational findings output (this skill's own findings)
--format FMT json | jsonl | markdown (default: markdown)
--min-severity SEV Filter report to findings at or above this severity
--include-info Include INFO-severity findings in the report (default: omit)
```
### Step 3 — Review the report
The output report has a predictable structure. The header
identifies the engagement, the source files, and the generation
timestamp. The summary table shows finding counts by severity.
Per-severity sections follow.
Each finding subsection includes a stable anchor (the fingerprint)
so cross-references from later artifacts (executive summary,
OWASP mapping) resolve into the report cleanly.
### Step 4 — Verify against sources
```bash
python3 ./scripts/compose_report.py engagements/acme-2026-q2/ --format json --output /tmp/compose-findings.json
jq '.[] | select(.severity == "high")' /tmp/compose-findings.json
```
If the report references a finding the operator didn't expect,
trace back via the finding's `skill_id` + `target` to the source
file.
## Examples
### Example 1 — End-of-engagement report
```bash
python3 ./scripts/compose_report.py engagements/acme-2026-q2/ \
--report-output engagements/acme-2026-q2/reports/vulnerability-report.md
```
### Example 2 — Interim report mid-engagement
```bash
python3 ./scripts/compose_report.py engagements/acme-2026-q2/ \
--min-severity high \
--report-output engagements/acme-2026-q2/reports/interim-2026-06-15.md
```
`--min-severity high` produces an interim report covering only
HIGH and CRITICAL findings — useful for in-engagement customer
syncs.
### Example 3 — Regenerate after OWASP mapping
```bash
python3 ./scripts/compose_report.py engagements/acme-2026-q2/ \
--source engagements/acme-2026-q2/findings/all-findings-with-owasp.jsonl \
--report-output engagements/acme-2026-q2/reports/vulnerability-report-v2.md
```
Re-run after `mapping-findings-to-owasp-top10` has enriched each
finding with its OWASP category; the regenerated report includes
the OWASP tag in each per-finding subsection.
## Output
JSON / JSONL / Markdown per `lib/report.py` for the skill's own
operational findings. The PRIMARY output is the composed
vulnerability report, written as standalone Markdown to the
`--report-output` path.
Each operational Finding includes:
- `id` — `compose::<issue>::<source-file>`
- `severity` — CRITICAL / HIGH / MEDIUM / INFO
- `category` — `report-composition`
- `summary` — what went wrong (or right) during composition
- `evidence` — source files, finding counts, dedup stats
## Error Handling
- **PATH missing or empty** → emits CRITICAL operational finding,
exits 1.
- **Source file unparseable** → emits HIGH operational finding,
skips the file, continues with remaining sources.
- **No findings files found** → emits HIGH operational finding,
exits 1.
- **Output report path not writable** → emits HIGH operational
finding, exits 1.
- **Finding missing required fields** → emits HIGH operational
finding, omits that record from the report, continues.
## Resources
- `references/THEORY.md` — Vulnerability-report structure history
(NIST SP 800-115, OWASP Testing Guide), CVSS v3.1 vector
composition, severity scoring tradeoffs (CVSS vs intrinsic vs
EPSS), finding-deduplication theory, why fingerprint-based dedup
beats title-based
- `references/PLAYBOOK.md` — Report-template variants per
audience (technical, executive, regulatory), per-finding
remediation phrasing patterns, evidence-redaction patterns
for distributed reports, cross-reference protocol with the
OWASP-mapping and exec-summary skills
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!