Command Injection in Express with Bearer Tokens
Command Injection in Express with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Command Injection in an Express API that uses Bearer Tokens occurs when untrusted input is passed to a system shell or a command-spawning helper without validation or sanitization, and that input is influenced by an attacker who possesses a valid token. While Bearer Tokens themselves do not cause injection, they enable an authenticated context that can be abused to escalate impact: an attacker who steals or guesses a token may leverage it to reach endpoints that invoke operating system commands. For example, an endpoint that builds a shell command using user-controlled data—such as a filename, IP address, or query parameter—and passes it to child processes (e.g., exec, execSync, or spawn) can be tricked into executing arbitrary instructions.
In Express, this risk is often introduced via route parameters, query strings, or request headers that are concatenated into shell commands. Consider an endpoint that pings a provided hostname to check reachability:
const { exec } = require('child_process');
app.get('/ping', (req, res) => {
const host = req.query.host;
exec(`ping -c 4 ${host}`, (error, stdout, stderr) => {
if (error) { return res.status(500).send('Error'); }
res.send(stdout);
});
});
If the caller provides host=example.com; cat /etc/passwd, the command executed becomes ping -c 4 example.com; cat /etc/passwd, leaking sensitive files. Bearer Tokens come into play when the endpoint is protected by token-based authentication (e.g., via an Authorization header), ensuring the request is treated as authenticated, but not validating or sanitizing the command input. The token does not mitigate the injection; it simply confirms the caller is recognized, potentially increasing the trust placed in the request. MiddleBrick’s scans detect such patterns under Input Validation and Unsafe Consumption checks, highlighting cases where untrusted data reaches system-level execution.
Attackers may also exploit environment variables, temporary files, or locale settings to alter command behavior. A seemingly benign use of execFile can still be dangerous if arguments are not rigorously validated. Real-world exposures frequently map to OWASP API Top 10:2023 A03:2023 Injection and A01:2023 Broken Object Level Authorization, especially when endpoints with Bearer Token protection inadvertently expose high-privileged operations. MiddleBrick’s LLM/AI Security checks further probe whether outputs leak tokens or sensitive data, which can compound the risk if injected commands expose secrets.
To illustrate the token context, an authenticated curl call might look like:
curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4ifQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" "http://localhost:3000/ping?host=example.com"
MiddleBrick’s OpenAPI/Swagger analysis resolves $ref definitions and cross-references runtime behavior to highlight mismatches between declared authentication and unchecked input handling, ensuring that Bearer Token scopes are not inadvertently widening the attack surface.
Bearer Tokens-Specific Remediation in Express — concrete code fixes
Remediation focuses on preventing untrusted data from reaching shell commands and ensuring Bearer Token usage does not obscure validation gaps. The safest approach is to avoid shell execution entirely. Use parameterized APIs or language-native utilities instead of spawning commands. For example, prefer dns.lookup or dedicated ICMP libraries for network checks rather than invoking ping via a shell.
If shell execution is unavoidable, rigorously validate and sanitize inputs, use a strict allowlist, and avoid concatenation. With Bearer Tokens, continue to validate the token per your auth scheme, but do not assume it implies safe input. Below are concrete Express code examples demonstrating secure patterns.
Example 1: Safe network check without shell execution
const dns = require('dns').promises;
app.get('/ping', async (req, res) => {
const host = req.query.host;
if (typeof host !== 'string' || !host.match(/^[a-z0-9.-]+$/i)) {
return res.status(400).send('Invalid host');
}
try {
const result = await dns.lookup(host);
res.json({ host, address: result.address });
} catch (err) {
res.status(500).send('Resolution failed');
}
});
Example 2: If shell usage is required, use spawn with argument array and strict allowlisting
const { spawn } = require('child_process');
app.get('/ping', (req, res) => {
const host = req.query.host;
if (typeof host !== 'string' || !host.match(/^[a-zA-Z0-9.-]+$/)) {
return res.status(400).send('Invalid host');
}
const child = spawn('ping', ['-c', '4', host]);
let output = '';
child.stdout.on('data', (data) => { output += data; });
child.on('close', (code) => {
if (code !== 0) { return res.status(500).send('Ping failed'); }
res.send(output);
});
});
Example 3: Express middleware for Bearer Token validation (no injection fix, but proper auth handling)
function validateBearer(req, res, next) {
const auth = req.headers['authorization'];
if (!auth || !auth.startsWith('Bearer ')) {
return res.status(401).send('Unauthorized');
}
const token = auth.substring(7);
// Replace with real token verification (e.g., jwt.verify or introspection)
if (token !== 'SECRET_TOKEN_PLACEHOLDER') {
return res.status(403).send('Forbidden');
}
next();
}
app.use('/api/', validateBearer);
app.get('/data', (req, res) => {
res.json({ message: 'Authenticated and input-safe' });
});
Key practices for Express with Bearer Tokens:
- Never pass concatenated user input to exec, eval, or shell commands.
- Use allowlists for hostnames, filenames, and identifiers; reject anything that does not match expected patterns.
- Apply consistent authentication middleware to protect endpoints, but remember middleware alone does not stop injection.
- Log and monitor suspicious inputs; MiddleBrick’s dashboard can track findings and score trends over time.
These fixes reduce the attack surface while preserving the intended functionality. MiddleBrick’s CLI can be integrated into scripts to validate remediation, and the GitHub Action can enforce score thresholds in CI/CD to prevent regressions.
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 |