Finding 3 of 7HighValidated by researcher
Any signed-in user can read other customers’ invoices
GET /api/v1/invoices/:id on app.example.com
Summary
The invoices endpoint checks that a request is signed in, but not that the invoice belongs to the caller’s account. Changing the ID in the URL returns another customer’s invoice, including billing contact and amounts.
Steps to reproduce
- Sign in as test user A (account acct_1a2b) and open any invoice.
- Note the request to /api/v1/invoices/4790, which returns A’s invoice.
- Replay the request with ID 4821, an invoice created under test user B (account acct_7f3e).
- The API responds 200 OK with B’s invoice. Repeated with a second pair of test accounts.
Evidence
GET /api/v1/invoices/4821 HTTP/1.1
Authorization: Bearer [redacted: user A]
HTTP/1.1 200 OK
{ "invoice": 4821, "account": "acct_7f3e", "total": 18400 }Business impact
Any customer can enumerate invoice IDs and read other customers’ billing data. Depending on your contracts and jurisdiction, exposure like this may need to be disclosed.
How to fix it
- Scope the invoice lookup to the caller’s account in the query itself, not after fetching.
- Return 404 rather than 403 for invoices outside the account, so IDs can’t be probed.
- Add an automated test that requests another account’s invoice and expects 404.
Retest scheduled after your fix is deployed.