{"id":"CVE-2026-102527","revision":null,"records":[{"revision":"e64605d9bf1c43b6b55cc1a0ab5553bf","observedAt":"2026-10-23T15:48:27.903+00:00","statement":{"source":"cve-program","id":"CVE-2026-102527","aliases":[],"title":"Nuxt OG Image cache poisoning through derivable cache keys on unsigned dynamic image routes","description":"Nuxt OG Image generates OG Images with Vue templates in Nuxt. From 6.2.5 until 6.7.0, the dynamic /_og/d/*.png route accepts unsigned requests while resolvePathCacheKey() produces cache keys from the request path, site URL, and normalized rendering options exposed through image URLs and server responses. An unauthenticated attacker can provide attacker-controlled image data through the title parameter together with a derived cacheKey and populate the cache slot used for a legitimate Open Graph image, causing spoofed image content to be served to users. This issue is fixed in version 6.7.0.","state":0,"publishedAt":"2026-10-15T16:55:23.15+00:00","modifiedAt":"2026-10-16T17:13:07.014+00:00","affected":[{"ecosystem":"Vendor product","name":"og-image","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"nuxt-modules\",\n                    \"product\": \"og-image\",\n                    \"versions\": [\n                        {\n                            \"version\": \">= 6.2.5, < 6.7.0\",\n                            \"status\": \"affected\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 4.0","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N","score":6.9,"severity":"MEDIUM"}],"references":["https://github.com/nuxt-modules/og-image/security/advisories/GHSA-2x6f-rp82-ppmj","https://github.com/nuxt-modules/og-image/pull/638","https://github.com/nuxt-modules/og-image/commit/e6c5b53ce7f434ab8cbc91298dccfb2b515c56a5","https://github.com/nuxt-modules/og-image/releases/tag/v6.7.0"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-102527","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-102527","identifiers":["CVE-2026-102527"]},"retained":false,"historicalAffected":[]},{"revision":"fae8ff5ec02b44d8b48a14b894915a19","observedAt":"2026-11-09T05:03:26.881+00:00","statement":{"source":"euvd","id":"EUVD-2026-102199","aliases":["CVE-2026-102527","GHSA-2x6f-rp82-ppmj"],"title":"Nuxt OG Image generates OG Images with Vue templates in Nuxt. From 6.2.5 until 6.7.0, the dynamic /_og/d/*.png route accepts unsigned requests while resolvePathCacheKey() produces cache keys from the request path, site URL, and normalized r…","description":"Nuxt OG Image generates OG Images with Vue templates in Nuxt. From 6.2.5 until 6.7.0, the dynamic /_og/d/*.png route accepts unsigned requests while resolvePathCacheKey() produces cache keys from the request path, site URL, and normalized rendering options exposed through image URLs and server responses. An unauthenticated attacker can provide attacker-controlled image data through the title parameter together with a derived cacheKey and populate the cache slot used for a legitimate Open Graph image, causing spoofed image content to be served to users. This issue is fixed in version 6.7.0.","state":0,"publishedAt":null,"modifiedAt":null,"affected":[],"metrics":[{"system":"EUVD CVSS 4.0","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N","score":6.9,"severity":null}],"references":["https://github.com/nuxt-modules/og-image/security/advisories/GHSA-2x6f-rp82-ppmj","https://github.com/nuxt-modules/og-image/pull/638","https://github.com/nuxt-modules/og-image/commit/e6c5b53ce7f434ab8cbc91298dccfb2b515c56a5","https://github.com/nuxt-modules/og-image/releases/tag/v6.7.0"],"sourceUrl":"https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-102199","license":"ENISA EUVD · source terms and attribution apply","enrichment":{"sourceStatus":null,"weaknesses":[],"productCriteria":[],"sourceDates":{"datePublished":"Oct 15, 2026, 4:55:23 PM","dateUpdated":"Oct 16, 2026, 5:13:07 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-102199","identifiers":["EUVD-2026-102199","CVE-2026-102527","GHSA-2x6f-rp82-ppmj"]},"retained":false,"historicalAffected":[]},{"revision":"0b24119edbbc4d9ab302513b1b86e2ae","observedAt":"2026-10-25T04:17:26.915+00:00","statement":{"source":"nvd","id":"CVE-2026-102527","aliases":[],"title":"Nuxt OG Image generates OG Images with Vue templates in Nuxt. From 6.2.5 until 6.7.0, the dynamic /_og/d/*.png route accepts unsigned requests while resolvePathCacheKey() produces cache keys from the request path, site URL, and normalized r…","description":"Nuxt OG Image generates OG Images with Vue templates in Nuxt. From 6.2.5 until 6.7.0, the dynamic /_og/d/*.png route accepts unsigned requests while resolvePathCacheKey() produces cache keys from the request path, site URL, and normalized rendering options exposed through image URLs and server responses. An unauthenticated attacker can provide attacker-controlled image data through the title parameter together with a derived cacheKey and populate the cache slot used for a legitimate Open Graph image, causing spoofed image content to be served to users. This issue is fixed in version 6.7.0.","state":0,"publishedAt":"2026-10-15T17:17:08.973+00:00","modifiedAt":"2026-10-16T18:17:14.633+00:00","affected":[],"metrics":[{"system":"CVSS 4.0 · security-advisories@github.com · Secondary","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/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":6.9,"severity":"MEDIUM"}],"references":["https://github.com/nuxt-modules/og-image/commit/e6c5b53ce7f434ab8cbc91298dccfb2b515c56a5","https://github.com/nuxt-modules/og-image/pull/638","https://github.com/nuxt-modules/og-image/releases/tag/v6.7.0","https://github.com/nuxt-modules/og-image/security/advisories/GHSA-2x6f-rp82-ppmj"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-102527","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Awaiting Analysis","weaknesses":["CWE-349"],"productCriteria":[],"sourceDates":{"published":"2026-10-15T17:17:08.973","lastModified":"2026-10-16T18:17:14.633"},"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-102527","identifiers":["CVE-2026-102527"]},"retained":false,"historicalAffected":[]},{"revision":"6083ff6f1f304b2a97900bd12d2da4a5","observedAt":"2026-10-24T13:17:17.793+00:00","statement":{"source":"osv","id":"GHSA-2x6f-rp82-ppmj","aliases":["CVE-2026-102527"],"title":"Nuxt OG Image cache poisoning through derivable cache keys on unsigned dynamic image routes","description":"**Vendor:** Nuxt\n**Product:** Nuxt OG Image\n**Version:** 6.2.5\n**Description:** Due to the specifics of caching and key generation in the Open Graph image cache created by the module, an unauthenticated attacker can modify the content of the image (for example, the `title` parameter) that is delivered to the user. \n**Impact:** Content Spoofing\n**Vulnerable component:** route `/_og/d/*.png`\n**Exploitation conditions:** Access to the application\n**Mitigation:** Upgrade to 6.7.2 and set a sufficiently secure `secret` in config `ogImage`\n**Researcher:** Dmitry Vanin (Positive Technologies)\n\n## Research\nDuring [the previous vulnerability research](https://github.com/nuxt-modules/og-image/security/advisories/GHSA-6c86-prf5-hj4h), it was discovered that version 6.2.5 changed the mechanism for generating cache indexes; it now takes into account the parameters passed during image generation.\n\nHowever, the image is still generated from data transmitted to the attacker.\n\n_Listing 1. New code for generating indexes in cache_\n```\nexport function resolvePathCacheKey(e: H3Event, path: string, resolvedOptions?: Record<string, any>) {\n  const siteConfig = getSiteConfig(e, {\n    resolveRefs: true,\n  })\n  const basePath = withoutTrailingSlash(withoutLeadingSlash(normalizeKey(path)))\n  const hashParts: any[] = [\n    basePath,\n    import.meta.prerender ? '' : siteConfig.url,\n  ]\n  // Hash resolved options (not raw query string) so unknown/extra query params\n  // cannot produce unique cache keys and bypass the cache.\n  if (resolvedOptions)\n    hashParts.push(hash(resolvedOptions))\n  return [\n    (!basePath || basePath === '/') ? 'index' : basePath,\n    hash(hashParts),\n  ].join(':')\n}\n```\nIn this case, `basePath` is obtained from the `_path` parameter, `resolvedOptions` are the normalized settings of the component, for example:\n\n_Listing 2. An example of `resolvedOptions`_\n```\n{\"emojis\":\"noto\",\"extension\":\"png\",\"width\":1200,\"height\":600,\"cacheMaxAgeSeconds\":259200,\"component\":\"OgImageDefaultImageTakumi\"}\n```\nFrom the analysis of `resolvedOptions`, it was concluded that, in general, all parameters are known either from the direct link to the OG Image or from the server response.\n\n## Vulnerability reproduction\n\n1. Find the route to OG Image.\n_Figure 1. Demonstration of finding the route to OG Image_\n<img width=\"974\" height=\"361\" alt=\"image\" src=\"https://github.com/user-attachments/assets/d3ee6b54-d545-4a3b-8cbf-f82df99ed4d0\" />\n\n2. Retrieve parameters from the server’s response, especially `cacheMaxAgeSeconds` (`cache-control` header, `s-maxage` key), the other parameters are known from the meta tags as well as from the `c_<component name>` parameter.\n_Figure 2. Obtaining parameters_\n<img width=\"974\" height=\"245\" alt=\"image\" src=\"https://github.com/user-attachments/assets/84a4cd8b-9281-47ef-b524-0047a0f6077a\" />\n\n3. Generate a cache key using a script.\n_Listing 3. Srcipt_\n```\nimport {hash} from \"ohash\";\n\nvar url = \"https://contoso.com\"\n\nvar obj = JSON.parse(`{\"emojis\":\"noto\",\"extension\":\"png\",\"width\":1200,\"height\":600,\"cacheMaxAgeSeconds\":259200,\"component\":\"OgImageBlogPostTakumi\"}`)\n\nvar basePath = '/'\n\nvar hashParts = [\n    basePath,\n    url\n  ]\n  \nif (obj)\n\thashParts.push(hash(obj))\n\nconsole.log([\n    (!basePath || basePath === '/') ? 'index' : basePath,\n    hash(hashParts),\n  ].join(':'))\n```\n4. Repeat the steps as in [the vulnerability 1](https://github.com/nuxt-modules/og-image/security/advisories/GHSA-6c86-prf5-hj4h), but transmit the obtained `cacheKey` in addition.  \n5. Thus, the same result as in [the vulnerability 1](https://github.com/nuxt-modules/og-image/security/advisories/GHSA-6c86-prf5-hj4h) was obtained.\n_Figure 4. Server response_\n<img width=\"974\" height=\"729\" alt=\"image\" src=\"https://github.com/user-attachments/assets/5895c0e8-e497-410d-bef9-f6f2f9649261\" />\n\n## Credits\nResearcher: Dmitry Vanin (Positive Technologies)","state":0,"publishedAt":"2026-10-15T20:15:27+00:00","modifiedAt":"2026-10-15T20:30:08.5729026+00:00","affected":[{"ecosystem":"npm","name":"nuxt-og-image","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"6.2.5"},{"kind":"fixed","version":"6.7.0"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V4","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"MODERATE"}],"references":["https://github.com/nuxt-modules/og-image/security/advisories/GHSA-2x6f-rp82-ppmj","https://nvd.nist.gov/vuln/detail/CVE-2026-102527","https://github.com/nuxt-modules/og-image/pull/638","https://github.com/nuxt-modules/og-image/commit/e6c5b53ce7f434ab8cbc91298dccfb2b515c56a5","https://github.com/nuxt-modules/og-image","https://github.com/nuxt-modules/og-image/releases/tag/v6.7.0"],"sourceUrl":"https://github.com/advisories/GHSA-2x6f-rp82-ppmj","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-2x6f-rp82-ppmj","identifiers":["GHSA-2x6f-rp82-ppmj","CVE-2026-102527"]},"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-09T09:04:02.9162191+00:00","complete":true,"records":1769,"lastAttemptAt":"2026-11-09T09:04:02.9162191+00:00","lastSuccessAt":"2026-11-09T09:04:03.0760313+00:00","error":null,"lastVerifiedAt":"2026-11-09T09:04:03.0760345+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-24e6fde7b744113daefb8f6135035fb8a5c69c9617c9c0d40574a0376532ffd3-0ea295a9c399a04b3ab57ccec2161d0d1cc039ee9ab5c4d8b6299048bd56b277","complete":true,"records":421333,"lastAttemptAt":"2026-11-09T09:02:14.7013141+00:00","lastSuccessAt":"2026-11-09T09:02:14.6291653+00:00","error":null,"lastVerifiedAt":"2026-11-09T09:02:14.7013141+00:00","snapshotPublishedAt":"2026-11-09T08:31:17+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-f975b42a7c2d46f6899c3d764d777217","complete":false,"records":13654,"lastAttemptAt":"2026-11-09T09:16:12.2541949+00:00","lastSuccessAt":"2026-11-09T09:16:12.249+00:00","error":"7 identifier lookups failed; latest failures include HTTP 403. Other identifiers were checked independently.","lastVerifiedAt":"2026-11-09T09:16:12.249+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13699,"expectedIdentifiers":13706,"failedIdentifiers":7},{"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-09T09:04:02.9162191+00:00","complete":true,"records":1096,"lastAttemptAt":"2026-11-09T09:04:02.9162191+00:00","lastSuccessAt":"2026-11-09T09:04:03.197028+00:00","error":null,"lastVerifiedAt":"2026-11-09T09:04:03.1970284+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-156d67f0b09643159ff4bd684ee896db","complete":true,"records":13666,"lastAttemptAt":"2026-11-09T09:04:03.6692263+00:00","lastSuccessAt":"2026-11-09T07:04:26.209+00:00","error":null,"lastVerifiedAt":"2026-11-09T07:04:26.209+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13706,"expectedIdentifiers":13706,"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-980593e6977a6d1b4fb1eed5a1ffe88a468736f89f0a06f710924ad59132c023","complete":true,"records":9914,"lastAttemptAt":"2026-11-09T09:04:02.7750454+00:00","lastSuccessAt":"2026-11-08T11:07:07.068788+00:00","error":null,"lastVerifiedAt":"2026-11-09T09:04:02.7750454+00:00","snapshotPublishedAt":"2026-11-08T11:02: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-fde804134ecdda0ddd5ff5c26ee1fff5a6fa659311f7ef2e51c6ad54964db0e2","complete":true,"records":1971,"lastAttemptAt":"2026-11-09T09:02:14.7586225+00:00","lastSuccessAt":"2026-11-06T19:03:17.0399903+00:00","error":null,"lastVerifiedAt":"2026-11-09T09:02:14.7586225+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-f6d341f4320a5a0c059c28102ee651c3dd06abc87b84d2bafa4e2a823ec07d35","complete":true,"records":3056,"lastAttemptAt":"2026-11-09T09:04:02.8843128+00:00","lastSuccessAt":"2026-11-09T05:02:23.1539412+00:00","error":null,"lastVerifiedAt":"2026-11-09T09:04:02.8843128+00:00","snapshotPublishedAt":"2026-11-09T04:47: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-d0592215f99679f1cc533698c7c7cf50c306057d38021110cecb15015dc78137","complete":true,"records":231297,"lastAttemptAt":"2026-11-09T09:04:02.4970329+00:00","lastSuccessAt":"2026-11-09T09:04:00.7848047+00:00","error":null,"lastVerifiedAt":"2026-11-09T09:04:02.4970329+00:00","snapshotPublishedAt":"2026-11-09T08:33:22+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null}]}