Excessive Data Exposure in Adonisjs with Cockroachdb
Excessive Data Exposure in Adonisjs with Cockroachdb
Excessive Data Exposure occurs when an API returns more data than necessary, such as internal identifiers, sensitive fields, or related resources that should remain hidden. When Adonisjs applications interact with Cockroachdb, this risk is amplified if query results are serialized directly without filtering. For example, a user profile endpoint that selects all columns from a profiles table might unintentionally expose password hashes, internal status flags, or tenant identifiers to the client.
With Cockroachdb, the distributed SQL layer can return additional metadata in certain drivers when joining across databases or using window functions. If Adonisjs models map these results without pruning, fields like created_at, updated_at, or even internal_role may appear in the response. This becomes critical when related records are included via relationships, such as a hasMany association that pulls in sensitive audit logs stored in Cockroachdb.
Consider an endpoint GET /users/:id that uses a standard Adonisjs Lucid model to fetch a user:
// app/Controllers/Http/UserController.ts
import User from 'App/Models/User'
export async function show({ params }: HttpContextContract) {
const user = await User.findOrFail(params.id)
return user
}
If the User model includes sensitive fields such as password_reset_token or two_factor_secret, and those fields map to columns in Cockroachdb, the API response will contain them. Even when using select projections, Cockroachdb may still return additional columns if the query is constructed incorrectly, especially when using raw queries or complex joins across nodes.
Another common pattern is returning lists of resources without filtering:
// app/Controllers/Http/ReportController.ts
import Report from 'App/Models/Report'
export async function index() {
return await Report.all()
}
If the Report model pulls from a Cockroachdb table that contains internal debugging columns or PII, the entire list is exposed. Adonisjs relationships can compound this; for instance, a hasMany relation to Comment might expose user emails or IP addresses stored in Cockroachdb. Without explicit field selection or serialization rules, developers risk exposing more data than intended.
LLM/AI Security checks within middleBrick help identify these exposures by correlating OpenAPI specifications with runtime data flows. For Cockroachdb-backed Adonisjs APIs, this means detecting when query results include fields that should be restricted and highlighting the need for explicit field filtering or response transformation.
Cockroachdb-Specific Remediation in Adonisjs
To prevent Excessive Data Exposure with Cockroachdb in Adonisjs, explicitly define which fields are returned by models and controllers. Use column-level selection and avoid returning entire model instances when only a subset of data is required.
First, limit fields at the model query level:
// app/Controllers/Http/UserController.ts
import User from 'App/Models/User'
export async function show({ params }: HttpContextContract) {
const user = await User.query()
.select('id', 'username', 'email', 'created_at')
.where('id', params.id)
.firstOrFail()
return user
}
This ensures only intended columns from the Cockroachdb table are fetched, avoiding accidental exposure of sensitive fields such as password_hash or two_factor_secret.
Second, use explicit serialization via Adonisjs schemas or resource classes to shape the response:
// app/Resources/UserResource.ts
import { Resource } from '@ioc:Adonisjs/AdonisjsResource'
export default class UserResource extends Resource {
public toArray() {
return {
id: this.resource.id,
username: this.resource.username,
email: this.resource.email,
createdAt: this.resource.created_at,
}
}
}
// app/Controllers/Http/UserController.ts
import User from 'App/Models/User'
import UserResource from 'App/Resources/UserResource'
export async function show({ params }: HttpContextContract) {
const user = await User.findOrFail(params.id)
return new UserResource(user)
}
This pattern is especially important with Cockroachdb when schemas evolve and new columns are added; serialization acts as a safeguard against unintended exposure.
Third, when using relationships, explicitly limit related data:
// app/Models/User.ts
import { DateTime } from 'luxon'
import { hasMany } from '@ioc:Adonisjs/Lucid/Relations'
import Comment from 'App/Models/Comment'
export default class User extends Model {
public comments = hasMany(() => Comment, {
// Explicitly limit fields on related models
fields: ['id', 'content', 'created_at']
})
}
// app/Controllers/Http/UserController.ts
export async function showWithComments({ params }: HttpContextContract) {
const user = await User.findOrFail(params.id)
const userWithComments = await User.query()
.preload('comments')
.select('id', 'username')
.where('id', params.id)
.firstOrFail()
return userWithComments
}
For Cockroachdb, ensure that any raw SQL or complex joins also explicitly list columns to avoid pulling in internal metadata:
import { Database } from '@ioc:Adonisjs/Lucid/Database'
export async function getSafeUserReport(database: Database) {
const result = await database
.from('users')
.select('id', 'username', 'email')
.leftJoin('profiles', 'users.id', 'profiles.user_id')
.select('profiles.display_name')
.whereNotNull('email')
return result
}
These practices reduce the attack surface by ensuring Cockroachdb only returns what the API consumer needs, aligning with the principle of least privilege in data exposure.
Related CWEs: propertyAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-915 | Mass Assignment | HIGH |