Path Traversal in Adonisjs with Api Keys
Path Traversal in Adonisjs with Api Keys — how this specific combination creates or exposes the vulnerability
Path Traversal occurs when an API endpoint uses user-supplied input to construct filesystem paths without adequate validation or sanitization. In AdonisJS, this commonly arises in controllers that read or serve files based on request parameters. When API keys are used for authentication, developers might assume that because a request includes a valid key, the endpoint is safe. This assumption can lead to insecure direct object references (IDOR) or relaxed input checks, increasing the risk of path traversal.
Consider an AdonisJS controller that serves user-uploaded documents. A typical pattern might look like this:
import fs from 'fs';
import path from 'path';
export default class DocumentController {
async show({ request, response }) {
const { apikey } = request.get();
const { fileId } = request.params();
// Assume apikey is validated elsewhere
const userDocument = await this.getUserDocument(apikey, fileId);
const filePath = path.join('/var/uploads', userDocument.path);
return response.download(filePath);
}
}
If userDocument.path originates from user input or is weakly validated, an attacker who knows or guesses a valid API key could manipulate fileId to traverse directories. For example, supplying fileId=../../../etc/passwd could lead to unauthorized file access if the path is concatenated without normalization and strict allowlisting. The presence of API keys does not inherently prevent this; it may instead encourage developers to skip additional checks, mistakenly believing authentication is sufficient.
Moreover, if API keys are passed as query parameters or headers and logged insecurely, path traversal attempts might be captured in logs, exposing sensitive filesystem structure. AdonisJS applications that rely on dynamic path construction for file downloads or reads are particularly vulnerable when input validation is lax. This combination highlights the importance of validating and sanitizing all user-controlled data, even when authenticated via API keys.
Another scenario involves OpenAPI/Swagger integrations where spec definitions reference file system operations without adequate constraints. If runtime inputs are not cross-referenced against schema definitions, path traversal vectors may remain undetected during unauthenticated scans, as the API key might be accepted but not properly enforced in path resolution logic.
Api Keys-Specific Remediation in Adonisjs — concrete code fixes
To mitigate path traversal risks in AdonisJS when using API keys, enforce strict input validation, avoid direct filesystem path concatenation, and use allowlisting. Below are concrete remediation steps with code examples.
1. Validate and sanitize input
Always validate incoming parameters against a strict schema. For file identifiers, use a regex or a known allowlist rather than dynamic paths.
import { schema } from '@ioc:Adonis/Core/Validator';
const documentSchema = schema.create({
fileId: schema.string({}, [ rules.alpha() ]) // allow only alphanumeric identifiers
});
export default class DocumentController {
async show({ request, response }) {
const payload = await request.validate({ schema: documentSchema });
const safeFileId = payload.fileId;
const filePath = path.join('/var/uploads', safeFileId);
return response.download(filePath);
}
}
2. Use a mapping table instead of raw paths
Store file metadata in a database and reference by ID rather than constructing paths from user input. This prevents directory traversal entirely.
import Database from '@ioc:Adonis/Lucid/Database';
export default class DocumentController {
async show({ params, response }) {
const document = await Database.from('documents').where('id', params.id).firstOrFail();
const safePath = path.join('/var/uploads', document.secure_path);
return response.download(safePath);
}
}
3. Normalize and restrict paths
If you must resolve paths, normalize them and ensure they remain within a designated directory.
import { resolve } from 'path';
const baseDir = '/var/uploads';
const userPath = '/var/uploads/uploads/../../../etc/passwd';
const normalized = resolve(baseDir, userPath);
if (!normalized.startsWith(baseDir)) {
throw new Error('Invalid path');
}
// Proceed safely
4. Secure API key handling
Ensure API keys are transmitted over HTTPS, stored securely, and not logged. Use middleware to validate keys without relaxing path checks.
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
export default class ApiKeyMiddleware {
public async handle({ request, response, next }: HttpContextContract) {
const apikey = request.header('X-API-Key');
if (!this.isValidKey(apikey)) {
return response.unauthorized();
}
await next();
}
private isValidKey(key: string | null): boolean {
return !!key && key.length === 32; // simplistic example
}
}
By combining these practices, AdonisJS applications can reduce path traversal risks while still leveraging API keys for authentication.
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 |