Crlf Injection in Feathersjs with Dynamodb
Crlf Injection in Feathersjs with Dynamodb — how this specific combination creates or exposes the vulnerability
Crlf Injection occurs when user-controlled data is reflected into HTTP headers without sanitization, enabling header injection via carriage return (\r) and line feed (\n) sequences. In a Feathersjs service that uses Dynamodb as a backend, this typically arises when query parameters, headers, or request body values are passed into DynamoDB operations and then echoed back in HTTP responses or logs. Feathersjs does not inherently sanitize inputs, and if a service directly uses user input to construct response headers, set custom metadata, or log item attributes retrieved from a DynamoDB table, an attacker can inject malicious headers such as X-Injected: injected or split responses to perform HTTP response splitting.
With DynamoDB, the risk surface often involves attributes stored and later rendered in application logic. For example, a user profile service might store a bio field in a DynamoDB table and later include it in a JSON response. If the service uses that field in an HTTP header (e.g., x-user-bio: {bio}) without validation, a newline in the bio enables header injection. Similarly, a search or filter parameter that maps to a DynamoDB query key may be reflected in a header or log entry, and newline characters in that input can break header structure. Because DynamoDB stores data as strings, numbers, binary, or nested documents, unchecked string attributes retrieved from DynamoDB can contain newline sequences that, when placed into headers by Feathersjs middleware or hooks, result in Crlf Injection. This combination is particularly dangerous when the Feathersjs app also uses features like authentication hooks that forward user-supplied metadata to downstream services, inadvertently propagating injected headers.
Another vector involves logging and debugging outputs. If a Feathersjs service logs DynamoDB responses that include user-controlled fields, newline characters can corrupt log boundaries and, in some log aggregation setups, facilitate log injection that may be used for log forging or log injection attacks. While this does not directly alter HTTP streams, it can assist in obfuscating follow-on attacks. In environments where DynamoDB Streams trigger Feathersjs services, injected newlines in attribute values could affect downstream processing if those values are later used in header construction or output without sanitization. Proper input validation and output encoding at the service layer are essential to prevent Crlf Injection when integrating Feathersjs with DynamoDB.
Dynamodb-Specific Remediation in Feathersjs — concrete code fixes
Remediation centers on validating and sanitizing data before it reaches HTTP headers and before it is stored or retrieved from DynamoDB. In Feathersjs, leverage hooks to normalize inputs and outputs, and ensure that any attribute derived from user input is stripped of carriage return and line feed characters before being used in headers or logs. Below are concrete code examples for a Feathersjs service using the official AWS SDK for DynamoDB.
Example 1: Input validation hook to strip newlines
This hook runs before a create operation and removes carriage return and line feed characters from specified fields, preventing them from being stored in DynamoDB and later reflected into headers.
const { Service } = require('feathersjs');
function sanitizeCrlf() {
return context => {
const fields = ['username', 'bio', 'email'];
if (context.data && typeof context.data === 'object') {
fields.forEach(field => {
if (context.data[field] && typeof context.data[field] === 'string') {
context.data[field] = context.data[field].replace(/[\r\n]+/g, ' ');
}
});
}
return context;
};
}
const app = require('feathers')();
app.use('/profiles', new Service({
name: 'profiles',
async create(data, params) {
// Assume this uses the AWS SDK to put an item into DynamoDB
const { DynamoDBClient, PutItemCommand } = require('@aws-sdk/client-dynamodb');
const client = new DynamoDBClient({});
const paramsDb = {
TableName: 'profiles',
Item: {
userId: { S: data.userId },
bio: { S: data.bio || '' }
}
};
await client.send(new PutItemCommand(paramsDb));
return data;
}
}));
app.service('profiles').hooks({
before: {
create: [sanitizeCrlf()]
}
});
Example 2: Output encoding hook before header assignment
If you must use DynamoDB item attributes in HTTP headers, encode newlines to prevent injection. This example shows a hook that safely sets a custom header using an attribute retrieved from DynamoDB.
const escapeHeaderValue = (value) => {
if (typeof value !== 'string') return value;
return value.replace(/[\r\n]+/g, '');
};
app.use('/users', new Service({
name: 'users',
async get(id, params) {
const { DynamoDBClient, GetItemCommand } = require('@aws-sdk/client-dynamodb');
const client = new DynamoDBClient({});
const cmd = new GetItemCommand({ TableName: 'users', Key: { userId: { S: id } } });
const resp = await client.send(cmd);
const item = resp.Item;
const user = {
userId: item.userId.S,
displayName: item.displayName?.S || ''
};
// Simulate setting a header in a Feathersjs context (e.g., in a before hook)
params.headers = params.headers || {};
params.headers['x-display-name'] = escapeHeaderValue(user.displayName);
return user;
}
}));
Example 3: Validate input against newline characters in service parameters
Explicitly reject or sanitize newlines in query parameters used for DynamoDB queries to prevent stored data from being weaponized later.
function validateNoCrlf(obj) {
for (const key of Object.keys(obj)) {
if (typeof obj[key] === 'string' && /[\r\n]/.test(obj[key])) {
throw new Error('Invalid input: newline characters not allowed');
}
}
return obj;
}
app.service('search').hooks({
before: {
find: [context => {
if (context.params.query) {
validateNoCrlf(context.params.query);
}
return context;
}]
}
});
General best practices
- Treat all DynamoDB string attributes as untrusted when used in HTTP headers.
- Apply consistent sanitization in before hooks for create, update, and patch operations.
- Log sanitized values or redact newlines to reduce log injection risks.
- Validate query parameters and path parameters before using them in DynamoDB key conditions.