IDOR: changing one number to see someone else's data
Insecure direct object references are the most common access-control bug in APIs: the endpoint checks that you are logged in, then fetches whatever record ID the request names.
Example
app.get("/allocations/:userId", isLoggedIn, async (req, res) => {
const docs = await allocations.find({ userId: req.params.userId });
res.json(docs);
});app.get("/allocations", isLoggedIn, async (req, res) => {
// the user comes from the session, never from the URL
const docs = await allocations.find({ userId: req.session.userId });
res.json(docs);
});How it happens
Routes like /invoices/:id or /users/:userId/profile pass the ID from the URL straight into a database lookup. Being logged in as user 7 and requesting /invoices/8 returns user 8's invoice. Related mistakes: admin-only middleware that is defined but never added to a route, and writing the whole request body to a record, which lets the caller set fields like role or isAdmin.
How to fix it
Authorisation is per record, not per route.
- Take the current user's ID from the session or token, not from the request
- When an ID must come from the request, check the record belongs to the user before returning it
- Apply role checks to every privileged route, and test them
- Pick accepted fields explicitly instead of saving the whole body
How RepoVerse finds it
- HighRecord looked up by an ID from the request, with no ownership check
Changing the ID in the URL shows or changes another user's data (IDOR / BOLA).
data flow · CWE-639
- HighAdmin-only middleware is defined but never applied to a route
Routes that were meant to be admin-only are reachable by any logged-in user, which is privilege escalation if they change data.
data flow · CWE-285
- ModerateWhole request body written to a database record
The caller can set fields you never meant to expose — `isAdmin`, `role`, `balance`.
data flow · CWE-915
Questions
- What is the difference between IDOR and BOLA?
- They are the same flaw. OWASP's API Security Top 10 calls it Broken Object Level Authorization (BOLA); the older web Top 10 called it Insecure Direct Object Reference.
- Can static analysis find IDOR?
- Partly. RepoVerse flags lookups keyed by a user-, account- or order-style ID from the request in handlers that never read the session or authenticated user. It marks these as likely, because only you know which records are meant to be public.
Related
- CSRF: requests your users never meant to sendHow CSRF (CWE-352) makes a logged-in visitor's browser submit forms to your site, and how CSRF tokens and SameSite cookies stop it in Express and other frameworks.
- Secure session cookies: the flags and the login stepSet session cookies safely: Secure, HttpOnly and SameSite flags (CWE-614, CWE-1004), regenerating the session at login against fixation, with Express examples.
- GitHub security scanner for code, secrets and dependenciesScan a GitHub repository for injection flaws, leaked secrets and vulnerable dependencies. Data-flow traces from request to sink, lockfile-aware, with fixes.
Updated 2026-10-11