

0 / 2 embers
0 / 3000 xp
click for more info
Complete a lesson to start your streak
click for more info
Still calibrating
click for more info
Not enough gems
Cost: 6 gems
1: Principle of Least Privilege
incomplete
2: Preventing Broken Access Control
incomplete
3: Don't Trust the Client
incomplete
4: Access Control Models
incomplete
5: Attribute-Based Access Control
incomplete
6: RBAC vs. ABAC
incomplete
7: Insecure Direct Object References
incomplete
8: Securing File Downloads
incomplete
9: Signed URLs
incomplete
Back
ctrl+,
Next
ctrl+.
This lesson's interactive features are locked, please to keep using them
Putting database identifiers in URLs is normal. It becomes unsafe when the server uses a client-controlled identifier to load an object without checking whether the requester is allowed to access it.
When broken access control involves an object identifier, it's called an Insecure Direct Object Reference (IDOR).
The fix is the same: check permissions on the server before returning any object data. Database IDs are not secrets, so just because an incoming request knows a user's order ID does not mean that user is allowed to see it.
app.get("/api/orders/:id", requireAuth, async (req, res) => {
const order = await db.orders.findById(req.params.id);
if (!order || order.ownerId !== req.user.id) {
return res.status(404).json({ error: "Not found" });
}
res.json(order);
});
Another strong pattern is to include ownership directly in the database lookup. You still need to handle a missing result, but an unauthorized order never leaves the database:
SELECT *
FROM orders
WHERE id = ? AND user_id = ?
Bearly Secure's order-detail API returns any order to any authenticated user. Fix the IDOR so account users can retrieve only their own orders.
With Bearly Secure still running, run and submit the CLI tests from the project root.