

0 / 2 embers
0 / 3000 xp
click for more info
Complete a lesson to start your streak
click for more info
Still calibrating
click for more info
Not enough gems
Cost: 6 gems
1: Injection
incomplete
2: Fixing SQL Injection
incomplete
3: Injection Beyond SQL
incomplete
4: Safe Validation and Sanitization
incomplete
5: When to Sanitize
incomplete
6: Unsafe Archive Extraction
incomplete
7: Safe Archive Extraction
incomplete
8: LLM Prompt Injection
incomplete
9: Limiting Tool Calls
incomplete
10: Narrow Tool Interfaces
incomplete
11: File Upload Security
incomplete
Back
ctrl+,
Next
ctrl+.
This lesson's interactive features are locked, please to keep using them
The fix for our file-path problems is to validate each entry name after resolving its final absolute path. Then use the relative path from the trusted extraction root to check whether the destination escapes it:
import { isAbsolute, relative, resolve, sep } from "node:path";
const root = resolve(extractionDirectory);
const destination = resolve(root, entryName);
const relativePath = relative(root, destination);
if (
relativePath === "" ||
relativePath === ".." ||
relativePath.startsWith(`..${sep}`) ||
isAbsolute(relativePath)
) {
throw new Error("Archive entry escapes the extraction directory");
}
Node's path.resolve produces an absolute destination, and path.relative describes how to reach it from the trusted root. If the relative path is:
..: the destination is the root's parent (bad)... plus the platform's path.sep: the destination is outside the root (bad).When it comes to archives, always validate all entry destinations before extracting any of them. If the fifth entry is malicious, but you only discover that after writing the first four, you'll get a partial extraction and leave the system in an inconsistent state.
Archive extraction also needs resource limits. Compressed input can expand dramatically, so production systems should cap the number of entries and total uncompressed size. If you don't, you're open to zip bomb attacks. They don't leak anything, but they can bring down your servers' ability to respond by exhausting their disk space or memory as a type of denial-of-service attack.
Bearly Secure resolves every ZIP entry before it writes files, but its isInsideDirectory helper trusts every destination. Keep bulk tax-document extraction inside data/bulk-tax-documents.
Run and submit the CLI tests from the project root.