Header Injection in Adonisjs with Cockroachdb
Header Injection in Adonisjs with Cockroachdb — how this specific combination creates or exposes the vulnerability
Header Injection in Adonisjs with Cockroachdb arises when user-controlled input is used to construct HTTP response headers or database operations without validation, enabling injection into the header stream or query execution flow. Adonisjs, a Node.js web framework, relies on strict separation between application logic and transport-layer concerns, but misuse of request-derived values in headers or in constructing Cockroachdb queries can lead to injection. Cockroachdb, while PostgreSQL-wire compatible, does not inherently introduce injection; however, when Adonisjs dynamically builds headers (e.g., Location, Set-Cookie, or custom headers) using request parameters and simultaneously uses those parameters in SQL statements targeting Cockroachdb, the combination expands the attack surface.
For example, if an endpoint reads a redirect_url query parameter and uses it in a res.header('Location', userValue) while also passing the same value into a Cockroachdb SELECT or COPY statement via an ORM query or raw client call, two distinct injection paths exist: HTTP response header injection and SQL injection. Header injection can manipulate client behavior, such as redirecting users to malicious sites or smuggling requests across proxies. SQL injection against Cockroachdb can bypass authentication, extract sensitive data, or modify records. The risk is amplified when Adonisjs routes do not sanitize or validate inputs before they touch either the response header logic or the database client used for Cockroachdb.
Middleware that sets headers based on request data must treat inputs as untrusted. Similarly, database access layers in Adonisjs that interact with Cockroachdb must avoid concatenating user input into SQL strings, even when using parameterized query builders. The framework’s IoC container and Lucid ORM provide safe patterns, but developers who bypass these patterns—such as using raw query strings with interpolated values—create conditions where both header and SQL injection become feasible. Proper validation, strict allowlists for header-affecting fields, and consistent use of parameterized queries eliminate the combined vulnerability in this stack.
Cockroachdb-Specific Remediation in Adonisjs — concrete code fixes
Remediation focuses on two controls: never use untrusted input in HTTP headers, and never inject untrusted input into SQL sent to Cockroachdb. Use Adonisjs built-in validation and ORM parameterization, and treat headers as strictly controlled.
- Validate and sanitize header inputs: Use Adonisjs schema validation to enforce strict allowlists for values that influence headers (e.g., redirect targets). Reject unexpected schemes and hosts.
- Use parameterized queries with Lucid ORM or Knex: Avoid string concatenation; bind values via placeholders so Cockroachdb receives parameters separately from SQL text.
- Escape and restrict custom headers: If custom headers are required, ensure they conform to RFC 7230 rules and do not contain injection-sensitive characters like newline or carriage return.
Safe Adonisjs + Cockroachdb examples
Safe route with validation and parameterized query:
const Route = use('Route');
const User = use('App/Models/User');
const { validate } = use('Validator');
Route.get('/users/:id', async ({ request, response }) => {
const schema = Joi.object({
id: Joi.number().integer().required(),
redirect: Joi.string().uri().required()
});
const { error, value } = validate(request.all(), schema);
if (error) {
return response.badRequest({ error: error.details[0].message });
}
// Parameterized query to Cockroachdb via Lucid ORM
const user = await User.query().where('id', value.id).first();
if (!user) {
return response.notFound();
}
// Safe header: use a fixed location or strictly validated URI
const safeRedirect = new URL(value.redirect).origin;
response.header('X-App-Origin', safeRedirect);
return response.json(user);
});
Raw Knex query with bound parameters to Cockroachdb:
const raw = use('knex');
async function getUserWithRole(userId, role) {
// Use named bindings; values are sent separately to Cockroachdb
const rows = await raw('SELECT * FROM users WHERE id = ? AND role = ?', [userId, role]);
return rows[0];
}
Setting headers safely without injection risk:
// Do NOT use request input directly in headers
// Instead, map to known values or use fixed origins
const ALLOWED_ORIGINS = new Set(['https://trusted.example.com', 'https://app.example.com']);
Route.post('/callback', async ({ request, response }) => {
const origin = request.input('origin');
if (!ALLOWED_ORIGINS.has(origin)) {
return response.badRequest({ error: 'Invalid origin' });
}
response.header('Access-Control-Allow-Origin', origin);
return response.json({ ok: true });
});
These patterns ensure that header values do not contain newlines or control characters and that Cockroachdb queries are parameterized, eliminating injection vectors specific to this stack.