Description
Description
util.Unzip rejects traversal entries with a destination path boundary check, but it copies each archive entry with io.Copy and does not appear to enforce a per-entry or total output-size limit.
Relevant code in internal/util/util.go:
path := filepath.Join(dest, f.Name)
if !strings.HasPrefix(path, filepath.Clean(dest)+string(os.PathSeparator)) {
return fmt.Errorf("illegal file path: %s", path)
}
_, err = io.Copy(f, rc)
Local validation output:
=== RUN TestReproH12_UnzipBombAndTraversalMitigation
repro_high_test.go:57: (a) traversal rejected by HasPrefix: illegal file path: /tmp/TestReproH12_UnzipBombAndTraversalMitigation3808501357/outside.txt
repro_high_test.go:76: (b) 2182-byte zip -> 2097152 bytes via io.Copy with NO LimitReader
repro_high_test.go:77: H12 = SPLIT: traversal mitigated (HasPrefix, FP), zip bomb real (io.Copy no cap, TP)
--- PASS: TestReproH12_UnzipBombAndTraversalMitigation (0.01s)
Expected behavior:
Unzip should enforce a reasonable per-entry and/or total extracted-size limit, or allow callers to provide one.
Actual behavior:
Each entry is copied until EOF, so extracted output size is controlled entirely by the archive contents.
Suggested fix:
Add an extraction size budget, such as a maximum bytes-per-entry and total extracted bytes. The copy path could use a bounded reader/writer and return an error once the configured limit is exceeded.
Environment
Environment
- Version: tested at commit 77de728
- OS: Linux / Docker
- Terminal: N/A
Description
Description
util.Unzip rejects traversal entries with a destination path boundary check, but it copies each archive entry with io.Copy and does not appear to enforce a per-entry or total output-size limit.
Relevant code in internal/util/util.go:
Local validation output:
Expected behavior:
Unzip should enforce a reasonable per-entry and/or total extracted-size limit, or allow callers to provide one.
Actual behavior:
Each entry is copied until EOF, so extracted output size is controlled entirely by the archive contents.
Suggested fix:
Add an extraction size budget, such as a maximum bytes-per-entry and total extracted bytes. The copy path could use a bounded reader/writer and return an error once the configured limit is exceeded.
Environment
Environment