GuardAPI

Fix BOLA (Broken Object Level Authorization) in AdonisJS

BOLA (Broken Object Level Authorization), previously known as IDOR, is the most prevalent vulnerability in modern APIs. In AdonisJS, it occurs when a developer fetches a Lucid model based on a user-supplied ID without verifying if the authenticated user has the right to access that specific instance. Attackers exploit this by simply incrementing IDs in the URL or payload to scrape data from other users.

The Vulnerable Pattern

public async show({ params, response }: HttpContextContract) {
  // VULNERABLE: Direct lookup by ID without ownership check
  const project = await Project.find(params.id)

if (!project) { return response.notFound({ error: ‘Project not found’ }) }

return project }

The Secure Implementation

The fix involves moving from a global lookup to a scoped query. By chaining `.where('userId', user.id)` to the Lucid query builder, the database engine enforces authorization at the fetch level. If the ID exists but belongs to another user, the query returns null. For complex logic, use AdonisJS Bouncer policies to centralize these checks: `await bouncer.authorize('viewProject', project)`. Always return a generic 404 on unauthorized access to avoid leaking the existence of private resources.

public async show({ auth, params, response }: HttpContextContract) {
  const user = auth.user!

// SECURE: Query is scoped to the authenticated user’s ID const project = await Project.query() .where(‘id’, params.id) .where(‘userId’, user.id) .first()

if (!project) { // Return 404 instead of 403 to prevent resource enumeration return response.notFound({ error: ‘Project not found’ }) }

return project }

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: support@guard-api.com