Command Injection in Rails with Jwt Tokens
Command Injection in Rails with Jwt Tokens — how this specific combination creates or exposes the vulnerability
Command injection in Ruby on Rails occurs when untrusted input is concatenated into system commands executed via system, exec, or backticks. When JWT tokens are involved, risk arises at two points: (1) the token payload is untrusted input that may be passed into shell commands, and (2) token handling code may be improperly secured, enabling an attacker to influence command execution indirectly.
Consider a Rails service that decodes a JWT and uses a claim to build a shell command. If the developer does not validate or sanitize the claim, an attacker can supply a malicious token with a crafted payload that leads to command injection. For example, a token containing { "org": "acme; id" } could be interpolated into a system call:
payload = { "org" => "acme; id" }
org = payload["org"]
system("curl https://api.example.com/org/#{org}")
Here, the attacker-controlled claim org appends ; id to the URL argument, but because the value is used in a shell context, command injection becomes possible. Even if the JWT signature is verified, the decoded claims must be treated as untrusted input.
Another scenario involves background jobs or admin tooling that reads JWTs from logs, headers, or parameters and passes them to diagnostic commands. If the token is logged and later used in a shell script without escaping, an attacker who can influence the token (e.g., via account registration or a compromised client) may inject commands through log injection or indirect execution paths.
JWT-specific risk also emerges when token handling libraries or custom middleware expose debug endpoints that echo token contents to shell commands for troubleshooting. Such endpoints should never be exposed in production, as they provide a direct injection vector tied to the token’s contents.
Because middleBrick scans the unauthenticated attack surface, it can detect endpoints where JWT claims are reflected into command-like behavior without proper input validation, highlighting the absence of sandboxing or strict allowlists for external input.
Jwt Tokens-Specific Remediation in Rails — concrete code fixes
To remediate command injection when using JWT tokens in Rails, avoid shell interpolation entirely and use safe patterns. Never pass untrusted token claims directly to system, exec, or backticks. Instead, use language-native libraries or APIs that do not invoke a shell, and enforce strict allowlists for any values that must influence behavior.
1. Use Ruby native methods instead of shell commands
Replace shell-based operations with Ruby or language-safe libraries. For example, use an HTTP client rather than curl:
require 'net/http' require 'uri'payload = { "org" => "acme" } org = payload["org"] uri = URI("https://api.example.com/org/#{org}") response = Net::HTTP.get(uri)This approach removes the shell from the execution path, eliminating command injection risk regardless of token content.
2. If shell commands are unavoidable, use strict allowlists and escaping
When shell interaction is necessary, validate and restrict input to a known set of safe values, and escape all dynamic parts. For example:
allowed_orgs = %w[acme example trusted] org = payload["org"] if allowed_orgs.include?(org) system("curl", "https://api.example.com/org/#{org}") else raise "Invalid org" endUsing the multi-argument form of
systembypasses shell interpolation, but you must still validate each argument. Do not rely on escaping user input for shell commands; prefer native alternatives.3. Secure JWT verification and claim handling
Ensure JWT verification is performed with a trusted library and that claims are validated before use. Do not use token contents to construct command arguments without strict validation:
begin decoded = JWT.decode(token, Rails.application.secrets.secret_key_base, true, { algorithm: 'HS256' }) claims = decoded.first rescue JWT::DecodeError head :unauthorized return endAfter decoding, apply allowlists and schema checks to claims. Treat the token as an opaque credential for authentication, not as a source of shell parameters.
4. Audit logging without shell exposure
If logging or tooling requires inspecting token contents, ensure logs are written safely and never passed to shell commands. Use structured logging and avoid string interpolation into shell-like contexts.
middleBrick’s LLM/AI Security checks include system prompt leakage and active prompt injection testing, which can surface risky patterns where token-derived data might reach unintended execution paths. The scanner also checks for Input Validation and Unsafe Consumption issues, helping you identify places where JWT claims could be improperly handled.
By combining secure JWT handling with safe command execution patterns, you reduce the attack surface and prevent command injection even when tokens are involved.
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 |