Path Traversal in Adonisjs with Jwt Tokens
Path Traversal in Adonisjs with Jwt Tokens — how this specific combination creates or exposes the vulnerability
Path Traversal occurs when an attacker manipulates file paths to access files outside the intended directory, typically using sequences like ../. In AdonisJS, this risk can intersect with JWT token handling in scenarios where tokens influence file operations or route resolution. For example, an endpoint that decodes a JWT to derive a user role or tenant identifier might use that value to build filesystem paths without adequate sanitization.
Consider an AdonisJS route that reads user-specific configuration from disk after validating a JWT claim:
import { join } from 'path'
import Drive from '@ioc:Drive'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class FilesController {
public async readConfig({ request, auth }: HttpContextContract) {
const tokenPayload = auth.user?.tokenMeta // hypothetical custom claim storage
const tenantId = tokenPayload?.tenant
// Vulnerable: tenantId used directly in path construction
const filePath = join('/config/tenants/', tenantId, 'settings.yaml')
const contents = await Drive.get(filePath)
return { contents }
}
}
If tenantId originates from a JWT claim and is not strictly validated, an attacker who crafts a token with tenantId: "../../../etc/passwd" could traverse directories. Because AdonisJS does not inherently sanitize values used with @ioc:Drive, the resulting path can escape the intended base directory.
Another common pattern involves using JWTs to gate access to exported reports or logs. An endpoint might decode a token to identify a user, then build a filename from claims such as username or reportId. If these values are concatenated into a path like uploads/${username}/${reportId}.csv without normalization, an attacker-supplied username containing ../ can read arbitrary files. This is a BOLA/IDOR-like issue compounded by path manipulation, detectable by the BOLA/IDOR and Input Validation checks in middleBrick’s scan.
JWT-specific context matters here: tokens are often trusted implicitly after signature verification, but claims themselves are not inherently safe for filesystem operations. A token issued by an upstream service may include a sub or custom fields that reflect organizational units. If the application uses these to construct paths, the trust boundary extends beyond authentication to include path safety. middleBrick’s JWT security checks do not test filesystem logic, but they can highlight unauthenticated endpoints or weak claim validation that indirectly enable path traversal when combined with dynamic path assembly.
In summary, the combination of AdonisJS file utilities and JWT-derived path components creates risk when input validation and path normalization are omitted. The vulnerability is not in JWT verification itself, but in how decoded claims are used to build filesystem paths without canonicalization or allowlist checks.
Jwt Tokens-Specific Remediation in Adonisjs — concrete code fixes
Remediation focuses on strict validation, canonicalization, and avoiding direct use of JWT claims in filesystem paths. When JWT-derived values must influence file access, enforce allowlists, scope by tenant isolation, and use platform utilities to prevent directory escapes.
1) Validate and normalize paths
Use Node’s path.normalize and resolve against a base directory. Reject paths that resolve outside the base.
import { resolve, relative, sep } from 'path'
function safePath(base: string, tenant: string, fileName: string): string {
const normalized = normalize(`${tenant}/${fileName}`).replace(/^(\/|\.\.|[a-z]+:\/)/i, '')
const full = resolve(base, normalized)
if (!full.startsWith(resolve(base) + sep)) {
throw new Error('Path traversal attempt')
}
return full
}
// Usage in AdonisJS
const baseDir = '/config/tenants'
const safe = safePath(baseDir, tenantId, 'settings.yaml')
const contents = await Drive.get(safe)
2) Use allowlist validation for tenant identifiers
Restrict tenant IDs to alphanumeric patterns and avoid using raw directory names.
const tenantPattern = /^[a-z0-9_-]{1,32}$/
if (!tenantPattern.test(tenantId)) {
throw new Error('Invalid tenant identifier')
}
const filePath = join('/config/tenants/', tenantId, 'settings.yaml') // now safe
3) Scope files by tenant directory via middleware
In AdonisJS, bind a path prefix in middleware so handlers never construct paths from claims directly.
// start/hooks.ts
import { Application } from '@ioc:Adonis/Core/Application'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
Application.hooks.register(() => {
return {
async beforeEach({ auth, request }: HttpContextContract) {
const tokenPayload = auth.user?.tokenMeta
const tenantId = tokenPayload?.tenant
if (!tenantId || !/^[a-z0-9_-]+$/.test(tenantId)) {
throw new Error('Invalid tenant')
}
// Attach a tenant-scoped drive or base path to request context
request.ctx.tenantBase = `/config/tenants/${tenantId}`
}
}
})
// In controller
export default class ReportsController {
public async show({ request }: HttpContextContract) {
const base = request.ctx.tenantBase
const filename = 'summary.csv' // controlled by server, not user claim
const filePath = join(base, filename)
const contents = await Drive.get(filePath)
return { contents }
}
}
4) Avoid dynamic paths for JWT-sensitive operations
Prefer database-backed mappings for tenant-to-path relationships rather than deriving paths from JWT claims. If you must use claims, treat them as identifiers only, not as part of filesystem routes.
// Lookup mapping from a secure configuration or DB
const tenantMap = {
acme: 'acme_corp',
globex: 'globex_labs'
}
const tenantHandle = tenantMap[tenantId]
if (!tenantHandle) throw new Error('Unknown tenant')
const filePath = join('/config/tenants', tenantHandle, 'settings.yaml')
These patterns align with secure development practices and help satisfy Input Validation and BOLA/IDOR checks in middleBrick. The scanner can verify that endpoints using JWT claims do not exhibit obvious path traversal indicators, such as unsanitized concatenation with user-controlled values.
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 |