

0 / 2 embers
0 / 3000 xp
click for more info
Complete a lesson to start your streak
click for more info
Difficulty: 10
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 destination path. We can use the relative path of the destination, starting from a trusted extraction root, to make sure it doesn't escape:
relativePath, err := filepath.Rel(root, destination)
if err != nil ||
relativePath == "." ||
relativePath == ".." ||
strings.HasPrefix(relativePath, ".."+string(filepath.Separator)) {
return errors.New("archive entry escapes the extraction directory")
}
In Go, filepath.Rel describes how to reach a destination from a given root. Since we want to accept only destinations that fall under the extraction directory, we reject paths that meet any of these conditions:
., so the destination is the root itself (bad)..., so the destination is the parent directory of the root (bad)... plus the platform's filepath.Separator, so the destination is outside the root (bad).Other platform-aware checks are also worth running against archive entries before extraction. A Windows-style path with backslashes cannot safely be treated as an ordinary document path. Nor can a symbolic link.
A symbolic link, or symlink, is a file that points to another filesystem path. These demand careful handling (or rejection). In Go, you can check if a file is a symlink by looking at its ModeSymlink bit.
For a primer on symlinks, see our Linux course.
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 plans every ZIP entry before writing it, but it does not validate the planned paths. Reject the entire archive when any entry could escape or redirect extraction.
With Bearly Secure still running, run and submit the CLI tests from the project root.