#![cfg(feature = "storage")]
use kkachi::recursive::PackagerBuilder;
#[test]
fn test_no_path_traversal() {
let dir = tempfile::tempdir().unwrap();
let db_path = dir.path().join("test.db");
std::fs::write(&db_path, b"fake-db-content").unwrap();
let out_dir = dir.path().join("dist");
let result = PackagerBuilder::new(&db_path)
.name("../evil")
.version("0.1.0")
.output_dir(out_dir.to_str().unwrap())
.compress(false)
.build();
match result {
Ok(pkg) => {
let canonical_out = out_dir.canonicalize().unwrap();
let canonical_whl = pkg.wheel_path.canonicalize().unwrap();
assert!(
canonical_whl.starts_with(&canonical_out),
"Wheel escaped output_dir! wheel_path={}, output_dir={}",
canonical_whl.display(),
canonical_out.display(),
);
let parent = dir.path();
let stray_files: Vec<_> = std::fs::read_dir(parent)
.unwrap()
.filter_map(|e| e.ok())
.filter(|e| {
let name = e.file_name();
let s = name.to_string_lossy();
s.contains("evil") || s.ends_with(".whl")
})
.collect();
assert!(
stray_files.is_empty(),
"Path traversal created stray files in parent dir: {:?}",
stray_files.iter().map(|e| e.path()).collect::<Vec<_>>(),
);
let file = std::fs::File::open(&pkg.wheel_path).unwrap();
let mut archive = zip::ZipArchive::new(file).unwrap();
for i in 0..archive.len() {
let entry = archive.by_index(i).unwrap();
let entry_name = entry.name().to_string();
assert!(
!entry_name.contains("../"),
"ZIP entry contains path traversal: {}",
entry_name,
);
}
}
Err(_) => {
}
}
}
#[test]
fn test_wheel_name_sanitization() {
let dir = tempfile::tempdir().unwrap();
let db_path = dir.path().join("test.db");
std::fs::write(&db_path, b"fake-db-content").unwrap();
let out_dir = dir.path().join("dist");
let tricky_names = [
"my-package", "name with space",
"name/slash",
"name\\backslash",
"name@version",
"name!bang",
];
for name in &tricky_names {
let result = PackagerBuilder::new(&db_path)
.name(*name)
.version("0.1.0")
.output_dir(out_dir.to_str().unwrap())
.compress(false)
.build();
match result {
Ok(pkg) => {
assert!(
!pkg.wheel_name.contains('/'),
"Wheel name for {:?} contains '/': {}",
name,
pkg.wheel_name,
);
assert!(
!pkg.wheel_name.contains('\\'),
"Wheel name for {:?} contains '\\': {}",
name,
pkg.wheel_name,
);
assert!(
!pkg.wheel_name.contains(' '),
"Wheel name for {:?} contains space: {}",
name,
pkg.wheel_name,
);
assert!(
pkg.wheel_path.exists(),
"Wheel file does not exist for name {:?}: {}",
name,
pkg.wheel_path.display(),
);
assert!(
pkg.wheel_name.ends_with("-py3-none-any.whl"),
"Wheel name for {:?} is not PEP 427 compliant: {}",
name,
pkg.wheel_name,
);
}
Err(_) => {
}
}
}
}