Zip Slip in Adonisjs with Basic Auth
Zip Slip in Adonisjs with Basic Auth — how this specific combination creates or exposes the vulnerability
Zip Slip is a path traversal vulnerability that occurs when an application constructs file paths using user-supplied input without proper validation. In AdonisJS, this often surfaces in file upload, extraction, or static asset handling pipelines. When Basic Authentication is used, an authenticated context can encourage developers to relax input checks, mistakenly assuming that credentials alone mitigate path traversal risks. However, authentication does not neutralize malicious path sequences such as ../ or their encoded variants.
Consider an authenticated endpoint that extracts a ZIP archive uploaded by a user. If the server uses the original file names directly to build destination paths, an archive containing ../../etc/passwd can escape the intended directory. In AdonisJS, this may occur in a controller that uses a package like adonis-compress or native stream pipelines without sanitizing entry paths. Basic Auth ensures the request is authenticated, but it does not enforce that the extracted files remain within a designated directory. The combination therefore exposes a critical boundary violation: trusted credentials coexist with unchecked path resolution, allowing unauthorized file reads or overwrites outside the application’s sandbox.
During a middleBrick scan, the tool tests the unauthenticated attack surface and flags path traversal indicators even when Basic Auth headers are present. The scanner’s checks do not rely on internal implementation details; they observe runtime behavior. If an endpoint accepts an archive and returns files or directory listings outside the intended scope, a high-severity finding is generated. Real-world examples align with CVE patterns where archive extraction leads to unauthorized file access. MiddleBrick maps findings to frameworks such as OWASP API Top 10 and provides remediation guidance that focuses on input validation and strict path canonicalization rather than relying on transport-layer authentication.
Basic Auth-Specific Remediation in Adonisjs — concrete code fixes
To mitigate Zip Slip in AdonisJS while using Basic Auth, treat authentication as independent of path safety. Always validate and sanitize user inputs that influence file system operations, regardless of whether credentials are present. Below are concrete, working examples that demonstrate secure handling in an AdonisJS controller.
Secure ZIP extraction with path validation
Use canonicalization and a strict allowlist to ensure extracted paths remain within a designated directory. The following example uses Node.js built-in modules and AdonisJS controller structure to enforce safety.
import { join, resolve, normalize } from 'path'
import { existsSync, mkdirSync, writeFileSync } from 'fs'
import { createGunzip } from 'zlib'
import { createTarStream } from 'tar'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class ArchiveController {
public async extract(ctx: HttpContextContract) {
const { request, response } = ctx
const baseDir = resolve(__dirname, '..', '..', 'tmp', 'uploads')
if (!existsSync(baseDir)) {
mkdirSync(baseDir, { recursive: true })
}
const file = request.file('archive', {
types: ['zip'],
size: '2mb'
})
if (!file) {
return response.badRequest({ error: 'Missing archive file' })
}
const destination = join(baseDir, file.clientName)
const target = resolve(baseDir, normalize(file.tmpPath))
// Ensure the temporary file is within baseDir
if (!target.startsWith(baseDir)) {
return response.forbidden({ error: 'Invalid path detected' })
}
// Stream extraction with path validation
await new Promise((resolveExtract, rejectExtract) => {
file
.getStream()
.pipe(createGunzip())
.pipe(
createTarStream({
onentry: (entry) => {
const resolved = resolve(baseDir, normalize(entry.path))
if (!resolved.startsWith(baseDir)) {
entry.abort()
rejectExtract(new Error('Zip Slip detected'))
return
}
entry.path = resolved
}
})
)
.on('finish', resolveExtract)
.on('error, rejectExtract)
)
})
return response.ok({ message: 'Extraction completed safely' })
}
}
Basic Auth integration without relaxing path checks
AdonisJS provides built-in authentication guards. When using Basic Auth, ensure that the auth middleware runs before your handler but does not skip validation logic.
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import { schema } from '@ioc:Adonis/Core/Validator'
const authSchema = schema.create({
username: schema.string.optional(),
password: schema.string.optional()
})
export default class UserController {
public async me({ auth, request, response }: HttpContextContract) {
const payload = request.validate({ schema: authSchema })
const user = await auth.authenticate()
// Basic Auth verified, but path handling remains strict
return response.ok({ user: user.serialize() })
}
}
Key practices include: never concatenate user input directly into file paths, always use path.resolve and path.normalize, and enforce a strict base directory prefix check. MiddleBrick’s scans validate these behaviors in runtime, ensuring that authenticated endpoints still enforce strict input controls.