Skip to content

fix zip symlink extraction, clean up cfg-gated test imports#199

Merged
jaemk merged 1 commit into
masterfrom
260719.zip-symlinks-clippy
Jul 20, 2026
Merged

fix zip symlink extraction, clean up cfg-gated test imports#199
jaemk merged 1 commit into
masterfrom
260719.zip-symlinks-clippy

Conversation

@jaemk

@jaemk jaemk commented Jul 19, 2026

Copy link
Copy Markdown
Owner
  • Restore zip symlink entries (S_IFLNK unix mode) as real symlinks in Extract::extract_into on unix. Previously the entry's target path text was written as a regular file, corrupting directory trees that rely on symlinks (e.g. a macOS .app's Frameworks/*/Versions/Current) and breaking the publisher's code signature. On windows symlink entries still extract as regular files (creating symlinks requires privileges; documented). Tar extraction was already correct.
  • Validate symlink targets: reject absolute targets and targets whose lexical resolution escapes the extraction root, consistent with the existing enclosed_name zip-slip defense. As a backstop against symlinked-parent traversal (a link aliasing an ancestor, then later entries descending through it), every file/symlink entry's physical parent must canonicalize to exactly canonical_root/<lexical parent> before anything is created.
  • Reject symlink entries in Extract::extract_file instead of writing the target text as the requested file.
  • Gate the test-only ReleaseAsset import in update.rs behind checksums and the Duration import in s3.rs behind s3-auth, so single-backend clippy -D warnings runs (--features s3, --features github, bare) are clean.

Tests: 14 zip-extraction tests (unix-gated) covering symlink restore, chains, implicit parents, absolute/escaping/deep-traversal rejection, symlinked destination dirs, dir-through-symlink containment, and regressions for mode preservation and zip-slip. Spec updated in specs/ref-update-pipeline.md.

…t escaping targets

- a zip entry whose unix mode is `S_IFLNK` was extracted as a regular file
  containing the target path text, corrupting directory trees that rely on
  symlinks (e.g. a macOS .app's `Frameworks/*/Versions/Current`) and breaking
  the publisher's code signature. On unix such entries are now restored with
  `std::os::unix::fs::symlink`; on windows they still extract as regular files
  (creating symlinks requires privileges; documented).
- symlink targets are validated: an absolute target or one whose lexical
  resolution escapes the extraction root is rejected, consistent with the
  existing `enclosed_name` zip-slip defense. As a backstop against
  symlinked-parent traversal (a link aliasing an ancestor, then entries
  descending through it), every file/symlink entry's physical parent must
  canonicalize to exactly `canonical_root/<lexical parent>` before anything is
  created.
- `extract_file` rejects a symlink entry instead of writing the target text as
  the requested file.
- gate the test-only `ReleaseAsset` import in update.rs behind `checksums` and
  the `Duration` import in s3.rs behind `s3-auth` so single-backend
  `clippy -D warnings` runs are clean.
@jaemk
jaemk force-pushed the 260719.zip-symlinks-clippy branch from bf672b6 to 464f0ec Compare July 20, 2026 00:37
@jaemk
jaemk merged commit 6ccfc16 into master Jul 20, 2026
3 checks passed
jaemk added a commit that referenced this pull request Jul 20, 2026
jaemk added a commit that referenced this pull request Jul 20, 2026
* docs: add bundle-install design spec for directory-bundle (.app) installs

Design doc for #145 phase A (maintainer sign-off before implementation):
`bundle_root_in_archive`/`bundle_install_path` builder API, whole-tree
stash-and-rollback swap with `MoveAll` semantics, same-filesystem staging,
preflight interaction, non-goals (.deb/.msi recipe-only, no signing/notarizing,
no escalation), test strategy, and the open API questions. Also records that
zip symlink entries are currently extracted as regular files (a standalone bug
for .app framework symlinks; see BNDL-4-2).

* docs: note the zip-symlink fix landed in #199
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant