Coverage area · 2 checks
API security: authorization and abuse paths
APIs expose your data model directly, so the most common API bugs are about who may touch which object. OpenRouting reviews your handlers for missing ownership checks, mass assignment and unbounded operations.
Illustrative example of how a finding in this area is reviewed.
Why this area matters
Broken object-level authorization (BOLA, also called IDOR) has been number one on the OWASP API Security Top 10 since the list began: an endpoint takes an object ID from the request and returns or updates it without checking the caller owns it. Mass assignment and missing function-level authorization follow close behind (CWE-639, CWE-862, CWE-915).
These bugs are invisible to pattern rules because the code looks normal — the problem is a check that isn't there. The access-control agent reads the handler, the lookup and the surrounding middleware to decide whether the object is scoped to the caller.
What goes wrong in real applications
Broken object-level authorization
Looking up an object by an ID from the request without scoping it to the caller lets any user read or change other users' records by changing the ID.
Mass assignment
Copying the request body straight onto a model lets callers set fields they shouldn't, such as role, owner or price.
Missing function-level authorization
Admin or internal endpoints that only check that a user is logged in, not what they are allowed to do.
Unbounded or costly operations
No pagination limits, no rate limiting and unrestricted GraphQL query depth let one client exhaust the backend or scrape the dataset.
Sample: the risky pattern and the fix
router.patch("/api/accounts/:id", requireLogin, async (req, res) => {
const account = await Account.findById(req.params.id);
if (!account) return res.sendStatus(404);
Object.assign(account, req.body);
await account.save();
res.json(account);
});const UpdateAccount = z.object({
displayName: z.string().max(80).optional(),
timezone: z.string().max(64).optional(),
});
router.patch("/api/accounts/:id", requireLogin, async (req, res) => {
const account = await Account.findOne({ _id: req.params.id, ownerId: req.user.id });
if (!account) return res.sendStatus(404);
account.set(UpdateAccount.parse(req.body));
await account.save();
res.json(account.toPublicJSON());
});Any logged-in user can update any account by changing the ID, and can set any field — including role or owner — because the body is copied wholesale. The fix scopes the lookup to the caller's own account and only accepts two validated fields.
Illustrative code, simplified for clarity — not taken from a customer repository.
What OpenRouting checks in your repository
- Handlers that load objects by a request-supplied ID without an owner or tenant filter
- Request bodies spread or assigned directly onto models
- Routes missing authorization middleware or role checks
- GraphQL resolvers without per-object authorization, and missing depth or complexity limits
- Whether scoping is enforced elsewhere — a base query, a policy layer or middleware (the main false-positive signal)
Scope and limits
- It reads your handlers; it doesn't send requests to your API, so authorization enforced only at a gateway or proxy may not be visible.
- Rate limits configured outside the repository (CDN, API gateway) aren't seen, so a missing-limit finding may already be covered.
Coverage areas reflect OpenRouting's check library. Code, secret and infrastructure scanning run today; other areas are rolling out. Scanners surface candidates and a review agent decides whether each one is real — it doesn't promise to find every issue.
Review agents for this area
- Access control & authorization — Checks that each sensitive action is authorized for the specific object, not just a logged-in user.
- Authentication & JWT — Checks that identity, tokens and sessions are actually verified and hardened.
- Server-side request forgery (SSRF) — Checks whether a server-side request can be pointed at a host the attacker chooses.
Common questions
Can a static scan really find IDOR?
Some of it. Rules flag lookups by request-supplied IDs; the access-control agent then checks for an ownership or tenant check. It won't find every case, especially when authorization logic is spread across services.
Does it cover GraphQL?
Yes, for resolvers in your repository: per-object authorization and query-limit configuration. It doesn't execute queries against your API.