

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
Authentication answers the question, "Who are you?" Authorization answers "What are you allowed to do?"
Broken access control happens when the server forgets to ask that second question. It's usually a careless mistake, not some clever Linux-kernel exploit:
Every protected action needs a server-side permission check. Not in the UI. Not in the mobile app. Not in a hidden form field. On the server. On every request.
A secure endpoint does two things, in order:
This endpoint has a problem:
app.get("/api/documents/:id", requireAuth, async (req, res) => {
const doc = await db.documents.findById(req.params.id);
if (!doc) return res.status(404).json({ error: "Not found" });
res.json(doc);
});
It checks that the user is logged in, but it lets any logged-in user see any document just by changing the ID in the URL!
To fix it, add a doc.ownerId !== req.user.id check. If the document belongs to another user, return a 404 Not Found response:
app.get("/api/documents/:id", requireAuth, async (req, res) => {
const doc = await db.documents.findById(req.params.id);
if (!doc || doc.ownerId !== req.user.id) {
return res.status(404).json({ error: "Not found" });
}
res.json(doc);
});
Returning the same 404 Not Found response for missing and unauthorized documents also avoids confirming that another user's document exists. A 403 Forbidden response is fine when it's not sensitive that a resource exists, but a 404 reveals even less here.
Attackers don't need clever exploits. They try the obvious things and see what the server lets through:
If the server doesn't enforce permissions, an attacker will eventually find something that works.
The order-detail route returns any order whose ID appears in the URL. Enforce order ownership on the server.
npm run db:reset
npm run dev
With Bearly Secure still running, run and submit the CLI tests from the project root.