Command Injection in Strapi with Bearer Tokens
Command Injection in Strapi with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Command Injection occurs when untrusted input is concatenated into a system command executed by the backend. In Strapi, this risk can manifest in custom controllers or services that invoke shell commands (e.g., via child_process functions) and incorporate data from authenticated requests that carry Bearer Tokens in the Authorization header. The Bearer Token itself is not malicious, but if the token’s associated user-supplied values (such as dynamic parameters, query strings, or request headers) are used to build shell commands without proper validation or escaping, the API endpoint becomes vulnerable.
Consider a Strapi custom endpoint that accepts a filename query parameter and uses the Bearer Token’s associated user identifier to construct a shell command for file operations. If the endpoint directly interpolates these values into a command like cat /data/${userId}/${fileName} using Node.js child_process methods, an attacker who knows or guesses a valid Bearer Token can inject shell metacharacters (e.g., ;, &, |) to execute arbitrary commands on the host. Strapi’s default behavior does not automatically sanitize inputs from request parameters, and developers might mistakenly trust the Authorization header as a safe source of identity while still passing other request-derived data into shell commands.
An attacker with a valid Bearer Token (e.g., obtained via credential compromise or a token leakage bug) can probe the API by sending crafted requests such as fileName=../../../etc/passwd;id. If the endpoint concatenates this input into a shell command, the injected segment can read sensitive files or change runtime behavior. Because Strapi often exposes administrative or data-facing endpoints, such vulnerabilities can lead to unauthorized data access or further compromise. The combination of Bearer Token authentication and unchecked external input creates a scenario where trusted identity context is leveraged to bypass casual assumptions about input safety.
During a middleBrick scan, this issue may surface under the Authentication, Input Validation, and Unsafe Consumption checks. The scanner submits requests with valid Bearer Tokens and probes endpoints that accept and reflect or execute dynamic input. Findings include details about which endpoints concatenate user-controlled data into shell-like contexts and highlight the absence of input sanitization or command parameterization.
Remediation guidance focuses on avoiding shell command construction with external data. When system-level operations are necessary, use language-level APIs that do not invoke a shell, and strictly validate and sanitize all inputs. MiddleBrick’s dashboard and CLI provide prioritized findings with step-by-step remediation guidance, helping teams address Command Injection risks in Strapi integrations that rely on Bearer Tokens.
Bearer Tokens-Specific Remediation in Strapi — concrete code fixes
Secure Strapi implementations avoid building shell commands from any request-derived data, including values tied to Bearer Tokens. Instead, use Strapi’s built-in services and file handling abstractions, or if shell interaction is unavoidable, enforce strict allowlists and use parameterized process invocation.
Example of vulnerable code in a Strapi custom controller (JavaScript):
const { exec } = require('child_process');
module.exports = {
customAction: async (ctx) => {
const tokenUser = ctx.state.user; // Assume Bearer Token validated by Strapi
const { fileName } = ctx.query;
// Vulnerable: directly interpolating user input into a shell command
const command = `cat /data/${tokenUser.id}/${fileName}`;
exec(command, (error, stdout, stderr) => {
if (error) return ctx.badRequest('Operation failed');
ctx.body = stdout;
});
},
};
The above exposes Command Injection because fileName is controlled by the request and concatenated into the command string. An attacker who supplies a malicious fileName can execute arbitrary shell commands.
Remediation using a parameterized approach without shell injection risk:
const fs = require('fs').promises;
module.exports = {
secureAction: async (ctx) => {
const tokenUser = ctx.state.user;
const { fileName } = ctx.query;
// Validate fileName to allow only safe characters and known files
const safeName = fileName.replace(/[^a-zA-Z0-9._-]/g, '');
if (!safeName || safeName !== fileName) {
return ctx.badRequest('Invalid file name');
}
const baseDir = `/data/${tokenUser.id}`;
const filePath = `${baseDir}/${safeName}`;
// Use Node.js filesystem APIs instead of shell commands
try {
const data = await fs.readFile(filePath, 'utf8');
ctx.body = data;
} catch (err) {
return ctx.notFound('File not found');
}
},
};
If shell execution is strictly required (rare in Strapi), use spawn with an explicit argument array and avoid the shell entirely:
const { spawn } = require('child_process');
module.exports = {
safeSpawnAction: async (ctx) => {
const tokenUser = ctx.state.user;
const { fileName } = ctx.query;
const safeName = fileName.replace(/[^a-zA-Z0-9._-]/g, '');
if (!safeName || safeName !== fileName) {
return ctx.badRequest('Invalid file name');
}
// Do NOT pass shell: true and avoid concatenated command strings
const child = spawn('cat', [`/data/${tokenUser.id}/${safeName}`]);
let stdout = '';
child.stdout.on('data', (chunk) => { stdout += chunk; });
child.on('close', (code) => {
if (code !== 0) return ctx.badRequest('Process failed');
ctx.body = stdout;
});
child.on('error', () => ctx.badRequest('Execution error'));
},
};
In all cases, treat the Bearer Token as an identity context, not as a source of trust for input safety. Validate and sanitize all external inputs, prefer platform APIs over shell invocation, and use middleBrick’s scans to detect remaining risks in your Strapi endpoints.
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 |