Skip to content
Severity Labs
← All posts

What good bug reports look like

Severity Labs · Notes

What good bug reports look like

After a thousand reports across a hundred programs, the difference between the ones engineers fix and the ones they ignore comes down to four things.

April 22, 20263 min read

Most security teams know the feeling. A report lands in security@, the title is something like "Critical vulnerability!!!", and the body is a single paragraph that asks for a bounty before describing what was actually found. You skim it. You can't tell what's broken. The hunter is asking what the fix is worth before you've established that anything is wrong.

These reports get triaged last, fixed never, and quietly move the needle on how the program is perceived. Hunters notice the silence. The good ones move on.

After triaging more than a thousand reports across more than a hundred programs, here's what separates the ones engineers actually fix from the ones that rot.

1. The first sentence tells you the bug

A good report opens with something like:

Stored XSS in the reviewer comment field at /reviews/{id}/comments allows session theft of any authenticated reviewer who opens an affected review.

You know the bug class, the location, and the impact in eighteen words. You can route it without reading further. You can decide severity before you've read a single repro step.

A bad report opens with:

I found a critical issue in your application that could lead to serious consequences for your users and business.

Zero information. The only thing this tells you is that the rest of the report is going to be a treasure hunt.

2. Repro steps work the first time

Good repro steps are numbered, executable, and contain every detail needed to land at the same end state. They include the request method, the URL, the exact payload, the authentication context (and how to obtain it if non-trivial), and the expected vs. actual response.

If a triager has to fill in blanks, guess the right user role, infer the payload encoding, or work out which environment to test against, the bug sits in the queue while they go back to the hunter for clarifications. Days lost.

The best reports include a curl command you can paste. The very best include a self-contained script.

3. Impact is concrete and bounded

"This is critical" is not an impact statement. "An unauthenticated attacker can read any user's session cookie within five seconds of them visiting an affected review" is.

Concrete impact does two things. It lets the triager assign severity without re-deriving the math, and it tells engineers what they're actually defending against, which informs the fix.

Bounded impact is just as important. Honest hunters call out what the bug doesn't do. "This requires the victim to be logged in and click a specific link within thirty seconds" is real and useful. Inflating impact to chase a higher bounty is the fastest way to lose triager trust, and triagers have memories.

4. The suggested fix shows the hunter understood the bug

Not every report needs a fix recommendation. But when one is included and it makes sense, when it shows the hunter understands not just that the bug exists but why, the bar for severity goes up. It tells the triager: this person reproduced it, understood the underlying cause, and thought about it as an engineer would.

A bad fix recommendation looks like "use a WAF" or "sanitize all input". These are non-answers. A good one looks like:

The handler at app/reviews/comments_controller.rb:42 passes params[:body] directly to Comment.new. The body field renders through <%== @comment.body %> in _comment.html.erb, which is raw-output. Either switch to <%= ... %> (Rails-escaped) or run the body through sanitize with an explicit allow-list before storage.

That's a fix you can ship.

What this means for hunters

Your reports compete for attention with whatever else is in the inbox. Lead with the bug. Make the repro work the first time. Bound the impact honestly. If you have a fix in mind, write it like an engineer would.

You'll get faster triage, larger bounties, and the kind of relationship with security teams that gets you invited to private programs.

What this means for security teams

If your reports look like the bad examples above, the problem isn't always the hunter. Sometimes your scope is unclear, your policy doesn't ask for specific information, or your acknowledgement template doesn't tell hunters what good looks like. Triage is a two-way conversation, and the program sets the tone.

If you'd rather not run that conversation yourself, that's what we do.

Get started

Stop letting reports pile up.

Hunters lose interest. Engineers lose mornings. The next report is already in the inbox.