Findings
Every finding is a confirmed exploit with a reproduction. Here's how to read one.
grayhat reports only what it could break. Each finding on a pull request has the same parts.
Anatomy of a finding
| Part | Example |
|---|---|
| Severity | critical, high, medium, low |
| Status | EXPLOIT VERIFIED |
| Weakness | CWE-639 (authorization bypass through a user-controlled key) |
| Title | Any signed-in user can read any invoice |
| Cause | This PR removed requireOwner() from GET /invoices/:id |
| Proof of concept | The exact request that worked against the sandboxed app |
| Fix | A link to the fix PR, when one passed both checks |
Severity
critical
Data from other users or tenants is exposed, or code runs that shouldn’t. Fix before merging.
high
A real attack path with a narrower blast radius, such as a race that double-spends a balance.
medium
Exploitable, but needs an unusual precondition or an already-privileged user.
low
Hardening: the exploit worked, but the impact is minor.
What it catches
Pattern scanners look for dangerous calls. The bugs that hurt most are usually a missing check, or two ordinary lines in the wrong order:
- IDOR:
GET /invoices/:idreturns anyone’s invoice - Business logic: coupons stack, or a refund exceeds the order total
- Race conditions: check-then-spend on a balance with no lock
- Home-grown auth: a token compared with
==that never expires - Hidden code: an encoded payload in a
postinstallscript
Dismissing a finding
Reply to a finding to dismiss it with a reason. grayhat remembers the dismissal for the rest of that pull request and won’t raise the same finding again on later pushes.