HIGH insecure direct object referenceadonisjscockroachdb

Insecure Direct Object Reference in Adonisjs with Cockroachdb

Insecure Direct Object Reference in Adonisjs with Cockroachdb — how this combination creates or exposes the vulnerability

In AdonisJS, an Insecure Direct Object Reference (IDOR) occurs when an API endpoint uses user-supplied identifiers (e.g., a URL parameter like id) to directly reference a database record without verifying that the authenticated user is authorized to access that specific resource. When the backend uses CockroachDB as the persistence layer, the risk is not in CockroachDB itself, but in how AdonisJS resolves and queries records against CockroachDB without adequate ownership or tenant checks.

Consider a typical route that fetches a "document" by ID:

// routes.ts
Route.get('documents/:id', 'DocumentsController.show')

If the controller directly uses the id to query CockroachDB without scoping to the requesting user, an attacker can manipulate the :id to access another user’s document:

// DocumentsController.ts
import Document from 'App/Models/Document'

export default class DocumentsController {
  public async show({ params, auth }: HttpContextContract) {
    const document = await Document.findOrFail(params.id)
    return document
  }
}

Because the query does not ensure the document belongs to the authenticated user (or a role/tenant the user is allowed to access), this is an IDOR. An authenticated user can change the URL from /documents/123 to /documents/124 and read data they should not see. CockroachDB does not enforce application-level permissions; it simply returns rows that match the query, so the responsibility to enforce authorization lies entirely in AdonisJS logic.

Additional exposure can arise when IDs are predictable (e.g., sequential integers or UUIDs that are not truly random), making enumeration feasible. If logging or error handling inadvertently reveals CockroachDB schema or constraint details, attackers gain insight into data structures to refine IDOR attacks. The API’s OpenAPI spec may also expose parameter names and types without clarifying authorization requirements, which can mislead developers about the security posture.

IDOR can intersect with other checks in middleBrick’s scan, such as BOLA/IDOR and Property Authorization, where the scanner tests whether different users can access or modify each other’s resources. Because the scan is unauthenticated, it may detect endpoints that accept resource identifiers but lack explicit ownership validation, surfacing the missing authorization boundary.

Cockroachdb-Specific Remediation in Adonisjs — concrete code fixes

To remediate IDOR when using CockroachDB with AdonisJS, always scope queries to the requesting user or tenant and enforce authorization before returning or modifying data. Below are concrete, syntactically correct examples.

1. Scope queries to the authenticated user

Ensure every data access ties the CockroachDB row to the authenticated user’s identity:

// DocumentsController.ts
import Document from 'App/Models/Document')
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

export default class DocumentsController {
  public async show({ params, auth }: HttpContextContract) {
    const document = await Document.query()
      .where('id', params.id)
      .where('user_id', auth.user?.id)
      .firstOrFail()
    return document
  }
}

This query adds a user_id filter so that even if an attacker changes the id, CockroachDB will return no rows unless the document belongs to that user.

2. Use route binding with ownership checks

Leverage AdonisJS route model binding to resolve the document and validate ownership in a single step:

// start/routes.ts
Route.get('documents/:document', 'DocumentsController.showByBinding')

// DocumentsController.ts
import Document from 'App/Models/Document'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

export default class DocumentsController {
  protected async resolveDocument({ params }: HttpContextContract) {
    const document = await Document.findByOrFail('id', params.document)
    if (document.userId !== this.ctx.auth.user?.id) {
      throw new Error('Unauthorized')
    }
    return document
  }

  public async showByBinding({ params, response }: HttpContextContract) {
    const document = params.document
    return document
  }
}

Route binding with a manual ownership check ensures that the resolved model matches the authenticated user before proceeding.

3. Apply tenant scoping for multi-tenant setups

In multi-tenant architectures, scope by tenant identifier (e.g., organization_id) instead of or in addition to user ID:

// DocumentsController.ts
import Document from 'App/Models/Document'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

export default class DocumentsController {
  public async index({ auth, request }: HttpContextContract) {
    const tenantId = auth.user?.organizationId
    const documents = await Document.query()
      .where('organization_id', tenantId)
      .execute()
    return documents
  }
}

By anchoring queries to organization_id from the authenticated user, you prevent cross-tenant reads even if IDs are guessed or enumerated.

4. Validate and normalize IDs

Avoid treating raw user input as trustworthy. Normalize and validate identifiers before using them in CockroachDB queries:

// DocumentsController.ts
import { schema } from '@ioc:Adonis/Core/Validator')
import Document from 'App/Models/Document'

const documentSchema = schema.create({
  id: schema.number([
    () => rules.exists({ table: 'documents', column: 'id' })
  ])
})

export default class DocumentsController {
  public async show({ params, auth, validator }: HttpContextContract) {
    const payload = await validator.validate({
      schema: documentSchema,
      data: { id: params.id }
    })

    const document = await Document.query()
      .where('id', payload.id)
      .where('user_id', auth.user?.id)
      .firstOrFail()
    return document
  }
}

This reduces risks from malformed or malicious IDs and ensures the query only returns rows the user is allowed to see.

Related CWEs: bolaAuthorization

CWE IDNameSeverity
CWE-250Execution with Unnecessary Privileges HIGH
CWE-639Insecure Direct Object Reference CRITICAL
CWE-732Incorrect Permission Assignment HIGH

Frequently Asked Questions

Can middleBrick detect IDOR in an API that uses CockroachDB and AdonisJS?
Yes. middleBrick runs unauthenticated checks such as BOLA/IDOR and Property Authorization, which can surface missing ownership validation regardless of the database, including CockroachDB with AdonisJS endpoints.
Does fixing IDOR require changes to the CockroachDB schema?
Not necessarily. IDOR is typically addressed in application logic by scoping queries (e.g., adding user_id or organization_id filters). CockroachDB schema changes are only needed if data model adjustments are required to support proper ownership or tenant isolation.