Prototype Pollution in Adonisjs with Cockroachdb
Prototype Pollution in Adonisjs with Cockroachdb — how this specific combination creates or exposes the vulnerability
Prototype pollution in Adonisjs applications that use Cockroachdb arises when user-controlled input is merged into objects that later influence SQL construction or ORM behavior. Adonisjs relies on JavaScript object shapes to build query scopes, dynamic filters, and schema-based operations. If an attacker can modify the prototype of Object or a framework-specific base object, properties added to Object.prototype can appear unexpectedly in loops, equality checks, or serialization logic used while interacting with the Cockroachdb driver.
When Adonisjs services parse JSON payloads to build ORM models or raw query parameters for Cockroachdb, they often iterate over keys using for...in or Object.keys. Polluted prototypes can introduce enumerable properties that were not intended by the developer, leading to unintended SQL conditions or malformed DML statements. Because Cockroachdb supports advanced SQL features used by Adonisjs via its node driver, malicious enumerable keys can affect generated SQL in subtle ways, such as adding unexpected WHERE clauses or influencing column mappings.
The risk is compounded when the application deserializes JSON into class instances or merges configuration objects with runtime data. Prototype pollution can bypass intended validation boundaries, since checks that rely on hasOwnProperty may be incomplete, allowing attacker-controlled values to propagate into the ORM layer communicating with Cockroachdb. This can lead to unauthorized data access or inconsistent application state, even when the database enforces its own constraints.
Real-world attack patterns mirror CVE-type scenarios where input validation focuses on the final value but misses prototype-level contamination. For example, an API endpoint that merges request bodies into an Adonisjs Lucid model and then issues a mergeWhere or dynamic filter may inadvertently include polluted properties in the generated SQL, changing query semantics in Cockroachdb.
Because middleBrick scans test input validation and property authorization in parallel, it can surface these issues by detecting unexpected enumerable properties that influence API behavior. The scanner does not fix the code, but it provides remediation guidance to harden object handling and ORM usage when integrating with Cockroachdb.
Cockroachdb-Specific Remediation in Adonisjs — concrete code fixes
Remediation focuses on preventing prototype pollution before data reaches Adonisjs ORM logic and ensuring Cockroachdb interactions are resilient to tainted input.
- Use strict object creation: Prefer
Object.create(null)for dictionaries that should never inherit fromObject.prototype. When merging request payloads into filters for Cockroachdb queries, avoid plain{}if you plan to iterate withfor...inwithouthasOwnPropertychecks. - Validate and sanitize input: Explicitly whitelist allowed keys for query parameters and model attributes. Reject or strip keys that begin with
__or match known pollution targets such asconstructor,prototype, and__proto__. - Use framework helpers: Adonisjs provides
schema.validateand shape-based parsing. Define strict shapes for incoming data and avoid merging raw objects directly into Lucid models or query builders targeting Cockroachdb.
Concrete code examples
Safe filter construction for Cockroachdb queries
import { schema } from '@ioc:Adonis/Core/Validator'
import Database from '@ioc:Adonis/Lucid/Database'
const filterSchema = schema.create({
filters: schema.object.optional().reportUnknownKeys('ignore'),
limit: schema.number.optional([ () => true ]),
status: schema.string.optional()
})
export async function listUsers(ctx) {
const validated = await ctx.validate({
schema: filterSchema,
data: ctx.request.qs()
})
// Build a clean params object with Object.create(null) to avoid prototype pollution
const params = Object.create(null)
if (validated.filters?.status) {
params.status = validated.filters.status
}
if (validated.limit) {
params.limit = validated.limit
}
// Use parameterized query building with Cockroachdb via Lucid
const users = await Database.query()
.from('users')
.where((builder) => {
if (params.status) {
builder.andWhere('status', params.status)
}
})
.limit(params.limit || 50)
return users
}
Sanitizing merged configuration for ORM usage
import { merge } from 'lodash'
function safeMergeTarget(target, source) {
// Reject keys that could pollute prototypes
const blockedKeys = ['constructor', 'prototype', '__proto__']
const cleanSource = Object.keys(source).reduce((acc, key) => {
if (!blockedKeys.includes(key) && Object.prototype.hasOwnProperty.call(source, key)) {
acc[key] = source[key]
}
return acc
}, {})
return merge(target, cleanSource)
}
const baseConfig = Object.create(null)
baseConfig.table = 'transactions'
const incoming = {
constructor: { malicious: true },
limit: 100,
__proto__: { injected: true }
}
const config = safeMergeTarget(baseConfig, incoming)
// config contains only { table: 'transactions', limit: 100 }
// Use config safely with Cockroachdb client
Database.raw('SELECT * FROM ${table} LIMIT ${limit}', config)
.then((result) => {
// process rows from Cockroachdb
})
Rejecting prototype pollution at the validation layer
import { schema } from '@ioc:Adonis/Core/Validator'
const userSchema = schema.create({
data: schema.object({
name: schema.string(),
email: schema.string.optional(),
// Explicitly disallow unexpected keys
allowUnknownKeys: false
})
})
export async function createUser(ctx) {
const payload = await ctx.validate({ schema: userSchema })
// payload.data is guaranteed not to contain prototype pollution keys
await Database.table('users').insert({
name: payload.data.name,
email: payload.data.email
})
}
These practices reduce the attack surface when Adonisjs applications interact with Cockroachdb by ensuring that only intended, validated data shapes influence query building and ORM behavior.