HIGH sandbox escapeadonisjsbasic auth

Sandbox Escape in Adonisjs with Basic Auth

Sandbox Escape in Adonisjs with Basic Auth — how this specific combination creates or exposes the vulnerability

A sandbox escape in AdonisJS when Basic Auth is involved typically arises from the interaction between the framework’s route handling, authentication guards, and process-level permissions. When Basic Auth is used, credentials are transmitted with every request and validated against a user provider (often a database model). If route or policy checks are bypassed, or if the authenticated context leaks into underlying system calls, an attacker may be able to move beyond the intended execution boundary.

Consider an endpoint that performs file operations based on user-supplied input. Even when protected by Basic Auth, if the application resolves paths by concatenating user input (e.g., a filename or directory parameter) without strict validation, an attacker can supply sequences like ../../../etc/passwd to traverse outside the intended directory. AdonisJS does not inherently sandbox filesystem access; it relies on application-level controls. Therefore, the framework’s authentication layer confirming identity does not automatically enforce content boundaries or safe path resolution.

Another scenario involves improper guard usage with policies. If a route uses basic auth to identify a user but does not enforce a corresponding policy check for authorization (BOLA/IDOR), an authenticated user might invoke actions scoped to another user’s resources. Because the route handler trusts the authenticated identity without verifying ownership or scope, the handler can be tricked into accessing or modifying data it should not, effectively breaking the logical sandbox that authentication alone provides.

SSRF-like patterns can also emerge if the handler makes outbound requests to user-supplied URLs. Even with valid Basic Auth credentials, an authenticated request that triggers an outbound call to an internal service (e.g., metadata service at http://169.254.169.254 or a local admin interface) can expose internal networks. The presence of Basic Auth does not mitigate SSRF; it only confirms who is making the request, not whether the request should be allowed to reach certain destinations.

LLM/AI Security checks highlight this risk when endpoints accepting user input interact with external systems or models. For example, if a Basic Auth–protected endpoint forwards user data to an LLM service without input validation, prompt injection or data exfiltration probes may succeed, revealing system prompts or sensitive outputs. middleBrick’s LLM/AI Security checks specifically test for system prompt leakage and unauthorized tool usage, which can be relevant when authenticated endpoints are used to drive generative AI workflows.

In summary, sandbox escape with Basic Auth in AdonisJS is not a flaw in the auth mechanism itself, but a consequence of insufficient input validation, missing authorization checks (BOLA/IDOR), and unsafe interactions with the host environment. Authentication confirms identity; it does not enforce data boundaries or safe system interactions. Proper scoping, canonical path resolution, and explicit policy enforcement are required to maintain the intended sandbox.

Basic Auth-Specific Remediation in Adonisjs — concrete code fixes

To remediate sandbox escape risks when using Basic Auth in AdonisJS, focus on strict input validation, explicit authorization, and safe handling of user-controlled data. The following examples demonstrate secure patterns.

1. Validate and sanitize all inputs

Never directly use request parameters in filesystem or network operations. Use validation schemas to enforce format and constraints.

import { schema } from '@ioc:Adonis/Core/Validator'

const fileSchema = schema.create({
  filename: schema.string({}, [rules.sanitizeChars(['../'], '')])
})

export default class FilesController {
  public async readFile({ request, response }: HttpContextContract) {
    const payload = request.validate({ schema: fileSchema })
    const safePath = join(__dirname, 'uploads', payload.filename)
    // Ensure resolved path is within allowed directory
    if (!safePath.startsWith(resolve(__dirname, 'uploads'))) {
      return response.badRequest({ error: 'Invalid path' })
    }
    // safely read file
  }
}

2. Enforce ownership and authorization explicitly

Use policies to verify that the authenticated user is allowed to access the target resource. Do not rely on route parameters alone to enforce boundaries.

import { schema } from '@ioc:Adonis/Core/Validator'

const idSchema = schema.create({
  id: schema.number()
})

export default class DocumentsController {
  public async show({ params, auth, response }: HttpContextContract) {
    const payload = params.validate({ schema: idSchema })
    const document = await Document.find(payload.id)
    if (!document) {
      return response.notFound()
    }
    // BOLA check: ensure document belongs to the authenticated user
    if (document.userId !== auth.user?.id) {
      return response.forbidden({ error: 'Access denied' })
    }
    return document
  }
}

3. Avoid user-controlled URLs for outbound requests

If your endpoint makes HTTP calls, reject or sanitize user-provided URLs to prevent SSRF. Use an allowlist or strict hostname checks.

import { schema } from '@ioc:Adonis/Core/Validator'
import got from 'got'

const urlSchema = schema.create({
  targetUrl: schema.string({}, [
    rules.url({ allowedProtocols: ['https'] }),
    rules.hostname(['api.example.com']) // strict allowlist
  ])
})

export default class ProxyController {
  public async fetch({ request, response }: HttpContextContract) {
    const payload = request.validate({ schema: urlSchema })
    try {
      const res = await got(payload.targetUrl, { headers: { Authorization: `Bearer ${process.env.API_TOKEN}` } })
      return response.ok(res.body)
    } catch (err) {
      return response.badRequest({ error: 'Request failed' })
    }
  }
}

4. Use middleware for authentication, not route-only guards

Ensure Basic Auth is enforced via middleware so that unauthorized requests never reach business logic. Combine with role-based checks where applicable.

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import { schema } from '@ioc:Adonis/Core/Validator'

export default class AuthMiddleware {
  public async handle(ctx: HttpContextContract, next: () => Promise) {
    const authSchema = schema.create({
      authorization: schema.string.optional({}, [rules.regex(new RegExp(/^Basic [A-Za-z0-9+/=]+$/))])
    })
    try {
      const payload = ctx.request.validate({ schema: authSchema })
      if (!payload.authorization) {
        return ctx.response.unauthorized({ error: 'Missing credentials' })
      }
      const [user] = atob(payload.authorization.split(' ')[1]).split(':')
      // validate user against provider; set ctx.auth.user
      await next()
    } catch {
      ctx.response.unauthorized({ error: 'Invalid credentials' })
    }
  }
}

5. Apply least privilege to filesystem and network access

Run the application process with minimal OS permissions and use path canonicalization to prevent directory traversal regardless of authentication.

import { resolve, join, normalize } from 'path'

export function safeJoin(base: string, userPath: string): string {
  const normalized = normalize(userPath).replace(/^(\/|\.\.)/, '')
  const target = resolve(base, normalized)
  if (!target.startsWith(resolve(base))) {
    throw new Error('Path traversal attempt')
  }
  return target
}

Frequently Asked Questions

Does Basic Auth alone prevent sandbox escape in AdonisJS?
No. Basic Auth confirms identity but does not enforce data boundaries, input validation, or authorization. Sandbox escape risks remain without strict validation and explicit authorization checks.
Can middleBrick detect sandbox escape risks when Basic Auth is used?
Yes. middleBrick scans endpoints without credentials and tests findings such as path traversal and IDOR. With a Pro plan, continuous monitoring can detect regressions that may expose sandbox boundaries.