Skip to content

fix(ergasia): validate archive entries and enforce extraction byte caps - #555

Merged
forkwright merged 1 commit into
mainfrom
fix/ergasia-extraction-hardening
Jul 3, 2026
Merged

fix(ergasia): validate archive entries and enforce extraction byte caps#555
forkwright merged 1 commit into
mainfrom
fix/ergasia-extraction-hardening

Conversation

@forkwright

Copy link
Copy Markdown
Owner

Hardens archive extraction against attacker-controlled torrent/usenet payloads (found by the deep-audit). The ZIP backend already validated entries; RAR and 7z did not.

  • RAR path traversalextract_rar now pre-validates every header across the volume set (absolute paths, .., non-UTF-8, and symlink/non-regular entries via st_mode), rejecting the whole archive before any write.
  • 7z path traversal — replaces decompress_file with the custom extract-fn API + pre-scan + per-entry re-validation; rejects symlinks (reparse-point / unix-mode).
  • RAR decompression-bomb denominator — the ratio-guard denominator now derives from the real volume chain (RAR signature + naming), not a directory-wide extension glob, so junk padding can no longer inflate it.
  • Nested-archive symlink followfind_nested_archives uses non-following file_type().
  • Header-trust bomb — a hard byte-cap on real extraction output (7z streaming .take() + rollback; RAR post-hoc snapshot-diff + rollback) aborts when output exceeds declared × ratio, no longer trusting self-reported header sizes.

9 new security tests; gate kanon gate --full green (1839 tests).

Closes #516
Closes #517
Closes #523
Closes #535
Closes #537

Harden archive extraction against arbitrary file write and decompression
bombs on attacker-controlled torrent/usenet payloads.

- RAR path traversal: extract_rar now validates every entry across the
  whole volume set before any write, rejecting absolute paths, parent
  traversal, and symlink/non-regular entries (unix mode in file_attr,
  since unrar 0.5.8 does not surface the RAR5 FSREDIR redirect kind).
- 7z path traversal: extract_7z replaces decompress_file with the custom
  decompress_file_with_extract_fn, pre-scanning + per-entry validating
  names and rejecting symlink/reparse/non-regular entries.
- RAR bomb denominator: volume_set_size derives the compressed size from
  this archive's actual naming chain, signature-verifying each volume so
  junk-extension padding cannot inflate the ratio denominator.
- Nested-archive symlink follow: find_nested_archives uses non-following
  DirEntry::file_type() instead of Path::is_file/is_dir.
- Header-trust bomb: real extraction output is capped at declared×ratio
  (streaming Take for 7z, post-hoc rollback for RAR whose writes unrar
  controls internally).

Gate-Passed: kanon 0.1.5 +stages:fmt,check,clippy,nextest,lint sha:f04b04e6ff392177efc91a320ae30da2e0ccdfd1
@forkwright
forkwright merged commit 3353751 into main Jul 3, 2026
12 checks passed
@forkwright
forkwright deleted the fix/ergasia-extraction-hardening branch July 3, 2026 14:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment