Skip to content

Commit

Permalink
Fix absolute paths being extracted outside of destination directory
Browse files Browse the repository at this point in the history
  • Loading branch information
rohan-b99 committed Jun 21, 2022
1 parent 48da7e5 commit 97eb284
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 12 deletions.
28 changes: 16 additions & 12 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,11 @@ where
ffi::ARCHIVE_EOF => return Ok(()),
ffi::ARCHIVE_OK => {
let target_path = CString::new(
sanetize_destination_path(
&dest.join(
CStr::from_ptr(ffi::archive_entry_pathname(entry))
.to_string_lossy()
.into_owned(),
),
)?
dest.join(sanitize_destination_path(Path::new(
&CStr::from_ptr(ffi::archive_entry_pathname(entry))
.to_string_lossy()
.into_owned(),
))?)
.to_str()
.unwrap(),
)
Expand All @@ -232,9 +230,9 @@ where
let link_name = ffi::archive_entry_hardlink(entry);
if !link_name.is_null() {
let target_path = CString::new(
sanetize_destination_path(&dest.join(
CStr::from_ptr(link_name).to_string_lossy().into_owned(),
))?
dest.join(sanitize_destination_path(Path::new(
&CStr::from_ptr(link_name).to_string_lossy().into_owned(),
))?)
.to_str()
.unwrap(),
)
Expand Down Expand Up @@ -453,10 +451,16 @@ where
}

// This ensures we're not affected by the zip-slip vulnerability. In summary, it
// uses relative destination paths to unpack files in unexpected places.
// uses relative destination paths to unpack files in unexpected places. This also
// handles absolute paths, where the leading '/' will be stripped, matching behaviour
// from gnu tar and bsdtar.
//
// More details can be found at: http://snyk.io/research/zip-slip-vulnerability
fn sanetize_destination_path(dest: &Path) -> Result<&Path> {
fn sanitize_destination_path(mut dest: &Path) -> Result<&Path> {
if dest.starts_with("/") {
dest = dest.strip_prefix("/").unwrap_or(dest);
}

dest.components()
.find(|c| c == &Component::ParentDir)
.map_or(Ok(dest), |_| {
Expand Down
Binary file added tests/fixtures/absolute-path.tar
Binary file not shown.
23 changes: 23 additions & 0 deletions tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//
// SPDX-License-Identifier: MIT OR Apache-2.0

use std::path::Path;
use compress_tools::*;

#[test]
Expand Down Expand Up @@ -560,3 +561,25 @@ fn uncompress_archive_zip_slip_vulnerability() {
"SECURITY ERROR: evil.txt has been uncompressed in /tmp!"
);
}

#[test]
fn uncompress_archive_absolute_path() {
let temp_dir = tempfile::TempDir::new().expect("Failed to create the tmp directory");
let dest = temp_dir.path();

let correct_dest = dest.join("test.txt");
let incorrect_dest = Path::new("/test.txt");

assert!(
uncompress_archive(
&mut std::fs::File::open("tests/fixtures/absolute-path.tar").unwrap(),
dest,
Ownership::Ignore,
)
.is_ok(),
"SECURITY ERROR: test.txt has been uncompressed in /!"
);

assert!(correct_dest.exists());
assert!(!Path::new(incorrect_dest).exists());
}

0 comments on commit 97eb284

Please sign in to comment.