Beginner levelFree

How to write a bug bounty report that gets accepted — structure and common mistakes

The ideal structure of a bug bounty report: title, summary, impact, steps to reproduce, PoC, remediation. The 10 mistakes that get your report rejected.

Gorka El BochiMay 11, 202612 min

Quick answer

An accepted report has 6 parts: a specific title (vuln + endpoint + impact), a 2-line summary, business-oriented impact (not technical), numbered and reproducible steps to reproduce, a PoC (video + curl), and concrete remediation. The 3 mistakes that kill reports: inflated severity, not searching for dupes first, a vague PoC. Typical bounty for a well-written report vs the same bug written badly: a 2-3× difference in payout.


The title formula

The title shape triage accepts without thinking:

css
[Vulnerability] in [Endpoint] leads to [Impact]

Good examples:

  • Stored XSS in /api/v1/comments leads to account takeover
  • IDOR in /api/users/{id}/orders allows reading any user's order history
  • Unauthenticated SSRF in /api/preview-url leads to AWS metadata access

Bad examples:

  • XSS — no context
  • Critical bug in production!!! — clickbait, triage discounts it
  • Found a vulnerability — which one?

[!tip] The title test If triage can't understand what you did and what happened by reading the title alone, it's badly written. Rewrite it until a tester with no context knows the severity and the sink.


Full structure — template

markdown
## Summary
[2 lines — what you found and what the business impact is]

## Severity
[Your proposed severity + CVSS 3.1 with justification]

## Impact
[What the attacker can do. Business language, not technical.]

## Steps to reproduce
1. ...
2. ...
3. ...

## Proof of Concept
[Video + reproducible curl + screenshots]

## Suggested remediation
[Concrete fix. If you know the stack, even better.]

## References
[Links to docs, similar CVEs, blog posts]

Anatomy of each section

Summary — 2 lines, no more

Triage reads 50 reports a day. If your summary needs 4 paragraphs to be understood, you've already lost.

Good:

The /api/v1/users/{id}/exports endpoint doesn't validate that the id in the path matches the userId in the JWT. Any authenticated user can download the CSV exports of any other user (full PII: name, email, order history).

Bad:

I found a very critical IDOR in the app that lets you read other users' data and it's very serious because it exposes PII and you should fix it ASAP.

Impact — business language

Triage is usually technical, but the report goes up to managers/legal before the payout. Speak their language.

Good:

An authenticated attacker can enumerate exports for the platform's 4.2M users (the id is sequential and numeric). Each export contains full PII regulated by GDPR Art. 4(1). Estimated cost of regulatory notification: €15k-€50k. Additional reputational damage if leaked.

Bad:

It's an IDOR that lets you read data.

Steps to reproduce — copy-paste-able

Each step must be executable with no extra context. Include full URLs, headers, raw body.

markdown
1. Create two accounts: victim (id=1001) and attacker (id=2042).
2. Log in as attacker. Get the JWT from the response (cookie `auth_token`).
3. Make the following request with the attacker's JWT but the victim's id:

```bash
curl -X GET 'https://target.com/api/v1/users/1001/exports' \
  -H 'Authorization: Bearer <attacker_JWT>' \
  -H 'Accept: application/json'
  1. Response: 200 OK with the full CSV of user 1001.
csharp

### PoC video — the multiplier

The PoC video is what separates €500 from2500 on the same bug. Triage approves it 3× faster.

**Video template (60-90 seconds):**

0:00-0:10 → Log in as attacker. Show the user id. 0:10-0:30 → Log in as victim in an incognito window. Show private data. 0:30-0:50 → Back to attacker. Make the malicious request. Show the response. 0:50-1:00 → Compare leaked data vs the victim's data. Perfect match. 1:00-1:30 → Cleanup: close sessions, confirm logout.

yaml

> [!success] PoC video tools
> Loom (web), OBS Studio (desktop), QuickTime (Mac). No audio narration  triage prefers a silent video with text annotations. Upload to YouTube unlisted or to the program's service if offered (H1 Attachments, Bugcrowd Files).

---

## CVSS 3.1 — the 4 vectors that matter

You don't need to memorize CVSS, but understanding these 4 moves the severity 2 points:

| Vector | Raises score | Lowers score |
|---|---|---|
| `AV` (Attack Vector) | Network (N) | Local (L) |
| `AC` (Attack Complexity) | Low (L) | High (H) |
| `PR` (Privileges Required) | None (N) | High (H) |
| `UI` (User Interaction) | None (N) | Required (R) |

**Rules that apply 90% of the time:**
- Bug reachable via HTTP  `AV:N`.
- No weird pre-conditions  `AC:L`.
- Works without login  `PR:N` (Critical likely).
- Works with a victim click  `UI:R` (Medium likely).

Example: an auth-required stored XSS that needs the victim to open a page  `AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:L/A:N` = 8.3 (High).

---

## The 10 mistakes that get reports rejected

| # | Mistake | How to avoid it |
|---|---|---|
| 1 | Not searching for dupes before submitting | Search disclosed reports + Hacktivity with the bug's keywords |
| 2 | Inflated severity (CVSS 9.0 for an info leak) | Be conservative. Triage rewards honesty. |
| 3 | Vague PoC ("try this and you'll see") | Full curl + video + numbered steps |
| 4 | Not testing your own repro before submitting | Log out, open incognito, repeat your steps. |
| 5 | Reporting out-of-scope issues | Read the **full** scope before starting |
| 6 | No impact statement | Always include "what the attacker can do in business terms" |
| 7 | Reporting trivial config issues (HTTP headers, banner version) | Only if there's a chain with real impact |
| 8 | Multiple bugs in one report | One report = one vuln. Separate reports get paid separately. |
| 9 | Aggressive tone in comments | "This is Critical, I don't get how you can't see it"  guaranteed N/A |
| 10 | Not replying to triage within 7 days | Reports in queue get closed without payout |

> [!warning] Anti-dupe checklist
> Before submitting: search the platform with 3 different keywords from the bug (endpoint, vuln type, payload). If you find even a similar one, read it thoroughly. Better to spend 30 more minutes analyzing than to eat a dupe.

---

## Templates for the most common reports

### Reflected XSS

```markdown
## Summary
The `q` parameter in `/search` reflects the user's input into the HTML context without sanitizing it, allowing arbitrary JavaScript execution.

## Steps to reproduce
1. Visit: https://target.com/search?q=<script>alert(document.domain)</script>
2. Observe the alert with the domain  XSS confirmed.

## Impact
An attacker can craft a malicious URL and send it to authenticated users. On click, the script executes in the victim domain's context  cookie theft (HttpOnly not verified), actions on behalf of the user, defacement.

## PoC
[video stealing a cookie and exfiltrating to the collaborator]

IDOR

markdown
## Summary
The `/api/users/{id}/data` endpoint doesn't validate ownership between the `id` in the path and the request JWT. Any authenticated user reads other users' private data.

## Steps to reproduce
1. Create 2 accounts: A (id=1001), B (id=1002).
2. Log in as A. Capture the JWT.
3. Request: GET /api/users/1002/data with A's JWT → 200 OK with B's data.

## Impact
Full enumeration of the PII of the platform's N users (sequential id). GDPR violation.

SQLi

markdown
## Summary
The `category` parameter in `/products/list` is vulnerable to error-based SQLi. The payload `' OR 1=1--` triggers a MySQL error leaking the query structure.

## Steps to reproduce
1. GET /products/list?category=' OR 1=1-- → 500 with MySQL error
2. Confirm via sqlmap: `sqlmap -u "https://target/products/list?category=1" --dbs`
3. Output: 12 databases, including `users_prod`.

## Impact
Full read of the `users_prod` DB (including password hashes, emails, payment refs). Possible RCE via `INTO OUTFILE` if the MySQL user has the FILE privilege.

How to handle disagreements with triage

Triage marks your report as "Informational" or "N/A" when you think it's High. What to do:

  1. Read their justification twice. They're often right.
  2. Respond with data, not emotion. Cite the program's docs, equivalent CVEs, the target's own blog posts.
  3. Re-PoC with a clearer scenario. If they said "no impact", record a video showing real exfil with the bug.
  4. Escalate once if you still disagree. "Mediator request" on H1, "Request second opinion" on Bugcrowd. Only once — escalating twice marks the report as problematic.
  5. Accept and learn. Sometimes triage is subjective. Better an accepted N/A and keeping the relationship with the program than winning the battle and losing the account.

Hunting checklist — pre-submit

  • Title with shape [Vuln] in [Endpoint] leads to [Impact]
  • Summary in 2 lines, business language
  • Your own CVSS 3.1 with justification for each vector
  • Numbered, reproducible-from-scratch steps
  • PoC video 60-90s + raw curl + screenshots
  • Impact statement with business consequences (PII, GDPR, financial, reputational)
  • Concrete remediation (not generic "validate input")
  • Dupe search in disclosed reports + Hacktivity
  • I logged out, opened incognito, repeated my steps — it works
  • The bug is in scope (I re-read the scope at the end)
  • I didn't mix multiple bugs into one report

Practice real vulnerabilities to train your PoC and documentation with bug bounty labs.

Keep learning · free account

Save your progress, unlock advanced payloads and rank your flags.

Create account
Premium · 1 more technique

There's an extra payload at the end

The exact PoC video template that triples triage speed — used by top H1 hunters earning >$100k a year.

Unlock

€7.99/mo · cancel anytime

Related articles

hunters training
709

hunters training

labs from real reports
55

labs from real reports

completions
1,204

completions

in bounties practiced
$213,970

in bounties practiced

46 flags captured this week·Real reports from HackerOne · Bugcrowd · Intigriti·No commitment·Free Academy