fix(tar): reject symlink targets that resolve outside destination - #83
Open
johnmccrae wants to merge 1 commit into
Open
johnmccrae wants to merge 1 commit into
johnmccrae wants to merge 1 commit into
Conversation
chef-client -z --recipe-url downloads a tarball and extracts it with mixlib-archive, which followed symlinks in the archive without verifying that the symlink target stayed within the destination directory. A crafted tarball containing a symlink entry pointing outside destination, followed by a second entry whose path traverses that symlink, let an attacker write files anywhere on disk that the extracting process could reach (tar-slip). Since chef-client runs as root, this is an arbitrary file write as root and a path to full node compromise (e.g. dropping a cron.d file, systemd unit, or SSH authorized_keys entry). - Tar: before creating a symlink, resolve its target relative to its own directory and skip (with a warning) any symlink whose target resolves outside destination_root. Because every other write is already confined to destination_root, this closes the escape for any chain of symlinks. - LibArchive: always set EXTRACT_SECURE_SYMLINKS and EXTRACT_SECURE_NODOTDOT flags on extraction (previously only permission flags were applied), giving the same protection natively in the libarchive-backed extractor used in production. - Add regression specs proving the escape is blocked while legitimate in-destination symlinks continue to work. Signed-off-by: John McCrae john.mccrae@progress.com Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: John McCrae <john.mccrae@progress.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
chef-client -z --recipe-url downloads a tarball and extracts it with mixlib-archive, which followed symlinks in the archive without verifying that the symlink target stayed within the destination directory. A crafted tarball containing a symlink entry pointing outside destination, followed by a second entry whose path traverses that symlink, let an attacker write files anywhere on disk that the extracting process could reach (tar-slip). Since chef-client runs as root, this is an arbitrary file write as root and a path to full node compromise (e.g. dropping a cron.d file, systemd unit, or SSH authorized_keys entry).
Signed-off-by: John McCrae john.mccrae@progress.com
Description
Summary
Fixes a path-traversal / arbitrary-file-write vulnerability ("tar-slip") in mixlib-archive's tar extraction. A malicious tarball can contain a symlink entry pointing outside the extraction destination, followed by a second entry whose path travels through that symlink. Previously neither the pure Ruby
Tarextractor nor theLibArchiveextractor verified that a symlink's target stayed within the destination directory, so the second entry's write landed wherever the attacker's symlink pointed — anywhere on disk.This is exploitable via
chef-client -z --recipe-url <URL>, which downloads and unpacks an untrusted tarball using mixlib-archive. Since chef-client typically runs as root on a managed node, this allows an attacker-controlled tarball to achieve arbitrary file write as root (e.g./etc/cron.d, a systemd unit, or/root/.ssh/authorized_keys), leading to code execution.Changes
lib/mixlib/archive/tar.rb: When handling a symlink entry, resolve its target relative to the symlink's own directory and reject (log + skip) any target that resolves outsidedestination_root. Every other entry write is already confined todestination_root, so this closes the escape regardless of symlink chaining.lib/mixlib/archive/lib_archive.rb: Always pass libarchive'sEXTRACT_SECURE_SYMLINKSandEXTRACT_SECURE_NODOTDOTextraction flags (previously only permission flags were conditionally set), providing the same protection natively for the libarchive-backed extractor used by default in production.spec/mixlib/tar_spec.rb) that build a tarball with a symlink escaping the destination plus a payload entry through it, asserting the escape is blocked, and that legitimate in-destination symlinks still extract correctly.spec/mixlib/lib_archive_spec.rbto pass the same./..ignore list used by the realMixlib::Archive#extractAPI, required onceEXTRACT_SECURE_NODOTDOTis enforced.Tests & Coverage
Reproduced the vulnerability against the pre-fix code (confirmed file written outside destination via symlink), then verified the fix closes it. Full suite:
bundle exec rake spec(33 examples, 0 failures) andbundle exec rake style(cookstyle, no offenses) both pass.Risk & Mitigations
Low risk of regression: legitimate symlinks that resolve within the destination directory continue to work (covered by a new spec). Symlinks whose target resolves outside destination are now skipped with a warning log rather than silently followed, which is strictly safer default behavior. No public API signatures changed.
DCO
All commits Signed-off-by.
Related Issue
Types of changes
Checklist:
Gemfile.lockhas changed, I have used--conservativeto do it and included the full output in the Description above.