GuardAPI

Fix BOLA (Broken Object Level Authorization) in Koa

BOLA (Broken Object Level Authorization) remains the apex predator in API security. In Koa, this manifests when a route handler blindly trusts user-supplied input—like a UUID or integer ID—to fetch a resource without verifying the requester's ownership. If you're fetching data based solely on `ctx.params` without scoping the query to `ctx.state.user.id`, you're practically handing the keys to your database to anyone with Burp Suite and a basic intruder payload.

The Vulnerable Pattern

router.get('/api/invoice/:id', async (ctx) => {
  const { id } = ctx.params;
  // VULNERABLE: No ownership check. Any authenticated user can access any invoice by ID.
  const invoice = await Invoice.findById(id);
  if (!invoice) return ctx.status = 404;
  ctx.body = invoice;
});

The Secure Implementation

To kill BOLA in Koa, you must implement resource-level access control at the database query level. First, ensure your authentication middleware (like koa-jwt) populates `ctx.state.user`. Second, never execute a `findById` or `findOne` using only the client-provided ID. Always include the `ownerId` (or equivalent relationship field) in the query filter. If the record doesn't exist for that specific user, return a 404. This prevents 'IDOR' style horizontal privilege escalation where User A accesses User B's data by simply incrementing an integer or guessing a UUID.

router.get('/api/invoice/:id', async (ctx) => {
  const { id } = ctx.params;
  const userId = ctx.state.user.id;

// SECURE: Scope the query to the authenticated user’s ID const invoice = await Invoice.findOne({ _id: id, ownerId: userId });

if (!invoice) { // Use 404 to prevent resource enumeration/discovery ctx.status = 404; ctx.body = { error: ‘Resource not found’ }; return; }

ctx.body = invoice; });

About this page

Framework notes in /guides are generated sketches kept for URL stability. They are not human pentest reports and they are not GuardAPI scan output. The product is a GET-only BOLA merge gate. Maintained by GuardAPI. Questions: [email protected]