HIGH symlink attackadonisjsmutual tls

Symlink Attack in Adonisjs with Mutual Tls

Symlink Attack in Adonisjs with Mutual Tls

A symlink attack in AdonisJS occurs when an application resolves user-controlled paths and writes files to locations outside the intended directory. When mutual TLS (mTLS) is used, the transport layer enforces client certificate validation, which strongly authenticates the peer. However, mTLS does not reduce risks in the application logic itself; it only ensures that the request originates from a trusted client. An authenticated client can still send crafted parameters—such as file paths or names—that lead to directory traversal or symlink-based path resolution. If AdonisJS code uses utilities like fs.ensureDir or fs.move with user input directly, an attacker can provide a filename that resolves via ../ or a symlink to a sensitive location, achieving unauthorized file write or overwrite.

In practice, consider an AdonisJS endpoint that accepts a filename and writes a file under uploads/. If the server resolves the path by concatenating a base directory with the user-supplied name without canonicalization, a filename such as ../../../etc/passwd or a symlink like file.txt -> /root/secrets can redirect the write outside uploads/. Mutual TLS ensures the request is authenticated, but it does not prevent the application from following malicious paths. The vulnerability therefore lies in insecure path handling, not in the TLS configuration. An attacker with a valid certificate can exploit this to read or overwrite arbitrary files, depending on server permissions.

To detect this class of issue, scans should test endpoints that handle file operations with authenticated mTLS requests containing path traversal or symlink payloads. The scanner checks whether resolved paths stay within the intended directory and whether symlinks are resolved before file operations. Developers should treat mTLS as a strong authentication mechanism and not a substitute for input validation and path canonicalization.

Mutual Tls-Specific Remediation in Adonisjs

Remediation focuses on secure path handling and ensuring symlinks are resolved safely. Always resolve user-supplied paths against a canonical base directory and reject paths that escape this directory. Use platform APIs that normalize and validate paths before file operations. In AdonisJS, this means validating and sanitizing any filename or path parameter, avoiding direct concatenation with user input, and ensuring symbolic links are not followed when writing files.

Below are concrete code examples for AdonisJS with mutual TLS configured at the reverse proxy or application layer. The application assumes mTLS is enforced upstream (e.g., by a load balancer), and AdonisJS can read the client certificate from headers. The focus here is on secure file handling.

Mutual Tls Configuration Example

AdonisJS does not terminate mTLS directly but can rely on headers set by the TLS terminating proxy. You can read the client certificate details to augment logging or authorization, while still applying strict path validation.

// start/hooks.ts
import { IHookContext } from '@adonisjs/core/types'

export const handleMtlsClientInfo = (ctx: IHookContext) => {
  const request = ctx.request
  const certHeader = request.headers().get('x-client-cert')
  // Optionally parse certificate details for audit logging
  // Do not rely on this for access control alone; validate paths rigorously
  if (certHeader) {
    ctx.auth.setUser({
      id: 'mtls-user',
      // extract subject or fingerprint if needed
    })
  }
}

Secure File Write with Path Canonicalization

Use Node.js path utilities to resolve and validate the final path before writing. Ensure the resolved path starts with the intended base directory.

import { join, resolve, normalize } from 'path'
import { ensureDir, move } from 'fs-extra'

export async function saveUploadedFile(baseDir: string, userFilename: string, content: Buffer) {
  // Normalize and resolve the user-provided filename
  const normalized = normalize(userFilename)
  // Prevent path traversal attempts
  if (normalized.startsWith('..') || normalized.includes('\0')) {
    throw new Error('Invalid filename')
  }
  const target = resolve(baseDir, normalized)
  // Ensure the target is within the allowed directory
  if (!target.startsWith(resolve(baseDir))) {
    throw new Error('Path traversal detected')
  }
  await ensureDir(baseDir)
  await move(target, target, { overwrite: true }) // example operation
}

Middleware to Enforce Safe Paths

Add a request-scoped validation layer that checks file-related parameters before they reach route handlers.

import { middleware } from '@adonisjs/core'

export const pathValidation = middleware(async (ctx, next) => {
  const fileName = ctx.request.input('fileName')
  const safeName = fileName.replace(/[^a-zA-Z0-9._-]/g, '_')
  if (safeName !== fileName) {
    ctx.response.badRequest({ error: 'Invalid filename' })
    return
  }
  ctx.request.merge({ safeFileName: safeName })
  await next()
})

Using the Middleware in Routes

import Route from '@ioc:Adonis/Core/Route'
import { pathValidation } from 'App/Middleware/path_validation'

Route.post('/upload', [pathValidation], async (ctx) => {
  await saveUploadedFile('uploads', ctx.request.safeFileName, ctx.request.file('file').data)
  return { ok: true }
})

These practices ensure that even with mTLS providing strong client authentication, the application remains resilient against symlink and path traversal attacks. Security depends on correct handling of user input, not solely on transport-layer authentication.

Frequently Asked Questions

Does mutual TLS prevent symlink attacks in AdonisJS?
No. Mutual TLS authenticates clients at the transport layer but does not protect against application-level path handling flaws. You must validate and canonicalize file paths independently.
How can scanning help detect symlink risks with mTLS?
Scans can send authenticated requests with crafted filenames containing path traversal or symlink payloads to verify whether resolved paths stay within the intended directory and whether symlinks are resolved safely.