Command Injection in Adonisjs with Basic Auth
Command Injection in Adonisjs with Basic Auth — how this specific combination creates or exposes the vulnerability
Command Injection occurs when an attacker can inject and execute arbitrary system commands through an application. In AdonisJS, this risk can be amplified when Basic Authentication is used for route protection without rigorous input validation and safe command construction. AdonisJS applications commonly interact with the operating system via child process utilities such as exec, spawn, or child_process. If user-controlled data—such as credentials, query parameters, or request headers—are concatenated into these commands without sanitization or parameterization, an attacker can terminate the intended command syntax and append malicious instructions.
When Basic Auth is implemented naively, the username or password fields may be passed directly into backend logic. For example, an endpoint that authenticates a user and then uses the provided username to build a system command creates a clear attack surface. An attacker could supply a payload like admin; cat /etc/passwd as the username. If the application does not validate or escape this input, the semicolon enables command chaining, allowing arbitrary commands to run with the privileges of the AdonisJS process. This combination of authenticated access and unsafe command usage violates the principle of least privilege and can lead to unauthorized file access, data exfiltration, or further system compromise.
In the context of middleBrick’s security checks, this scenario is flagged under the Input Validation and Unsafe Consumption categories. The scanner tests whether authenticated endpoints safely handle special characters and shell metacharacters. It also examines whether authentication mechanisms expose sensitive system information in error messages, which could aid an attacker in crafting injection strings. Because the risk stems from how user data is handled after authentication, the vulnerability persists even when access is technically restricted to authenticated users.
Basic Auth-Specific Remediation in Adonisjs — concrete code fixes
Securing AdonisJS endpoints that use Basic Authentication requires strict input validation, avoiding shell command construction with user data, and using safe APIs that do not invoke a shell. Below are concrete remediation steps and code examples.
1. Avoid Shell Commands Entirely
Prefer AdonisJS-native operations and Node.js libraries that do not spawn a shell. For file system tasks, use fs/promises or AdonisJS providers. For system interactions that cannot be avoided, use child_process methods that bypass the shell, such as spawn with an argument array.
import { execFile } from 'child_process'
// Safe: arguments are passed as an array, no shell injection
execFile('git', ['log', '--oneline', '-5'], (error, stdout, stderr) => {
if (error) {
console.error(`execFile error: ${error}`)
return
}
console.log(stdout)
})
2. Validate and Sanitize All User Input
If you must process input that could reach system commands, enforce strict allowlists and reject unexpected characters. For usernames, restrict to alphanumeric characters and a limited set of safe symbols.
import { schema } from '@ioc:Adonis/Core/Validator'
const usernameSchema = schema.create({
username: schema.string({}, [
// Only allow alphanumeric and underscores
rules.regex('^[a-zA-Z0-9_]+$'),
]),
})
export default class AuthController {
public async login({ request, auth }) {
const payload = await request.validate({ schema: usernameSchema })
const user = await auth.attempt(payload.username, request.input('password'))
return user
}
}
3. Use Environment Variables for Sensitive Configuration
Do not construct commands that include secrets or usernames from request data. Use environment variables and AdonisJS’s config system for credentials, and reference them safely in process-level configuration rather than runtime user input.
// .env
DB_USER=app_user
// config/database.ts
export default {
connection: 'pg',
pg: {
clientUrl: Env.get('DB_URL'),
user: Env.get('DB_USER'),
},
}
4. Implement Proper Error Handling
Ensure that error messages do not leak stack traces or system details that could aid injection attempts. Use generic responses for authentication failures and log detailed errors internally only.
try {
await auth.attempt(username, password)
} catch (error) {
// Do not expose internal details
throw new Exception('Invalid credentials', 401, 'E_INVALID_CREDENTIALS')
}
By combining these practices—avoiding shell command construction, rigorously validating input, and using AdonisJS’s built-in authentication and configuration patterns—you significantly reduce the risk of Command Injection in authenticated 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 |