Skip to content

About

Draft, score (CVSS 3.1) and lint HackerOne/Bugcrowd vulnerability reports before you submit — completeness + leaked-secret gate. Zero-dependency Python.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

Repository files navigation

finding-forge

tests

Turn a verified finding into a clean, complete, submission-ready report — with accurate CVSS 3.1 scoring and a pre-submit lint that catches missing sections and leaked secrets.

finding-forge encodes one rule of good bug-bounty work: one clean, reproducible report beats ten noisy ones. It scaffolds the sections triagers actually read, scores severity with a CVSS v3.1 implementation that matches the FIRST calculator to the decimal, and gates your draft before you paste it into HackerOne or Bugcrowd so a stray Authorization: header or an empty Steps to Reproduce never goes out under your name.

  • Zero dependencies. Pure Python standard library (argparse, re, json, math). Python 3.9+.
  • No network, no telemetry, no secrets. It reads your draft locally and prints a verdict. Nothing leaves your machine.
  • CI-friendly. lint exits non-zero on hard problems, so it drops straight into a pre-commit hook or pipeline.

Why report quality is the whole game

Triage is a queue. A report that is missing a repro, hand-waves impact, or forces the triager to guess your CVSS gets bounced to Needs More Info — and every round-trip is days of latency and a dent in your signal. A report that lands complete on the first read gets triaged fast, scored fairly, and paid. finding-forge removes the three things that most often go wrong:

  1. Missing structure — you forget a section under time pressure. The template won't let you.
  2. Wrong severity — hand-computed CVSS is error-prone; a wrong vector invites a downgrade. The math here is exact.
  3. Leaked material — you paste real traffic into the PoC and ship a live token or a customer's PII. The lint catches it first.

Install

git clone https://github.com/jakubkozub/finding-forge
cd finding-forge
pip install .        # provides the `finding-forge` command

Or run it straight from a checkout with no install at all:

python -m finding_forge --help

Usage

1. new — scaffold a report

finding-forge new --type idor --title "IDOR in /api/invoices lets users read others' invoices" -o report.md

Supported bug-class templates:

--type Class
idor IDOR / Broken Object-Level Authorization
broken-access-control Broken Access Control / Privilege Escalation
auth-bypass Authentication Bypass
xss Cross-Site Scripting (reflected / stored / DOM)
ssrf Server-Side Request Forgery
sqli SQL Injection
csrf Cross-Site Request Forgery
info-disclosure Sensitive Information Disclosure
generic Anything else (neutral skeleton)

Every template emits the same skeleton triagers expect — Title, Summary, Affected Asset, CVSS, Impact, Steps to Reproduce, Proof of Concept, Remediation, References — pre-filled with class-specific hints and a suggested CVSS vector that is scored live:

# IDOR in <endpoint> allows reading/modifying other users' <object>

> Bug class: **IDOR / Broken Object-Level Authorization** — DRAFT. Fill every `<TODO: ...>`, redact real secrets, and delete this banner before submitting.

## Summary

The `<TODO: endpoint>` endpoint authorizes the *session* but not *ownership* of the
requested object. Any authenticated user can read `<TODO: describe object>` ...

## CVSS

- Vector: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N`
- Base score: **6.5 (Medium)**
...

Fill in every <TODO: ...>, drop in your PoC, and you have a report. Placeholders are written so the linter can spot anything you left behind.

2. cvss — score or build a vector

Score an existing vector string:

$ finding-forge cvss "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N"
Vector      : CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Base score  : 6.1
Severity    : Medium

Build one from individual metrics (handy when you're reasoning about impact metric by metric):

$ finding-forge cvss --av N --ac L --pr N --ui N --s U --c H --i H --a H
Vector      : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Base score  : 9.8
Severity    : Critical

Add --explain for the expanded metric names, or --json for machine-readable output:

$ finding-forge cvss "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N" --json
{
  "vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
  "base_score": 7.5,
  "severity": "High",
  "metrics": { "AV": "N", "AC": "L", "PR": "N", "UI": "N", "S": "U", "C": "H", "I": "N", "A": "N" }
}

The base-score math follows the FIRST CVSS v3.1 specification exactly — including the scope-changed impact term and the integer-scaled Roundup function — and is unit-tested against the official calculator for a spread of canonical vectors (7.5 High, 9.8 / 10.0 Critical, 6.1 Medium, 3.1 Low, 0.0 None, and more).

3. lint — the pre-submit gate

$ finding-forge lint report.md
finding-forge lint - report.md

Sections
  [FAIL] Steps to Reproduce - required section missing
  [PASS] Title - IDOR in invoice download allows reading ...
  [PASS] Summary - present
  ...

Secrets & PII
  [FAIL] JWT token - eyJhbGciOiJI...sR8U (line 16)
  [FAIL] Authorization header - Authorizatio...sR8U (line 16)
  [FAIL] Bearer token - Bearer eyJhb...sR8U (line 16)
  [FAIL] Cookie header - Cookie: sess...2543 (line 17)

CVSS
  [PASS] CVSS vector - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N = 7.5 (High)

Result: FAIL - 5 error(s), 2 warning(s)

lint checks three things:

  • Completeness — every expected section is present and non-empty (placeholder-only sections don't count).
  • Secrets & PII — leaked JWTs, AWS/GitHub/Slack/Google/Stripe keys, private-key blocks, Authorization / Cookie / Bearer / Basic-auth headers with real values, high-entropy strings, unredacted emails, and Luhn-valid card numbers. Redacted placeholders (<token>, $SESSION, example.com) are recognised and left alone, so a properly sanitised report stays quiet.
  • Quality — a CVSS vector is present and actually parses, repro steps are enumerated, and there's no vague filler (might, could possibly, ...) or leftover <TODO>.

How the gate works

Level Meaning Exit code
error Hard problem: missing section, leaked secret, no CVSS non-zero — blocks submission
warn Worth a look: email/PII, filler, leftover <TODO> zero by default; non-zero with --strict

Use it as a real gate — for example in a pre-commit hook or CI:

finding-forge lint report.md --strict || {
  echo "Report not submission-ready. Fix the items above."; exit 1;
}

Add --json for tooling and --quiet to show only problems.


How it fits the workflow

finding-forge owns the last mile: verified finding → polished report → clean submission.

   recon / testing         finding-forge              submit
  ┌───────────────┐   ┌────────────────────────┐   ┌──────────┐
  │  you find and │   │ new  → draft the report │   │ HackerOne│
  │  VERIFY a bug │──▶│ cvss → score it right   │──▶│ Bugcrowd │
  │  (out of scope│   │ lint → gate before send │   │ VDP / ...│
  │   for this    │   └────────────────────────┘   └──────────┘
  │   tool)       │
  └───────────────┘

It pairs naturally with a redaction step in front of the lint: run your traffic captures through a redactor to strip live tokens and PII, then let finding-forge lint act as the backstop that fails the submission if anything slipped through. The lint is deliberately your seatbelt, not your only line of defence — you should never be relying on it to notice the secret, but you'll be glad it does.


Development

python -m unittest discover -v     # 42 tests, standard-library unittest

The suite asserts the CVSS math against known-correct base scores, that every template renders the full section set, and that the lint fails a report missing Steps to Reproduce and carrying a planted JWT/Cookie while passing a clean, complete report.

License

MIT © 2026 Jakub Kozub. See LICENSE.

About

Draft, score (CVSS 3.1) and lint HackerOne/Bugcrowd vulnerability reports before you submit — completeness + leaked-secret gate. Zero-dependency Python.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages