HIGH command injectionexpressdynamodb

Command Injection in Express with Dynamodb

Command Injection in Express with Dynamodb — how this specific combination creates or exposes the vulnerability

Command Injection occurs when an attacker can cause an application to execute unintended system commands. In an Express service that uses the AWS SDK for JavaScript to interact with DynamoDB, this typically arises when input that reaches DynamoDB operations is passed to a shell or native function that executes commands. For example, using child_process functions such as exec or execFile to build system commands from user-controlled data creates an exploitable path, even if the ultimate target is a DynamoDB table. A common pattern is constructing a shell string to invoke the AWS CLI or other utilities based on request parameters, such as a table name or filter value, without proper validation or escaping. If the input is not strictly controlled, an attacker can inject additional shell commands and potentially read or modify files, execute binaries, or pivot to other services.

DynamoDB itself does not execute shell commands, but the surrounding Express code can introduce risk when integrating AWS SDK calls with system command execution. Consider an endpoint that accepts a partition key value and uses it to run a shell command for logging or custom processing. If the SDK call is combined with exec, and the parameter is concatenated into the command string, the boundary between data and command is blurred. Attack patterns such as CVE-related injection techniques can manifest when untrusted input reaches exec or similar APIs. Even when DynamoDB operations themselves are safe, the surrounding Express route can become a vector if it builds commands using unsanitized inputs like req.query.table or req.body.name. The risk is not in DynamoDB’s API but in how Express orchestrates the SDK and system utilities, especially when credentials are present in the environment and over-permissive IAM policies allow broader impact.

An example scenario: an Express route receives a key value intended for a DynamoDB query, and the developer adds logging by invoking the AWS CLI via child_process.exec. If the key value is used directly in the command string, an attacker can append shell metacharacters to run arbitrary commands. This exposes not only the DynamoDB data plane but also the host environment. The Express application’s trust boundary expands to include shell execution, and DynamoDB becomes one of the actions the injected command can perform. Secure design requires treating all external inputs as untrusted, avoiding shell command construction from request data, and using SDK methods directly without spawning processes. When DynamoDB operations and shell commands coexist in the same code path, rigorous input validation and strict separation of concerns are essential to prevent injection.

Dynamodb-Specific Remediation in Express — concrete code fixes

To eliminate Command Injection risks in an Express app using DynamoDB, avoid shell command construction entirely and interact with DynamoDB through the AWS SDK only. Use the AWS SDK for JavaScript’s DynamoDB DocumentClient for type-safe operations and parameterized queries. Never concatenate user input into shell commands, and if system utilities are required, use strict allowlists for values and avoid dynamic input in command arguments.

Insecure pattern to avoid:

const { exec } = require('child_process');
app.get('/log-table', (req, res) => {
  const { tableName } = req.query;
  // Risky: user-controlled input used in shell command
  exec(`aws dynamodb describe-table --table-name ${tableName}`, (error, stdout) => {
    if (error) return res.status(500).send('Error');
    res.send(stdout);
  });
});

Secure Express route using DynamoDB DocumentClient:

const { DynamoDBDocumentClient, DescribeTableCommand } = require('@aws-sdk/lib-dynamodb');
const { ddbClient } = require('./ddbClient'); // configured DynamoDB client
const ddbDocClient = DynamoDBDocumentClient.from(ddbClient);
app.get('/describe-table', async (req, res) => {
  const { tableName } = req.query;
  // Validate tableName against an allowlist to prevent abuse
  const allowedTables = ['users', 'orders', 'products'];
  if (!allowedTables.includes(tableName)) {
    return res.status(400).json({ error: 'Invalid table name' });
  }
  try {
    const command = new DescribeTableCommand({ TableName: tableName });
    const response = await ddbDocClient.send(command);
    res.json(response.Table);
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: 'DescribeTable failed' });
  }
});

If you must invoke external processes for integration purposes, use parameterized arguments and strict allowlists rather than string interpolation. For example, prefer spawn with fixed arguments and validate each input character against a whitelist. Additionally, enforce least-privilege IAM policies for the Express application so that even in the event of a misconfiguration, the impact is limited. Regularly review route definitions to ensure no child_process or exec calls remain that depend on dynamic user input.

ApproachRiskRemediation
Shell command with dynamic inputHigh — Command InjectionRemove shell usage; use AWS SDK directly
SDK with parameterized commandsLow — Proper validationUse DocumentClient and allowlists

Related CWEs: inputValidation

CWE IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

Can DynamoDB operations themselves be vulnerable to injection?
DynamoDB APIs are not vulnerable to command injection because they do not execute shell commands. However, if application code builds shell commands using DynamoDB data, the risk shifts to the surrounding Express process. Always validate and sanitize inputs before using them outside the SDK.
What is a secure way to log DynamoDB activity in Express without using shell commands?
Use the AWS SDK to fetch the data and structured logging libraries in Node.js, such as winston or pino, to emit JSON logs. Avoid spawning processes; instead, stream logs to a centralized system via HTTPS. This keeps the execution path within managed SDK calls and eliminates shell injection vectors.