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 ID | Name | Severity |
|---|---|---|
| CWE-250 | Execution with Unnecessary Privileges | HIGH |
| CWE-639 | Insecure Direct Object Reference | CRITICAL |
| CWE-732 | Incorrect Permission Assignment | HIGH |