HIGH header injectionadonisjsdynamodb

Header Injection in Adonisjs with Dynamodb

Header Injection in Adonisjs with Dynamodb — how this specific combination creates or exposes the vulnerability

Header injection occurs when untrusted input is placed into HTTP headers without validation or sanitization. In an AdonisJS application that interacts with DynamoDB, this typically arises when request parameters (e.g., query strings, headers, or body fields) are used to construct responses or influence DynamoDB operations that later affect response headers. For example, if an endpoint accepts a next or redirect_url parameter and uses it to set a Location header without validation, an attacker can inject arbitrary headers, potentially enabling HTTP response splitting or open redirects.

DynamoDB itself does not interpret headers, but the application layer in AdonisJS is responsible for safely constructing responses. If input flows from a DynamoDB item into an HTTP header (e.g., using item attributes to set custom headers), unsanitized attributes can lead to injection. Consider a scenario where a user profile stored in DynamoDB contains a display name that is later used in a header such as x-user-display. Without proper sanitization, newline characters in the display name could enable header injection. AdonisJS routes and controllers should treat any data entering the response pipeline—including data retrieved from DynamoDB—as untrusted.

The risk is compounded when developers use DynamoDB data to influence redirects or construct links. For instance, retrieving an item with a user-supplied redirect target and then setting a Location header without validation can lead to open redirects. Because DynamoDB stores schemaless data, an attribute might contain unexpected values (including newline or carriage return sequences) that, when passed to AdonisJS header-setting functions, bypass assumptions about content safety. This is not a DynamoDB flaw but an application-layer issue where AdonisJS improperly trusts data sourced from DynamoDB when building headers.

Dynamodb-Specific Remediation in Adonisjs — concrete code fixes

To prevent header injection when using DynamoDB in AdonisJS, sanitize and validate any data that may influence HTTP headers. Treat all DynamoDB attribute values as untrusted when they are used in response construction. Below are concrete patterns and code examples to implement safe handling.

1. Validate and sanitize header inputs

Never directly use DynamoDB item attributes for header values without normalization. Strip or encode newline characters and enforce strict allowlists where possible.

const sanitizeHeaderValue = (value) => {
  if (typeof value !== 'string') return '';
  // Remove newline and carriage return characters to prevent header splitting
  return value.replace(/[\r\n]+/g, ' ').trim();
};

// In a controller, when setting a custom header from DynamoDB data
const userData = await dynamodb.get({ TableName: 'users', Key: { userId: '123' }});
const safeDisplayName = sanitizeHeaderValue(userData.Item?.displayName || '');
response.header('x-user-display', safeDisplayName);

2. Safe redirect handling with DynamoDB data

If using DynamoDB to store redirect targets, validate the URL strictly and avoid using raw user input or untrusted attributes for the Location header. Use a URL parsing library and ensure the redirect destination is within expected domains.

const validDomains = ['app.example.com', 'static.example.com'];
const isValidRedirect = (url) => {
  try {
    const parsed = new URL(url, 'http://localhost');
    return validDomains.includes(parsed.hostname);
  } catch {
    return false;
  }
};

// Example using DynamoDB item to decide redirect
const result = await dynamodb.get({ TableName: 'redirects', Key: { id: 'home' }});
const targetUrl = result.Item?.url;
if (targetUrl && isValidRedirect(targetUrl)) {
  return response.redirect(targetUrl);
}
return response.redirect('/fallback');

3. Use AdonisJS built-in header utilities safely

AdonisJS provides helpers to manage headers; avoid manually concatenating header values that may originate from DynamoDB. When setting multiple headers, ensure each is independently sanitized.

// Good: using response.header with sanitized values
const item = await dynamodb.query({ ... }).promise();
item.Items.forEach((entry) => {
  const safeValue = sanitizeHeaderValue(entry.meta || '');
  response.header(`x-entry-meta-${entry.id}`, safeValue);
});

// Avoid: directly injecting unsanitized DynamoDB attributes
// response.header('x-meta', item.Item.untrustedMeta); // unsafe

4. Input validation at the route level

Use AdonisJS validation schemas to reject or normalize inputs that could lead to header injection, especially when those inputs influence DynamoDB queries or response headers.

import { schema } from '@ioc:Adonis/Core/Validator';

const headerInputSchema = schema.create({
  redirect_url: schema.string.optional([
    schema.url({}, { tldStrict: false }),
    (_, value) => {
      try {
        const u = new URL(value);
        if (!['app.example.com', 'static.example.com'].includes(u.hostname)) {
          throw new Error('Invalid domain');
        }
      } catch {
        throw 'Invalid redirect URL';
      }
    },
  ]),
});

// In controller
const payload = await validator.validate({ schema: headerInputSchema });
// Safe to use payload.redirect_url after validation

Frequently Asked Questions

Can DynamoDB data directly cause header injection, or is this always an application-layer issue?
DynamoDB does not cause header injection; it stores raw data. Injection occurs at the application layer when AdonisJS places unsanitized DynamoDB attribute values into HTTP headers. Proper sanitization and validation in AdonisJS prevent injection regardless of DynamoDB content.
What specific newline characters should be removed to prevent header splitting in AdonisJS when using DynamoDB?
Remove carriage return (\r, ASCII 13) and line feed (\n, ASCII 10) characters, and any combination such as \r\n. Use a sanitize function that replaces [\r\n]+ with a space and trims the result before placing the value into headers.