Command Injection in Feathersjs with Dynamodb
Command Injection in Feathersjs with Dynamodb — how this specific combination creates or exposes the vulnerability
Command Injection occurs when an attacker can control part of a system command executed by the application. In a Feathersjs service that uses Dynamodb, this typically arises when data from client requests is passed to shell commands or to lower-level SDK calls that may invoke the operating system. Feathersjs is a flexible framework that allows hooks and services to run custom logic; if that logic builds shell commands using user input (e.g., for tagging, invoking CLI tools, or constructing query strings) and passes them to functions like child_process or to lower-level executables, injection becomes possible.
With Dynamodb, the Java-based DynamoDB CLI (via AWS SDK calls) is not usually invoked directly, but developers sometimes execute shell commands to transform data, manage backups, or call external tools. If user-controlled parameters such as id, name, or filter are concatenated into these shell commands without validation or escaping, an attacker can inject additional shell instructions. For example, a malformed name field containing ; or && can cause the shell to execute arbitrary commands, leading to unauthorized file access or data manipulation. Even when using the AWS SDK for JavaScript to interact with Dynamodb, improper handling of inputs in wrapper scripts that build shell commands (e.g., using aws dynamodb put-item via exec) exposes the attack surface.
In a Feathersjs hook, consider a scenario where a before hook builds a shell command to enrich an item with external metadata using user-supplied fields:
app.service('items').hooks({
before: {
create: [async context => {
const { name, partitionKey } = context.data;
// Dangerous: directly embedding user input into a shell command
const { execSync } = require('child_process');
try {
const metadata = execSync(`aws dynamodb get-item --table-name Items --key '{"id":{"S":"${name}"}}'`).toString();
context.data.externalMeta = metadata;
} catch (error) {
// handle error
}
}]
}
});
Here, name originates from the request. An attacker could set name to test"; rm -rf / #, causing the shell to execute destructive commands. Even if the AWS CLI is not used, passing unchecked input to Dynamodb operations that internally invoke system utilities can propagate the risk. The combination of Feathersjs’s hook architecture and Dynamodb’s integration with external tooling amplifies the impact if input validation is omitted.
Another vector involves environment variables or configuration that reference shell commands built from user data. For instance, if a service constructs a Dynamodb query string using unsanitized input and passes it to a shell-based parser, special characters can alter command boundaries. Because Feathersjs encourages modular services and hooks, developers might inadvertently trust data flowing between services without re-validation. The risk is not in Dynamodb itself, but in how Feathersjs services orchestrate interactions and manage data flows that include shell commands.
Dynamodb-Specific Remediation in Feathersjs — concrete code fixes
Remediation centers on preventing user input from reaching the shell and ensuring that all Dynamodb interactions use the SDK’s structured API rather than string-based commands. In Feathersjs, apply validation and sanitization in hooks, and prefer the AWS SDK’s document client to avoid manual string assembly.
1. Avoid shell command construction; use the AWS SDK directly
Replace any shell-based Dynamodb calls with the official AWS SDK for JavaScript. This eliminates shell injection entirely and leverages built-in parameter handling.
const { DynamoDBDocumentClient, GetCommand } = require('@aws-sdk/lib-dynamodb');
const { DynamoDB } = require('@aws-sdk/client-dynamodb');
const client = DynamoDBDocumentClient.from(new DynamoDB({}));
app.service('items').hooks({
before: {
create: [async context => {
const { id } = context.data; // id should be validated as a string pattern
const command = new GetCommand({
TableName: 'Items',
Key: { id: { S: id } }
});
const response = await client.send(command);
context.data.externalMeta = response.Item;
}]
}
});
This approach uses structured objects for keys and attribute values, ensuring that special characters are treated as data, not command syntax.
2. Validate and sanitize all inputs
Use a validation library (e.g., Ajv) to enforce strict patterns for identifiers. For example, ensure that primary keys contain only alphanumeric characters and underscores, rejecting potentially dangerous characters used in shell metacharacters.
const validate = require('validate.js');
const customValidators = {
alphanumericUnderscore: function(value, attributes, attributeName, options) {
if (!/^[a-zA-Z0-9_]+$/.test(value)) {
return 'Only alphanumeric and underscore are allowed';
}
}
};
app.hooks({
before: {
create: [async context => {
const constraints = { id: { alphanumericUnderscore: true } };
const validationResult = validate(context.data, constraints);
if (validationResult) {
throw new Error('Invalid input: ' + JSON.stringify(validationResult));
}
}]
}
});
3. Use environment variables for configuration, not runtime input
If your service relies on external tooling, store command templates or bucket names in environment variables and interpolate only trusted, pre-sanitized values at runtime. Never interpolate request data directly into command strings.
// Safe: using environment variable for table name, not user input
const tableName = process.env.DYNAMODB_TABLE; // set via deployment config
const params = {
TableName: tableName,
Key: { id: { S: validatedId } }
};
const command = new GetCommand(params);
By combining SDK-native operations with strict input validation, Feathersjs services can interact with Dynamodb securely while avoiding command injection risks.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |