Symlink Attack in Adonisjs with Dynamodb
Symlink Attack in Adonisjs with Dynamodb — how this specific combination creates or exposes the vulnerability
A symlink attack in AdonisJS when using DynamoDB typically occurs during file operations that resolve user-controlled paths, such as uploads or temporary file storage, combined with DynamoDB metadata handling. While DynamoDB itself does not interact directly with the filesystem, AdonisJS applications often store files on disk (or via a local cache) and persist references—such as file paths or keys—in DynamoDB. If an attacker can manipulate path resolution—e.g., through an insecure file upload that uses user-supplied filenames without normalization or validation—they may create a symbolic link that points outside the intended directory. When the application later reads or writes using the path stored in DynamoDB, the symlink redirects access to arbitrary locations, potentially exposing sensitive data or enabling write operations in restricted areas.
In AdonisJS, this can surface in controllers that accept file uploads and store metadata (e.g., file path, original name, bucket key) in a DynamoDB table. For example, if the filename is concatenated into a path using string interpolation without sanitization, an attacker might upload a file named ../../../etc/passwd, and the application could resolve this to a sensitive system location. The DynamoDB entry then records the unsafe resolved path, and later operations—such as serving the file or processing it—follow the malicious link. Because DynamoDB stores the path as data, the application trusts it as authoritative, amplifying the impact of the symlink creation. This pattern aligns with common insecure deserialization and path traversal concerns, but the specific risk here is the coupling between filesystem path resolution and database-stored references.
Additionally, if the application uses temporary directories or caches that are shared across users, a symlink placed in one user’s context could affect others when DynamoDB entries are processed by background jobs or event-driven workflows. For instance, a worker reading a file reference from DynamoDB might inadvertently follow a symlink injected earlier, leading to unauthorized reads or writes. The DynamoDB integration does not introduce the symlink vulnerability directly, but it can store and propagate unsafe path information, making the attack persistent across sessions and deployments.
Dynamodb-Specific Remediation in Adonisjs — concrete code fixes
To mitigate symlink risks in AdonisJS with DynamoDB, focus on path sanitization, strict validation, and avoiding storage of raw filesystem paths. Instead of saving absolute or relative paths that can be manipulated, store minimal metadata and reconstruct paths in a controlled manner using safe base directories. Use AdonisJS built-in path utilities and validate all user input before constructing file system references.
1. Validate and sanitize filenames
Ensure uploaded filenames are normalized and restricted to safe characters. Use Node.js path utilities to remove sequences like .. and resolve against a known base directory.
import { join, resolve } from 'path';
import { safeBasename } from '@ioc:AdonisJS/Core/Helpers';
const userSuppliedName = 'document.pdf';
const baseDir = '/app/uploads';
const safeName = safeBasename(userSuppliedName);
const finalPath = resolve(baseDir, safeName);
// Ensure the resolved path is still within baseDir
if (!finalPath.startsWith(resolve(baseDir))) {
throw new Error('Invalid path');
}
2. Use DynamoDB to store identifiers, not filesystem paths
Store a unique identifier (e.g., UUID) in DynamoDB and map it to a file on disk via application logic rather than storing the path itself. This prevents attackers from influencing path resolution through stored metadata.
import { DynamoDB } from 'aws-sdk';
import { v4 as uuidv4 } from 'uuid';
const ddb = new DynamoDB.DocumentClient();
async function storeFileRecord(userId: string, fileBuffer: Buffer, originalName: string) {
const fileId = uuidv4();
const key = `user/${userId}/${fileId}`;
// Save file to disk using key, not originalName
await fs.writeFile(`/app/uploads/${key}`, fileBuffer);
const params = {
TableName: 'Files',
Item: {
id: fileId,
owner: userId,
originalName: originalName, // store original name for display only
s3Key: key, // or a local path key, not a direct filesystem path
createdAt: new Date().toISOString(),
},
};
await ddb.put(params).promise();
return fileId;
}
3. Control path resolution in file-serving logic
When serving files, reconstruct the path from the stored identifier rather than trusting values from DynamoDB. Avoid using user-supplied paths directly in filesystem operations.
async function serveFile(fileId: string, userId: string) {
const params = {
TableName: 'Files',
Key: { id: fileId },
};
const data = await ddb.get(params).promise();
if (!data.Item || data.Item.owner !== userId) {
throw new Error('Not found');
}
const filePath = join('/app/uploads', data.Item.s3Key);
// Double-check that filePath is within allowed directory
if (!filePath.startsWith(resolve('/app/uploads'))) {
throw new Error('Invalid file path');
}
return filePath;
}
4. Apply least-privilege filesystem permissions
Ensure the runtime user for AdonisJS has no write access to sensitive system directories. This limits the impact of any symlink that might be created despite validation.
5. Scan and monitor using middleBrick
Use the middleBrick CLI to scan your AdonisJS endpoints for symlink and path traversal issues. Run middlebrick scan <url> to get findings mapped to OWASP API Top 10 and receive prioritized remediation guidance without agents or credentials.
Frequently Asked Questions
Can DynamoDB itself be exploited via symlink techniques?
Does middleBrick detect symlink risks in API configurations?
middlebrick scan <url> CLI or use the GitHub Action to fail builds if risk scores drop below your threshold.