OWASP A01 · Broken Access ControlCWE-639 Authorization Bypass Through User-Controlled KeyHigh
IDOR — reading another tenant's data by changing an id
An endpoint returns any record by id without checking who owns it.
What happened
Insecure Direct Object Reference is the most common access-control bug and access control has been OWASP #1 for four cycles. /api/invoice/1002 → change to 1003 and you read another customer's invoice, because the server trusts the id in the URL and never checks ownership. It passes every scanner because each request is individually 'valid'.
The code
✕ Vulnerable — Access control
app.get("/api/invoice/:id", auth, async (req, res) => {
const inv = await db.invoice(req.params.id); // no ownership check
res.json(inv);
});✓ Fixed — Access control
app.get("/api/invoice/:id", auth, async (req, res) => {
const inv = await db.invoice(req.params.id);
if (!inv || inv.orgId !== req.user.orgId) return res.sendStatus(404);
res.json(inv); // enforce ownership server-side, deny by default
});References
Educational case study. The "vulnerable" snippet is a minimal teaching example, not a working exploit. Benteng · a Palu Gada tool.