Zip Slip in Feathersjs with Dynamodb
Zip Slip in Feathersjs with Dynamodb — 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 a Feathersjs application that uses Dynamodb as a persistence layer, the risk typically arises around file uploads, asset management, or when the service interacts with local storage and build artifacts—such as when generating reports or storing exported data.
Feathersjs is a framework that abstracts business logic into services. If a service accepts a filename or path parameter (e.g., fileName or path) and uses it to read/write files on disk—perhaps to later store a reference in a Dynamodb table—trusting that input can lead to traversal outside the intended directory. For example, a payload like ../../../etc/passwd could move outside the upload folder. Even if Dynamodb itself does not execute files, the vulnerability is exposed when the application layer uses untrusted input to build file system paths before or after storing metadata in Dynamodb.
An insecure implementation might look like this: a Feathersjs service receives a file upload, saves it using a user-provided name, and writes it to disk with fs.writeFileSync, while also persisting metadata (e.g., file path, user ID) into Dynamodb. If the filename is not sanitized, an attacker can traverse directories, overwrite critical files, or read arbitrary files. The Dynamodb record then stores a reference to the malicious path, potentially enabling further exploitation. This pattern is common in applications that generate signed URLs or manage document repositories, where path traversal can lead to unauthorized access to sensitive files.
Additionally, if the Feathersjs application uses plugins that generate dynamic paths—for instance, organizing uploads by user ID without canonicalizing the path—an attacker can supply sequences like ../../../../../../../../../../etc/shadow to escape the sandbox. The interaction with Dynamodb becomes relevant when audit logs or file metadata are stored; compromised paths can corrupt references or enable enumeration of sensitive resources.
Because middleBrick scans the unauthenticated attack surface and tests input validation and path traversal vectors, it can detect such issues in Feathersjs services that handle file operations, even when Dynamodb is used purely as a metadata store. The scanner checks whether user-controlled path components are properly validated, normalized, and restricted to intended directories.
Dynamodb-Specific Remediation in Feathersjs — concrete code fixes
To remediate Zip Slip in a Feathersjs application that uses Dynamodb, ensure that any user-controlled input used in file paths is strictly validated, normalized, and confined to a designated directory. Do not rely on Dynamodb to enforce path safety; the fix must happen at the file system interaction layer.
Use a whitelist of allowed characters for filenames and reject paths containing .. or path separators. Canonicalize the target directory with path.resolve and ensure the resolved path starts with the intended base directory. Below is a secure example using Node.js path utilities and the AWS SDK for Dynamodb operations.
const path = require('path');
const fs = require('fs-extra');
const { DynamoDBClient, PutItemCommand, GetItemCommand } = require('@aws-sdk/client-dynamodb');
const client = new DynamoDBClient({ region: 'us-east-1' });
const BASE_DIR = path.resolve(__dirname, 'uploads');
async function saveFileSecurely(userId, originalName, content) {
// Validate filename: allow only alphanumeric, dashes, underscores, and extensions
const safeName = originalName.replace(/[^a-zA-Z0-9._-]/g, '_');
if (!safeName || safeName !== originalName) {
throw new Error('Invalid filename');
}
const targetPath = path.join(BASE_DIR, userId);
const finalPath = path.resolve(targetPath, safeName);
// Ensure the resolved path is within BASE_DIR
if (!finalPath.startsWith(BASE_DIR)) {
throw new Error('Path traversal detected');
}
await fs.ensureDir(targetPath);
await fs.writeFile(finalPath, content);
// Store metadata in Dynamodb
const putCmd = new PutItemCommand({
TableName: 'UserFiles',
Item: {
userId: { S: userId },
fileName: { S: safeName },
filePath: { S: finalPath },
uploadedAt: { S: new Date().toISOString() }
}
});
await client.send(putCmd);
return finalPath;
}
async function getFileMetadata(userId, fileName) {
const getCmd = new GetItemCommand({
TableName: 'UserFiles',
Key: {
userId: { S: userId },
fileName: { S: fileName }
}
});
const resp = await client.send(getCmd);
return resp.Item || null;
}
In this example, the filename is sanitized by replacing disallowed characters rather than allowing raw user input. The path.resolve and prefix check ensure that even if the input contains traversal sequences, the final path cannot escape BASE_DIR. The Dynamodb interaction stores only the sanitized filename and resolved path, avoiding storage of attacker-controlled paths.
Additionally, apply input validation at the Feathersjs service layer. Use hooks to sanitize parameters before they reach business logic. For file uploads, prefer libraries that handle path safety internally and avoid constructing filesystem paths from raw user input. middleBrick’s input validation checks can help identify whether path traversal risks are present in your service endpoints.
If you use the Pro plan, enable continuous monitoring to detect regressions in path handling. The GitHub Action can fail builds if scans detect insecure file handling patterns, and the MCP Server allows you to run scans directly from your IDE during development.