Any signed-in user can download any customer’s invoice
Summary
The invoice endpoint checks that you’re signed in, and never checks that the invoice is yours. Numbers are sequential, so one account can walk through every customer’s invoices.
Impact
Any registered user can read every customer’s name, billing address and tax ID. Sign-up is free, so the bar is one email address.
Rated High, above the 6.5 base, because the data is personal and the ID is guessable.
- Sign in as test customer A and download your own invoice, number 10421.
- Repeat the request with the next number, 10422, which belongs to test customer B.
- The server returns customer B’s invoice.
GET /api/v2/invoices/10422/pdf HTTP/1.1
Host: app.example.com
Authorization: Bearer HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="INV-10422.pdf"The PDF shows test customer B’s name and billing address (screenshot in the appendix, redacted: ).
Look the invoice up through the signed-in customer, and answer 404 for anyone else’s.
-- before
SELECT * FROM invoices WHERE id = :id;
-- after
SELECT * FROM invoices WHERE id = :id AND customer_id = :session_customer;Add a test that asks for another customer’s invoice and expects 404. Random IDs are a second layer at best.
Retest passed
Other customers’ invoices now return 404, with or without /pdf, and the new test runs in the pipeline. Closed in the updated report.









