HIGH container escapeadonisjsbasic auth

Container Escape in Adonisjs with Basic Auth

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

A container escape in an AdonisJS application using HTTP Basic Authentication occurs when an attacker who has compromised an API endpoint or misconfiguration is able to break out of the container’s isolated runtime and access the host system. This risk is heightened when Basic Auth is used without additional transport protections and when the application processes untrusted input that reaches system-level commands or file operations.

AdonisJS does not inherently introduce container escape vulnerabilities, but certain usage patterns combined with Basic Auth can expand the attack surface. For example, if an endpoint authenticated only with Basic Auth accepts user-controlled input and passes it to shell commands (e.g., via child process execution), an authenticated attacker can inject shell metacharacters to execute arbitrary commands on the host. In containerized deployments, processes often run as root for convenience; if the compromised process has such capabilities, command injection leads directly to container escape.

Another scenario involves file upload or path traversal where Basic Auth protects an endpoint but the handler writes or reads files outside the container’s intended directory (e.g., using user-supplied filenames). If the container shares the host filesystem via a volume mount without proper restrictions, an authenticated attacker can read sensitive host files or write malicious content to locations that affect other containers or the host. This is an authentication bypass-adjacent risk: Basic Auth may be correctly implemented, but authorization and input validation are weak, enabling authenticated attackers to traverse paths like ../../../../host/etc/passwd.

Moreover, misconfigured CORS or exposed admin routes protected only by Basic Auth can allow authenticated attackers to leverage browser-based request smuggling or CSRF to trigger server-side requests that reach host services bound to localhost. Because Basic Auth sends credentials in each request, session fixation or credential leakage via logs further increases the likelihood of authenticated command execution or sensitive file access.

To detect such patterns, middleBrick runs checks across multiple categories including Input Validation, Authorization, and Unsafe Consumption. When a scan targets an endpoint that uses Basic Auth and accepts unvalidated input destined for system interactions, findings related to Command Injection, Path Traversal, or Excessive Agency may appear, with remediation guidance emphasizing strict input validation, least-privilege execution, and avoiding direct shell command construction from user data.

Basic Auth-Specific Remediation in Adonisjs — concrete code fixes

Secure Basic Auth usage in AdonisJS involves enforcing HTTPS, avoiding shell command construction from user input, and applying strict validation and least privilege. Below are concrete code examples that demonstrate safe patterns.

1. Enforce HTTPS and reject Basic Auth over plain HTTP

Ensure your server rejects or upgrades non-TLS connections. In AdonisJS, you can enforce HTTPS at the server level or within middleware.

// start/server.ts
import { defineConfig } from '@adonisjs/core/app'

export default defineConfig({
  https: {
    enabled: true,
    certPath: '/path/to/fullchain.pem',
    keyPath: '/path/to/privkey.pem',
  },
})

2. Use middleware to require Basic Auth and validate credentials

Create an authentication middleware that verifies the Authorization header and rejects malformed or missing credentials.

// start/hooks.ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import { Exception } from '@poppinss/utils'

export const authBasic = async (ctx: HttpContextContract, next: () => Promise) => {
  const authHeader = ctx.request.header('authorization')
  if (!authHeader || !authHeader.startsWith('Basic ')) {
    ctx.response.unauthorized({ message: 'Missing or invalid authorization header' })
    return
  }
  const base64 = authHeader.split(' ')[1]
  const decoded = Buffer.from(base64, 'base64').toString('utf-8')
  const [username, password] = decoded.split(':')
  if (username !== process.env.BASIC_USER || password !== process.env.BASIC_PASS) {
    ctx.response.unauthorized({ message: 'Invalid credentials' })
    return
  }
  await next()
}

3. Apply middleware to routes and avoid shell command construction

Register the middleware and use it on routes. Never build shell commands from user input; use parameterized APIs instead.

// start/routes.ts
import Route from '@ioc:Adonis/Core/Route'
import { authBasic } from './hooks'

Route.group(() => {
  Route.get('/safe-endpoint', async ({ response }) => {
    // Safe: no shell interaction, input validated and sanitized
    response.send({ ok: true })
  }).middleware([authBasic])

  // Avoid this pattern:
  // Route.post('/run', async ({ request, response }) => {
  //   const { filename } = request.only(['filename'])
  //   const { stdout } = await exec(`cat ${filename}`) // Dangerous
  //   response.send({ stdout })
  // }).middleware([authBasic])
}).prefix('api/v1')

4. Validate and sanitize all inputs; use allowlists

When you must process user input, validate against an allowlist and avoid any direct use in system operations. For file operations, restrict paths to a designated directory.

// start/validators/file.ts
import { schema, rules } from '@ioc:Adonis/Core/Validator'

export const fileSchema = schema.create({
  filename: schema.string({ trim: true, escape: true }, [
    rules.maxLength(255),
    rules.regex(/^[a-zA-Z0-9._-]+$/), // allowlist safe characters
  ]),
})

// in controller
import { fileSchema } from 'App/Validators/file'

export default class FilesController {
  public async read({ request, response }) {
    const payload = await request.validate({ schema: fileSchema })
    const safePath = path.join('/safe/dir', payload.filename)
    // Ensure resolved path remains within safe directory
    if (!safePath.startsWith('/safe/dir')) {
      response.badRequest({ message: 'Invalid path' })
      return
    }
    // Proceed with safe file read
    response.send({ path: safePath })
  }
}

5. Use environment variables for credentials and avoid hardcoding

Store Basic Auth credentials in environment variables and reference them securely. Do not commit secrets to source control.

// .env
BASIC_USER=apiuser
BASIC_PASS=SuperSecretPass123

// config/auth.ts
export default {
  basic: {
    user: Env.get('BASIC_USER'),
    pass: Env.get('BASIC_PASS'),
  },
}

6. Prefer token-based auth where feasible

For endpoints that require repeated access, consider migrating to token-based authentication (e.g., JWT) to avoid sending credentials in every request and to enable more granular scopes and revocation.

// Example: Issue a JWT after Basic Auth verification
import jwt from 'jsonwebtoken'

const issueToken = (username: string) => {
  return jwt.sign({ sub: username }, process.env.JWT_SECRET!, { expiresIn: '1h' })
}

Frequently Asked Questions

Can middleBrick detect container escape risks when Basic Auth is used in Adonisjs?
Yes. middleBrick scans the unauthenticated attack surface and, when Basic Auth is present, can identify endpoints where authenticated inputs reach system-level operations. Findings may include Command Injection, Path Traversal, and Unsafe Consumption, with remediation guidance focused on input validation, least privilege, and avoiding shell interactions.
Does middleBrick provide code examples for securing Basic Auth in Adonisjs?
middleBrick reports include prioritized findings and remediation guidance. For securing Basic Auth in Adonisjs, follow standard practices: enforce HTTPS, validate and sanitize all inputs, use allowlists, avoid constructing shell commands from user data, and prefer token-based authentication where feasible. Refer to the code examples provided for concrete implementation patterns.