{"record":{"id":"f86c5e2ecadf3633","repo":"SeleniumHQ/selenium","slug":"unsafe-entry-path-traversal","errorCode":null,"errorMessage":"Unsafe entry (path traversal): {:?}","messagePattern":"Unsafe entry \\(path traversal\\): (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"rust/src/files.rs","lineNumber":120,"sourceCode":"pub fn create_path_if_not_exists(path: &Path) -> Result<(), Error> {\n    if !path.exists() {\n        fs::create_dir_all(path)?;\n    }\n    Ok(())\n}\n\npub fn check_path_traversal(entry_path: &Path) -> Result<(), Error> {\n    if entry_path.as_os_str().is_empty()\n        || entry_path.components().any(|c| {\n            matches!(\n                c,\n                std::path::Component::ParentDir\n                    | std::path::Component::RootDir\n                    | std::path::Component::Prefix(_)\n            )\n        })\n    {\n        return Err(anyhow!(\"Unsafe entry (path traversal): {:?}\", entry_path));\n    }\n    Ok(())\n}\n\npub fn uncompress(\n    compressed_file: &str,\n    target: &Path,\n    log: &Logger,\n    os: &str,\n    single_file: Option<String>,\n    volume: Option<&str>,\n) -> Result<(), Error> {\n    let mut extension = match infer::get_from_path(compressed_file)? {\n        Some(kind) => kind.extension(),\n        _ => {\n            if compressed_file.ends_with(PKG) || compressed_file.ends_with(DMG) {\n                if MACOS.is(os) {\n                    PKG","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/SeleniumHQ/selenium/blob/aa36b38e696a0909e973bdf5e2f9031ffe842c4b/rust/src/files.rs#L102-L138","documentation":"Returned by check_path_traversal() in rust/src/files.rs when an archive entry's path is empty or contains a ParentDir (..), RootDir (/ or \\), or Windows Prefix component. This is the zip-slip / tar-slip defense: it prevents a malicious or malformed archive from writing outside the target directory during decompression. It is called for every entry before extraction.","triggerScenarios":"uncompress/unzip iterates archive entries and calls check_path_traversal(entry_path) on each. Any entry whose components include .. or an absolute root triggers the error before the file is written. Also fires on an empty path string.","commonSituations":"A downloaded driver archive (zip/tar) contains an entry like ../../etc/cron.d/x; a macOS .pkg Payload cpio entry has an absolute path; a corrupted archive produces a garbage entry path; a mirror serves a tampered archive.","solutions":["Do not bypass this check; instead verify the archive's source and integrity (sha256) before trusting it.","Re-download the driver from the official endpoint to replace a possibly tampered archive.","If the archive is legitimately structured with absolute paths, extract it manually in a sandbox and copy the needed binary.","Report the upstream package if a legitimate driver ships a traversal entry."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Rust: verify entry path is safe before extraction (mirrors the library check)\nfn is_safe_entry(p: &Path) -> bool {\n    !p.as_os_str().is_empty() && !p.components().any(|c| matches!(c,\n        std::path::Component::ParentDir | std::path::Component::RootDir\n        | std::path::Component::Prefix(_)))\n}","typeGuard":null,"tryCatchPattern":"// Callers typically cannot catch inside Selenium Manager; validate archives pre-download:\n// 1. Verify sha256 of the downloaded archive against the published checksum.\n// 2. Scan the archive's entry list with `unzip -l` / `tar -tf` before trusting.\n// (Internal Rust callers can use check_path_traversal directly.)","preventionTips":["Always verify the archive's sha256 against the published checksum before extraction.","Download drivers only from official endpoints to avoid tampered archives.","Keep the path-traversal check enabled; never bypass it."],"tags":["rust","selenium-manager","security","archive","path-traversal","zip-slip"],"backgroundTag":null,"analyzedSha":"aa36b38e696a0909e973bdf5e2f9031ffe842c4b","analyzedAt":"2026-08-14T02:32:32.244Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}