Prevent extraction from escaping destination_dir via pre-existing symlinks#9493
Open
thesmartshadow wants to merge 1 commit intoruby:masterfrom
Open
Prevent extraction from escaping destination_dir via pre-existing symlinks#9493thesmartshadow wants to merge 1 commit intoruby:masterfrom
thesmartshadow wants to merge 1 commit intoruby:masterfrom
Conversation
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.
What was the end-user or developer problem that led to this PR?
When extracting a gem, RubyGems correctly rejects obvious path traversal patterns such as absolute paths or
.., but it can still follow a pre-existing symlink inside the destination directory.In practice, if part of the extraction path already exists as a symlink pointing outside the extraction root, a file that appears to be written under
destination_dircan end up being written outside of it instead. That breaks the expected safety boundary of extraction and makes extraction unsafe in reused or shared directories.What is your fix for the problem, implemented in this PR?
This PR adds a link-aware safety check before writing extracted files.
After ensuring the parent directory exists, it resolves the real path of that parent directory and verifies that it still stays under the intended extraction root. If the resolved parent path escapes
destination_dir, extraction now raisesGem::Package::PathErrorinstead of continuing with the write.This keeps extraction confined to the intended destination even when pre-existing symlinks are present in the path.
This PR also adds a regression test covering that case by planting a symlink in the destination path and asserting that:
Gem::Package::PathErrorValidation
I verified the change with:
Gem::Package::PathErrorChecklist