

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
File uploads accept large amounts of user-controlled data in formats that may later be parsed, served, or executed. A safe upload boundary cannot trust the filename or content type supplied by the client.
This handler writes an upload under its original name without inspecting the contents:
file, header, err := request.FormFile("file")
if err != nil {
return err
}
defer file.Close()
contents, err := io.ReadAll(file)
if err != nil {
return err
}
return os.WriteFile(filepath.Join("public/uploads", header.Filename), contents, 0o644)
The attacker still chooses the filename and extension, and a multipart Content-Type header is only another client claim. A name collision can overwrite an earlier upload, and renaming a script to image.png does not turn its bytes into an image.
A safer handler inspects the bytes, generates its own storage name, and writes outside public asset directories:
contentType, extension, valid := detectDocumentType(contents)
if !valid {
return errors.New("unsupported file type")
}
identifier, err := identifiers.NewUUID()
if err != nil {
return err
}
storagePath := filepath.Join("data/uploads", identifier+extension)
Useful upload boundaries include:
See OWASP's File Upload Cheat Sheet for a broader defense-in-depth checklist.
Bearly Secure already receives tax-document bytes in memory and persists their metadata, but StoreDocument accepts any bytes and gives every file a generic name. Archive imports also trust file extensions. Detect each file's type before persistence and generate a safe storage name.
With Bearly Secure still running, run and submit the CLI tests from the project root.