Zip Slip in Feathersjs with Api Keys
Zip Slip in Feathersjs with Api Keys — how this specific combination creates or exposes the vulnerability
Zip Slip is a path traversal vulnerability that occurs when an API constructs file paths by directly concatenating user-supplied input with a base directory. In FeathersJS applications that use API keys for authentication, a common pattern is to associate uploaded or downloadable resources with the authenticated entity via the key’s scope or metadata. If the API key is used only to identify permissions or tenant context, but file paths are built by concatenating a user-provided filename or path segment, an attacker can supply sequences like ../../../etc/passwd or archive entries that traverse outside the intended directory. When FeathersJS services handle file uploads or downloads without canonicalizing and validating the resulting path, the API key–based authorization check can pass while the actual file operation escapes the allowed directory.
Consider a FeathersJS service that stores user attachments keyed by an API key identifier. An endpoint like /files/:apiKey/:name might look up the key, authorize access, and then join uploads/ with the name parameter. If name is user-controlled and not sanitized, an attacker can set name to ../../../secrets/config.json. The authorization based on the API key succeeds, but the resolved path traverses outside uploads/, exposing sensitive files. Even when API keys enforce tenant isolation, Zip Slip can lead to horizontal or vertical privilege escalation across tenant boundaries or host system files.
Because middleBrick scans the unauthenticated attack surface, it can detect endpoints where path traversal is feasible even when API key checks appear present. The scan checks input validation and path-resolution logic across the 12 security checks, highlighting risks such as improper canonicalization, missing path sanitization, and overly permissive directory traversal patterns. Remediation focuses on strict input validation, path normalization, and ensuring that API key–based authorization is combined with secure file handling rather than relied upon alone to enforce path boundaries.
Api Keys-Specific Remediation in Feathersjs — concrete code fixes
To remediate Zip Slip in FeathersJS when using API keys, enforce strict path handling in your service hooks and middleware. Do not rely on API key–based authorization alone to prevent path traversal. Instead, normalize and validate file paths, and scope files by API key without allowing user input to control directory traversal.
Example: Secure file path handling in a FeathersJS service
const path = require('path');
const crypto = require('crypto');
// Utility to generate a safe, non-traversable filename or path
function safeFilename(input, ext) {
const hash = crypto.createHash('sha256').update(input).digest('hex');
return `${hash}${ext ? `.${ext}` : ''}`;
}
// FeathersJS service hook to sanitize and scope file paths
app.service('files').hooks({
before: {
async create(context) {
const { apiKey, file } = context.data; // Assume multipart/form-data parsed
// Validate and authorize the API key via your auth strategy (not shown)
const userId = await resolveApiKeyOwner(apiKey); // implement this
if (!userId) throw new Error('Unauthorized');
// Do not trust context.data.path or uploaded filename for directory traversal
const originalName = file ? file.name : 'unknown';
const ext = path.extname(originalName);
const safeName = safeFilename(`${userId}-${Date.now()}`, ext.replace('.', ''));
// Ensure uploads are scoped per API key/user and avoid user-controlled subpaths
const uploadDir = path.resolve(__dirname, '..', 'uploads', userId);
// Ensure directory exists securely (omitted fs.mkdir details for brevity)
// Build a safe destination path; do not concatenate user input
const destination = path.join(uploadDir, safeName);
await moveFileTo(file.tmpPath, destination); // implement file move
// Return a safe reference, never the user-supplied path
context.result = { path: destination, name: safeName };
return context;
}
}
});
// Example resolveApiKeyOwner placeholder (implement your auth lookup)
async function resolveApiKeyOwner(apiKey) {
// Map API key to user ID; ensure keys are scoped per tenant/user
const mapping = { 'trusted-key-123': 'user-abc' };
return mapping[apiKey] || null;
}
In this example, the API key is used only for authentication and scoping (mapping to a user ID). The file path is built from a hashed, non-user-controlled name, and the destination directory is explicitly scoped under the user ID without concatenating any user-provided path segments. This prevents Zip Slip regardless of malicious input in the filename or path parameters.
Comparing approaches
| Approach | Authorization | Path Handling | Zip Slip Risk |
|---|---|---|---|
| API key + user path concatenation | API key validates tenant | Unsafe join(userPath) | High |
| API key + scoped directory + hashed filename | API key maps to user | Safe path.join(scoped, hash) | Low |
Additionally, ensure your API’s OpenAPI specification (if used) does not promote unsafe path parameters. middleBrick’s OpenAPI/Swagger spec analysis can cross-reference runtime findings with spec definitions to highlight inconsistencies in path templates that may encourage traversal. With the Pro plan, continuous monitoring can alert you if new endpoints introduce similar risks, and the GitHub Action can fail builds when insecure path patterns are detected in code or specs.