Command Injection in Spring Boot with Bearer Tokens
Command Injection in Spring Boot with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Command Injection occurs when an attacker can influence a system command executed by the application, typically through insufficient input validation. In a Spring Boot application that uses Bearer Tokens for authentication, the token itself is usually passed in the Authorization header and is not directly used to construct system commands. However, the vulnerability arises when the application incorrectly incorporates authorization-derived data or other request metadata into runtime command execution, for example by passing the token value or its claims to a subprocess or by building shell commands from request inputs that are mistakenly treated as safe because the request is authenticated.
Consider a scenario where an authenticated API endpoint uses a Bearer Token to identify a user and then invokes a system utility that includes user-specific information in a command string. If the token or a claim extracted from it is concatenated into the command without proper sanitization or without using a safe invocation method, an attacker who can control the token (e.g., via registration or a forged token) may inject shell metacharacters to execute arbitrary commands. Even when Bearer Tokens are validated by Spring Security, the application must still treat all external inputs—including headers and claims—as untrusted. A common insecure pattern is using Runtime.getRuntime().exec() or ProcessBuilder with string concatenation that includes token-derived values, which enables shell injection despite the presence of a valid token.
Another relevant pattern is when an authenticated endpoint constructs dynamic commands for system or scripting operations, such as invoking binaries with user identifiers extracted from the token. For instance, if the token carries a username claim and that claim is used directly in a command like whois username without escaping, an attacker can append shell operators to the username to run additional commands. Because the request is authenticated, developers may mistakenly assume inputs are safe, which increases the risk of insecure code paths. This combination of authenticated context and unsafe command construction can lead to unauthorized command execution, privilege escalation, and data compromise.
Spring Boot applications should avoid building commands from any external data, including Bearer Token claims. When system interaction is necessary, prefer strict input validation, allowlists, and safe APIs such as ProcessBuilder with a list of arguments rather than a single command string. Do not pass tokens or derived values into shell commands, and enforce principle of least privilege for any process execution to limit the impact of potential misconfigurations.
Bearer Tokens-Specific Remediation in Spring Boot — concrete code fixes
Remediation focuses on ensuring Bearer Token data is never used to construct commands and that all external inputs are handled safely. Below are concrete, secure code examples for Spring Boot that demonstrate how to handle authenticated requests without introducing command injection risks.
Insecure example to avoid: Using token claims in command construction.
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/whois")
public String whois(Authentication authentication) {
String username = authentication.getName(); // or extract a claim
// Risky: building a shell command with user-derived input
try {
Process process = Runtime.getRuntime().exec(new String[]{"whois", username});
// process handling omitted
return "ok";
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
In this example, even though authentication is enforced via Bearer Tokens, the username from the authentication context is concatenated into a command argument unsafely. An attacker with a valid token could supply a username such as admin; rm -rf / if input validation is absent, leading to command injection.
Secure remediation using ProcessBuilder with a list and input validation:
@RestController
@RequestMapping("/api/users")
public class UserController {
private static final Pattern USERNAME_PATTERN = Pattern.compile("^[a-zA-Z0-9._-]{1,64}$");
@GetMapping("/whois")
public ResponseEntity whois(Authentication authentication) {
String username = authentication.getName();
if (!isValidUsername(username)) {
return ResponseEntity.badRequest().body("Invalid username");
}
// Safe: using ProcessBuilder with a list; no shell involvement
try {
ProcessBuilder pb = new ProcessBuilder("whois", username);
pb.redirectErrorStream(true);
Process process = pb.start();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
StringBuilder output = new StringBuilder();
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
}
return ResponseEntity.ok(output.toString());
}
} catch (IOException e) {
throw new RuntimeException("Execution failed", e);
}
}
private boolean isValidUsername(String input) {
return USERNAME_PATTERN.matcher(input).matches();
}
}
In the secure version, the username is validated against a strict allowlist pattern before use. ProcessBuilder is used with a list of arguments, avoiding shell interpretation entirely. No part of the Bearer Token or its claims is concatenated into a shell command, and the application does not rely on the presence of authentication to bypass input checks.
Additional recommendations:
- Never pass tokens or authorization headers into scripts or external commands.
- Use Java’s built-in mechanisms (e.g., libraries designed for safe process invocation) instead of shell features like pipes or redirects.
- Apply the principle of least privilege to the runtime environment and consider restricting which commands can be executed via an allowlist at the OS or container level.
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 |