v0.16.0
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_bytesuses that default.0or0Bdisables 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
EXTRACTFAILEDwhile the item is still in the Starr queue (they used to goDELETEDand restart the same bomb). - Folder watcher stays uncapped unless you set limits.
0/ empty is unlimited. max_retriesdefault is 2 (first try plus two retries).0now means that default, not unlimited.- New global
remnant_actiondefaults torename: leftover dest files from an interrupted extract are renamed to*.remnantand 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/MaxRatioabort 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, oroff. Applies to Starr and to folders withmove_back. Files that arrived with the download are kept; names that were not there before extract are leftovers.offfails without retrying.max_retries/UN_MAX_RETRIES: default2.0uses that default.
Per Starr app ([[sonarr]] / radarr / lidarr / readarr / whisparr)
max_bytes/UN_*_MAX_BYTES: override the app default above, or0for 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 (defaultfalse).
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 afterremnant_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.cueis 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
.txzpackages (pkg addon 14/15). - Linux: conventional package names (
unpackerr_…_amd64.deb,unpackerr-….x86_64.rpm); one armhf /armv7hl. - Docker:
golift/unpackerrandghcr.io/unpackerr/unpackerr.:latestis tagged releases;:nightlyis a daily build frommain;:unstableis a manual publish branch. Alpine 3.24. - Built with Go 1.27.
Merged contributions
- Protect disk from rogue archives by @davidnewhall in #667
- Clear interrupted-extraction leftovers and retry by @davidnewhall in #666
- Stamp Windows FileVersion into the exe by @davidnewhall in #668
- Replace Makefile releases with GoReleaser Pro by @davidnewhall in #660
- Sign Windows exe with golift/codesign@v1 by @davidnewhall in #656
- ui: migrate tray backend to energye/systray by @SergioChan in #618
- fix(ui): replace dlgs dialogs with zenity by @SergioChan in #616
- Fix memory leak: clean up stale/failed items from extract map by @mprachar in #624
- Fix cross-platform CUE split path resolution and ManualImport by @mprachar in #621
- fix: remove upper limit on API key length validation by @ferrohd in #628
- ci: checkout PR head on pull_request_target runs by @SergioChan in #620
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