0.3.9 - 2026-08-27
Release Notes
An adversarial review of the same day's hardening, which found that the
hardening was incomplete and that one of its fixes did not fire.
Security
-
A member could still be renamed out from under the uniqueness check. 0.3.8
refused three ways a crafted end of central directory record could make this
crate and its ZIP dependency resolve different directories. There was a
fourth, and it is inside a single well-formed entry where no record-level
guard can see it: the Info-ZIP Unicode Path extra field, tag 0x7075, carries a
replacement name and the ZIP crate applies it, whilecentral.rsskipped
extra fields and counted the recorded name. Three members with distinct
recorded names — the third renaming itself to the second's — came back
conformant and unpacked to the third's bytes, while Python'szipfilesaw two
members of one name. The metadata member is swappable the same way.Refused rather than honoured, which is the decision §2.1 has now taken four
times. Honouring it would make the field a third way to spell a member's name,
after the name field and the bit 11 encoding SPEC §2.1 defines, and that is a
change to the format rather than a fix to a reader. Measured against the tools
available: Info-ZIP writes 0x5455 and 0x7875 even with-UN=UTF8, 7-Zip
writes 0x000a, Python writes none. Those fields are untouched. -
The provenance carry added in 0.3.7 did not fire on a read-only container.
commitset the replacement's permissions — taken from the file being
replaced — before carrying the mark onto it, so a container at 0444 made the
temporary read-only andxattr::setwas then denied. Measured: a marked
container at 0444 came back fromrepackwith no mark, silently, exit zero.
Where a platform enforces the mark it is worse: the carry fails,commit
propagates it, and an in-place rewrite of any read-only marked container fails
outright. The carry now runs first. The test that should have caught this used
a default-mode file. -
A failed
unpack --metadatano longer leaves the metadata behind. 0.3.8
reordered the commits so a refusal leaves no payload; the inverse was left
standing, so a payload that could not land left a metadata file the error
never mentioned and the obvious retry then failed on it.
Fixed
display_nameescapes a backslash, so its rendering is reversible. A name
that literally spellsreport\u{202E}fdp.exeand one carrying the override
used to come out identical.
Install slipcase 0.3.9
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/excelano/slpc-rust/releases/download/v0.3.9/slipcase-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/excelano/slpc-rust/releases/download/v0.3.9/slipcase-installer.ps1 | iex"Install prebuilt binaries via Homebrew
brew install excelano/tap/slipcaseDownload slipcase 0.3.9
| File | Platform | Checksum |
|---|---|---|
| slipcase-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| slipcase-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| slipcase-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| slipcase-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| slipcase-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |