Sandbox Escape in Adonisjs with Cockroachdb
Sandbox Escape in Adonisjs with Cockroachdb — how this specific combination creates or exposes the vulnerability
A sandbox escape in AdonisJS when interacting with CockroachDB typically occurs when application code that runs inside a restricted environment (for example, dynamic rule evaluation or user-defined templates) executes database queries that bypass intended access controls. Because CockroachDB is a SQL database, injection techniques that manipulate query structure can expose data or operations that should be isolated.
Consider an AdonisJS controller that builds SQL conditions dynamically using string concatenation instead of parameterized queries. If this controller is invoked from a sandboxed context (such as a scheduled job or a rules engine that evaluates user expressions), an attacker who can influence the input may introduce additional statements or UNION-based projections that reach beyond the intended row-level scope. CockroachDB’s wire protocol and SQL dialect behave similarly to PostgreSQL, so classic SQL injection patterns apply: crafted payloads can change the WHERE clause, append stacked queries, or exploit type coercion to force index scans on sensitive tables.
One realistic scenario: an endpoint like /api/tenant/:id/reports constructs a WHERE clause by concatenating tenant_id directly into the query string. If the :id parameter is not strictly validated, a payload such as 1; SELECT * FROM users can cause the database to return administrative data. Because CockroachDB supports multiple schemas and databases within a cluster, an injection can pivot across schemas if the connected role has broader permissions than intended. The sandbox fails when the query output includes columns that the calling context does not expect, enabling information disclosure or unauthorized data manipulation.
Another vector involves AdonisJS’ query builder being coerced into producing unsafe SQL through type confusion. For instance, numeric IDs expected as integers might be cast to strings by the ORM layer, allowing injection through unexpected type paths. When combined with CockroachDB’s strict typing but flexible JSONB extraction, attackers can force type casts that reveal nested fields or invoke functions that read from system tables. This is especially risky if the application uses the same database connection for both tenant-specific operations and shared metadata, as a single compromised query can enumerate schemas via SHOW SCHEMAS or infer role permissions.
LLM/AI Security checks are relevant here because generated code snippets that include raw query building can propagate these patterns across repositories. The scanner’s active prompt injection tests and system prompt leakage detection are designed to surface insecure examples that might otherwise be copied into AdonisJS services interacting with CockroachDB. Treat every dynamic SQL construct as an attack surface, regardless of the execution context.
Cockroachdb-Specific Remediation in Adonisjs — concrete code fixes
Remediation centers on strict input validation, parameterized queries, and principle-of-least-privilege database roles. Avoid string interpolation for SQL fragments; use the AdonisJS Lucid ORM’s bound parameters or explicit query parameterization. Validate tenant identifiers against a whitelist or enforce row-level security through query predicates rather than post-filtering.
Example of a vulnerable pattern and its fix:
// Vulnerable: string concatenation
const { request } = useRequest();
const tenantId = request.param('id');
const rows = await Database.from('reports')
.whereRaw(`tenant_id = ${tenantId}`)
.select('*');
// Secure: parameterized query with integer cast
const tenantId = Number(request.param('id'));
if (Number.isNaN(tenantId)) {
throw new Error('Invalid tenant identifier');
}
const rows = await Database.from('reports')
.where('tenant_id', tenantId)
.select('id', 'title', 'created_at');
For CockroachDB, prefer explicit parameter markers and avoid whereRaw unless absolutely necessary. If dynamic sorting or column selection is required, map user input to an allowlist:
const allowedColumns = ['id', 'title', 'created_at', 'updated_at'];
const column = allowedColumns.includes(request.qs().col) ? request.qs().col : 'id';
const rows = await Database.from('reports')
.where('tenant_id', tenantId)
.select(column);
When using JSONB columns in CockroachDB, validate the structure before extraction and avoid dynamic key concatenation:
const report = await Database.from('reports')
.where('tenant_id', tenantId)
.select('metadata::jsonb->>{"preferences"} as preferences')
.first();
// Prefer static paths and reject unexpected keys in application logic
Enforce connection-level restrictions in your AdonisJS configuration so the database user cannot access unrelated schemas or system tables. Combine this with runtime checks that verify the existence of tenant rows before executing scoped queries.
middleBrick’s scans can surface these classes of issue by correlating OpenAPI specifications with runtime behavior, and the Pro plan enables continuous monitoring so regressions in AdonisJS endpoints using CockroachDB are flagged as soon as they are introduced. The CLI provides JSON output for integration into CI/CD pipelines, while the GitHub Action can gate merges if risk scores exceed your chosen threshold.