Skip to content

v0.16.0

Choose a tag to compare

@davidnewhall davidnewhall released this 30 Aug 22:30
· 5 commits to main since this release
4b81e0e

This is a big extractor release. Unpackerr now ships xtractr v0.6.0 (up from v0.3.1 in 0.15.2). Archives are harder to trick into writing outside the extract folder or filling a disk, leftover files from a crashed extract no longer get reported as success, and there are new knobs for how aggressive that protection is.

If you extract huge Starr downloads (bigger than the new per-app byte caps) or you had max_retries = 0 for unlimited retries, read Behavior changes first.

Behavior changes

  • Starr extracts now have default uncompressed-byte caps: Sonarr/Whisparr 20GB, Radarr 75GB, Lidarr 4GB, Readarr 1GB. Empty max_bytes uses that default. 0 or 0B disables the cap for that instance.
  • Starr also has fixed (not tunable) extras/file/ratio caps: 1000 files, 5:1 ratio, 8 nested archives, extras walk depth 3, and symlink-named archives are skipped. Hitting a cap fails the item and does not retry. Exhausted Starr failures stay EXTRACTFAILED while the item is still in the Starr queue (they used to go DELETED and restart the same bomb).
  • Folder watcher stays uncapped unless you set limits. 0 / empty is unlimited.
  • max_retries default is 2 (first try plus two retries). 0 now means that default, not unlimited.
  • New global remnant_action defaults to rename: leftover dest files from an interrupted extract are renamed to *.remnant and the extract is retried.

Security

These landed in xtractr and Unpackerr uses them automatically.

  • Zip-slip / path escape: member names that would write next to (not under) the extract folder are rejected.
  • Planted-symlink writes: extract no longer follows a symlink already sitting at the dest path, so an archive cannot clobber a file outside the output tree.
  • Symlink-named archives are skipped on Starr (and on folders unless allow_symlinks = true). The extras pass never follows archive-member zip links.
  • Zip-bomb / disk-fill: MaxBytes / MaxFiles / MaxRatio abort the extract; nested extras share the leftover budget instead of resetting it. Duplicate extras are deduped by device+inode.
  • 7z CRC32 is verified; close errors are no longer ignored.

New config knobs

Global

  • remnant_action / UN_REMNANT_ACTION: rename (default), delete, or off. Applies to Starr and to folders with move_back. Files that arrived with the download are kept; names that were not there before extract are leftovers. off fails without retrying.
  • max_retries / UN_MAX_RETRIES: default 2. 0 uses that default.

Per Starr app ([[sonarr]] / radarr / lidarr / readarr / whisparr)

  • max_bytes / UN_*_MAX_BYTES: override the app default above, or 0 for unlimited.

Per watched folder ([[folder]])

  • max_bytes, max_files, max_ratio, max_nested, extras_max_depth — all default unlimited (0 / empty).
  • allow_symlinks — include symlink-named files in the initial archive search (default false).

Extraction reliability

  • Interrupted extracts: a dest that already exists used to mark the item EXTRACTED. Unpackerr now snapshots dests (from xtractr FinalDests), classifies leftovers vs download content, and retries after remnant_action. Partial moves under the same dests are rolled back first.
  • Cross-device dests: when rename cannot move a file onto another filesystem, xtractr copies to a temp name in the dest folder, then replaces. Refused files are reported instead of silently ignored.
  • CUE/FLAC: stream frames (no more OOM on large sheets), stop double-correlating FLAC, detect .cue.txt, and fix cross-platform split paths / Lidarr ManualImport. APE+CUE (Monkey Audio) splits the same way when a .cue is extracted.
  • Multi-part RAR/7z now returns the full volume list. Archive symlinks are restored as links instead of empty stubs.
  • Memory leak: stale/failed items are removed from the extract map (#624, thanks @mprachar).
  • Starr API keys longer than the old upper bound are accepted (#628, thanks @ferrohd).

Desktop

  • Tray backend is energye/systray (click/right-click shows the menu). Config dialogs use zenity instead of dlgs. Thanks @SergioChan.

Packaging and install

Releases are built with GoReleaser Pro. User-facing bits:

  • macOS: notarized universal DMG / Unpackerr.app.. Minimum macOS 13.
  • Windows: Authenticode-signed exe; Explorer File version is stamped (Major.Minor.Patch.REVISION).
  • FreeBSD: real pkgng .txz packages (pkg add on 14/15).
  • Linux: conventional package names (unpackerr_…_amd64.deb, unpackerr-….x86_64.rpm); one armhf / armv7hl.
  • Docker: golift/unpackerr and ghcr.io/unpackerr/unpackerr. :latest is tagged releases; :nightly is a daily build from main; :unstable is a manual publish branch. Alpine 3.24.
  • Built with Go 1.27.

Merged contributions

Extractor (xtractr) highlights that ship with this release: zip-slip and symlink-follow hardening (golift/xtractr#159, golift/xtractr#161, golift/xtractr#175), extract caps (golift/xtractr#176, golift/xtractr#182, golift/xtractr#185), remnants/refusals (golift/xtractr#177, golift/xtractr#181), cross-device copy (golift/xtractr#178), 7z CRC32 (golift/xtractr#171), APE+CUE (golift/xtractr#145), FLAC OOM/corruption (golift/xtractr#142, golift/xtractr#143), multi-part volumes (golift/xtractr#140).

New contributors

Full Changelog: v0.15.2...v0.16.0