I'm always excited to connect with professionals, collaborate on cybersecurity projects, or share insights.
You can spot a critical vulnerability, prove that it is real, and still walk away with a rejected report. Not because the bug is weak, but because the report fails to tell the story.
Triagers do not read your report like a blog post. They skim. They search for signal. They decide in seconds whether this is worth their time or not. Bug bounty is not only about payloads and tools. It is also about communication. Your report is your pitch.
If your write up is vague, messy, or missing key pieces, it gets buried under “N/A”, “Informative”, or “Not a security issue”. A solid report on the other hand gets reproduced quickly, escalated faster, and usually rewarded better.
This article walks you through a practical blueprint for writing reports that are easy to read, easy to reproduce, and hard to ignore. No fluff. No corporate templates. Just the structure, wording, and proof that make triagers say “yes”.
Table of contents [Show]
When someone on the triage side opens your report, they are not starting fresh and relaxed. They are usually deep in a queue of dozens or even hundreds of submissions.
In that first quick scan they are trying to answer three questions:
If your report does not answer those three within a few seconds, it becomes work. If it becomes work, it gets delayed or closed.
A clean structure does three things for you:
This is not only about looking professional. Clear structure directly affects your acceptance rate, your payout, and your reputation as a researcher.
Let us walk through a complete report layout using a simple but high impact example: an IDOR in a billing endpoint. Each part has a job. Skip one and the whole thing becomes weaker.
Your title is your headline. It is the first thing a triager sees in their inbox or queue. It should describe the vulnerability and hint at the impact in a single sentence.
Weak: IDOR Bug Found
Better: IDOR in Billing API Allows Viewing Other Users' Invoices
The second one tells us what the bug is, where it lives, and why we should care. Think of your title as the tweet version of your finding. Specific and sharp.
Right under the title, you want a very short summary. Someone should be able to read this block only and still understand the core problem.
## Summary
An Insecure Direct Object Reference (IDOR) exists in the `/api/billing/invoice` endpoint.
By changing the `invoice_id` parameter, an authenticated user can retrieve invoices
that belong to other customers, including their names, addresses, and payment details.
Notice how it answers the three questions:
/api/billing/invoice.No extra story yet. Just enough context to set up the rest of the report.
The description is where you slow down and explain the vulnerability in simple, precise language. Imagine you are explaining it to a new developer on the team.
## Description
The billing API uses the `invoice_id` parameter to return invoice details.
The backend checks that the user is logged in, but it does not verify that the
requested invoice actually belongs to the logged in user.
As a result, any authenticated user can modify the `invoice_id` value and access
invoices generated for other accounts. These invoices contain personally identifiable
information (PII) such as full names, billing addresses, and payment amounts.
The issue exists because authorization is performed only at the session level,
without an ownership check on the requested resource.
Good descriptions answer:
You are not just saying “this is IDOR”. You are showing the exact broken assumption on the backend.
This is the heart of your report. If the triager cannot follow these steps and see the bug, everything else falls apart.
## Steps to Reproduce
1. Create two accounts:
- Account A (attacker): `user1@example.com`
- Account B (victim): `user2@example.com`
2. Log in as Account B and open any invoice from the billing page.
3. Intercept the request that loads the invoice and note the ID value:
`GET /api/billing/invoice?invoice_id=12345`
4. Log out and then log in as Account A.
5. Send the same request as Account A, reusing the victim invoice ID:
`GET /api/billing/invoice?invoice_id=12345`
6. Observe that Account A receives the full invoice details for Account B, including:
- Customer name
- Billing address
- Amount paid
- Invoice date
Key points for strong reproduction steps:
A good test is this: could someone who has never seen the application follow your steps and trigger the bug on a staging environment? If the answer is no, the steps need more detail.
The proof of concept is where you show raw evidence. Think of it as attaching receipts.
## Proof of Concept
### HTTP Request (attacker viewing victim invoice)
```http
GET /api/billing/invoice?invoice_id=12345 HTTP/1.1
Host: example.com
Cookie: session=attacker_session_token
```
### Response:
```json
{
"invoice_id": "12345",
"user_id": "67890",
"user_name": "Jane Doe",
"billing_address": "123 Main St, City, State",
"amount": "$299.99",
"date": "2025-01-15"
}
```Visual Evidence
This is where doubts disappear. Even if your wording is not perfect, a clear screenshot or a short clip removes any question about whether the behavior is real. Triagers trust what they can see.
A mistake many hunters make is assuming triagers can automatically see the severity. They cannot. You must spell out what the vulnerability enables.
## Impact
This vulnerability allows any authenticated user to:
- Access billing information belonging to other users
- Perform large scale enumeration of invoice IDs
- Collect names, addresses, and payment data at high volume
- Use harvested billing records for targeted phishing or identity theft
Realistic example: an attacker signs up for a free account, cycles through predictable
invoice IDs, and downloads thousands of invoices. The collected PII is monetized or
used in social engineering campaigns.
Estimated severity: High
Example CVSS: 7.5 (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N)
This section is your argument. This is where you show why the bug matters beyond the basic “I can see someone else's invoice”.
The more concrete your scenario, the easier it is for a triager to escalate the issue internally.
Providing recommended fixes is optional, but it elevates your report. It signals that you understand the vulnerability deeply enough to guide the solution.
## Remediation
Recommended fix:
Add an ownership check before returning invoice data. The backend must verify that
the invoice being requested belongs to the authenticated user.
Example logic:
```python
def get_invoice(invoice_id, user_id):
invoice = db.get_invoice(invoice_id)
if not invoice or invoice.user_id != user_id:
return {"error": "Unauthorized"}, 403
return invoice
```
**Additional recommendations:**- Implement rate limiting to prevent mass enumeration
- Use UUIDs instead of sequential IDs for invoices
- Add logging and alerting for unauthorized access attempts
```
You do not have to write production-ready code. A clean explanation of what needs to change is more than enough. What matters is clarity: the developer should immediately understand what part of the logic failed and how to reinforce it.
This section also shows maturity. It tells the program that you are not just reporting bugs — you understand secure design, and you are here to help the product improve. That kind of professionalism gets noticed.
Even experienced hunters fall into predictable pitfalls. Avoiding these instantly raises the quality of your submissions.
Fix these and your reports will instantly look cleaner, more professional, and easier to triage.
AI is helpful for organizing thoughts or polishing grammar, but fully AI-written reports sound generic. Triagers can tell. Use AI for support, not substitution.
Do not try to impress with jargon. Your goal is to make the report reproducible, not academic. Simple, direct writing wins every time.
Screenshots and short videos remove uncertainty. A triager can watch a ten-second clip and validate your bug faster than reading a paragraph. Highlight the exact request or field that proves the issue.
If you have multiple bugs, submit your strongest ones first. Programs often prioritize hunters who consistently deliver solid, high-value reports.
Close the browser, reset your session, and try following your own STR from scratch. If you cannot reproduce it alone, neither can the triager.
Combining multiple vulnerabilities is risky. One invalid issue can cause the whole report to be rejected. Split them up — it improves clarity and increases your acceptance rate.
If a report gets closed and you disagree, respond with evidence, not emotion. Triagers are people. Mistakes happen. Clear communication and professionalism build long-term trust.
A strong bug bounty report is clear, structured, and easy to reproduce. When you follow a consistent format, you reduce friction for the triager — and that directly increases your chances of getting accepted and rewarded.
Your goal is simple:
Bug bounty is not only about finding bugs. It is about communicating them in a way that makes action unavoidable.
Write like a professional. Think like a triager. And your reports will stand out immediately.
Your email address will not be published. Required fields are marked *