Action not permitted
Modal body text goes here.
Modal Title
Modal Body
Vulnerability from cleanstart
Package langfuse-worker version 3.224.0-r1 fixes 25 vulnerabilities: ghsa-p63j-vcc4-9vmv, ghsa-55q2-fjhq-7xh7, ghsa-c2j3-45gr-mqc4, CVE-2026-69192, CVE-2026-54272...
| URL | Type | |
|---|---|---|
{
"affected": [
{
"package": {
"ecosystem": "CleanStart",
"name": "langfuse-worker"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.224.0-r1"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"3.224.0-r1"
]
}
],
"credits": [],
"database_specific": {},
"details": "Package langfuse-worker version 3.224.0-r1 fixes 25 vulnerabilities: ghsa-p63j-vcc4-9vmv, ghsa-55q2-fjhq-7xh7, ghsa-c2j3-45gr-mqc4, CVE-2026-69192, CVE-2026-54272...",
"id": "CLEANSTART-2026-TC75125",
"modified": "2026-09-04T11:14:10Z",
"published": "2026-09-01T11:17:16Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/langfuse/langfuse"
}
],
"related": [],
"schema_version": "1.7.3",
"summary": "Security fixes in langfuse-worker 3.224.0-r1",
"upstream": [
"ghsa-p63j-vcc4-9vmv",
"ghsa-55q2-fjhq-7xh7",
"ghsa-c2j3-45gr-mqc4",
"CVE-2026-69192",
"CVE-2026-54272",
"CVE-2026-69198",
"ghsa-5p4m-2wfm-xmqj",
"CVE-2026-50159",
"CVE-2026-71436",
"CVE-2026-71437",
"CVE-2026-71439",
"CVE-2026-71438",
"CVE-2026-67213",
"CVE-2026-67214",
"ghsa-7rqj-j65f-68wh",
"ghsa-xmf8-cvqr-rfgj",
"ghsa-x445-f3h2-j279",
"ghsa-r28c-9q8g-f849",
"CVE-2026-69153",
"ghsa-f88m-g3jw-g9cj",
"CVE-2026-13697",
"CVE-2026-14643",
"CVE-2026-15157",
"CVE-2026-16728",
"CVE-2026-16729"
]
}
GHSA-F88M-G3JW-G9CJ
Vulnerability from github – Published: 2026-07-21 22:07 – Updated: 2026-07-21 22:07Impact
A number of vulnerabilities, two rated as "High" severity using CVSSv4, have been discovered and fixed in the upstream libvips dependency.
Those processing untrusted input with versions of sharp prior to 0.35.0 are affected.
Patches
Using prebuilt binaries provided by sharp?
Most people rely on the prebuilt binaries provided by sharp.
Please upgrade sharp to the latest version, currently 0.35.3, which provides libvips 8.18.3.
Using a globally-installed libvips?
Please ensure you are using the latest libvips 8.18.3.
Workarounds
Add the following to your code to prevent sharp from decoding GIF, TIFF and VIPS images.
sharp.block({ operation: ["VipsForeignLoadNsgif", "VipsForeignLoadTiff", "VipsForeignLoadVips"] });
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "sharp"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.35.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-1395"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-21T22:07:17Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "### Impact\n\nA number of vulnerabilities, two rated as \"High\" severity using CVSSv4, have been discovered and fixed in the upstream libvips dependency.\n\nThose processing untrusted input with versions of sharp prior to 0.35.0 are affected.\n\n### Patches\n\n#### Using prebuilt binaries provided by sharp?\n\nMost people rely on the prebuilt binaries provided by sharp.\n\nPlease upgrade sharp to the latest version, currently 0.35.3, which provides libvips 8.18.3.\n\n#### Using a globally-installed libvips?\n\nPlease ensure you are using the latest libvips 8.18.3.\n\n### Workarounds\nAdd the following to your code to prevent sharp from decoding GIF, TIFF and VIPS images.\n```js\nsharp.block({ operation: [\"VipsForeignLoadNsgif\", \"VipsForeignLoadTiff\", \"VipsForeignLoadVips\"] });\n```",
"id": "GHSA-f88m-g3jw-g9cj",
"modified": "2026-07-21T22:07:17Z",
"published": "2026-07-21T22:07:17Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/libvips/libvips/security/advisories/GHSA-2fcj-gj27-279x"
},
{
"type": "WEB",
"url": "https://github.com/libvips/libvips/security/advisories/GHSA-523x-vhfw-6r76"
},
{
"type": "WEB",
"url": "https://github.com/libvips/libvips/security/advisories/GHSA-jmwm-wc68-mhwm"
},
{
"type": "WEB",
"url": "https://github.com/libvips/libvips/security/advisories/GHSA-r98w-4fp7-m9c7"
},
{
"type": "WEB",
"url": "https://github.com/lovell/sharp/security/advisories/GHSA-f88m-g3jw-g9cj"
},
{
"type": "PACKAGE",
"url": "https://github.com/lovell/sharp"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:N/VC:L/VI:H/VA:H/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "sharp inherited vulnerabilities in libvips: CVE-2026-33327, CVE-2026-33328, CVE-2026-35590, CVE-2026-35591"
}
GHSA-P63J-VCC4-9VMV
Vulnerability from github – Published: 2026-07-21 19:36 – Updated: 2026-08-13 18:19Summary
Browser Mode exposes a set of built-in "commands" that run on the Node.js side of the test runner and can touch the local filesystem (taking screenshots, managing Playwright traces, uploading files for <input type="file">, comparing screenshots).
Several of these commands accept a file path from the browser and act on it without checking the allowWrite permission gate and without confining the path to the project directory. A client that can reach the Browser Mode API can therefore read, create, overwrite, or delete files anywhere the Vitest process can access, even when allowWrite is false.
This matters most when the Browser Mode API is exposed to the network (for example test.api.host is set, or the dev server is reachable from another machine or origin). In that configuration allowWrite defaults to false precisely to block file access, and these commands bypass that protection. On a default localhost-only setup with trusted test code, there is no untrusted party in a position to exploit it. The gap still matters wherever you rely on allowWrite: false to contain untrusted test code, because these commands ignore that flag.
Affected commands and impact
| Command | Operation | Impact |
|---|---|---|
upload (Playwright + WebdriverIO) |
Read | Arbitrary local file read; contents are loaded into the page and readable by test code. Highest-impact case. |
takeScreenshot (Playwright + WebdriverIO) |
Write | Writes a PNG to an arbitrary path (absolute path used verbatim), creating parent directories. |
screenshotMatcher |
Write | Writes reference/diff PNGs; directory derived from client path allows partial traversal. |
stopChunkTrace |
Write | Writes a Playwright trace .zip to a path escapable via ../ in the trace name. |
deleteTracing |
Delete | Deletes arbitrary files by path. |
annotateTraces |
Read (disclosure) | Records a client-controlled attachment path that the reporter copies into the attachments directory, disclosing file contents. |
The writes do not let an attacker choose the file contents (they produce PNG images or trace archives), so the integrity impact is creating, overwriting, or deleting a file at an arbitrary path rather than writing a chosen payload. The reads (upload, annotateTraces) are more serious because they expose the full contents of an arbitrary file.
The fix adds, to every file-touching provider command, an allowWrite check for write/delete operations and path confinement to the project root (matching the existing fs command pattern), so client-supplied absolute paths and ../ traversal are rejected.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "@vitest/browser"
},
"ranges": [
{
"events": [
{
"introduced": "4.0.0"
},
{
"fixed": "4.1.10"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "@vitest/browser"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.2.7"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "@vitest/browser"
},
"ranges": [
{
"events": [
{
"introduced": "5.0.0-beta.1"
},
{
"fixed": "5.0.0-beta.6"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-73653"
],
"database_specific": {
"cwe_ids": [
"CWE-22",
"CWE-552",
"CWE-862"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-21T19:36:12Z",
"nvd_published_at": null,
"severity": "CRITICAL"
},
"details": "## Summary\n\nBrowser Mode exposes a set of built-in \"commands\" that run on the Node.js side of the test runner and can touch the local filesystem (taking screenshots, managing Playwright traces, uploading files for `\u003cinput type=\"file\"\u003e`, comparing screenshots).\n\nSeveral of these commands accept a file path from the browser and act on it without checking the `allowWrite` permission gate and without confining the path to the project directory. A client that can reach the Browser Mode API can therefore read, create, overwrite, or delete files anywhere the Vitest process can access, even when `allowWrite` is `false`.\n\nThis matters most when the Browser Mode API is exposed to the network (for example `test.api.host` is set, or the dev server is reachable from another machine or origin). In that configuration `allowWrite` defaults to `false` precisely to block file access, and these commands bypass that protection. On a default localhost-only setup with trusted test code, there is no untrusted party in a position to exploit it. The gap still matters wherever you rely on `allowWrite: false` to contain untrusted test code, because these commands ignore that flag.\n\n## Affected commands and impact\n\n| Command | Operation | Impact |\n|---|---|---|\n| `upload` (Playwright + WebdriverIO) | Read | Arbitrary local file read; contents are loaded into the page and readable by test code. Highest-impact case. |\n| `takeScreenshot` (Playwright + WebdriverIO) | Write | Writes a PNG to an arbitrary path (absolute path used verbatim), creating parent directories. |\n| `screenshotMatcher` | Write | Writes reference/diff PNGs; directory derived from client path allows partial traversal. |\n| `stopChunkTrace` | Write | Writes a Playwright trace `.zip` to a path escapable via `../` in the trace name. |\n| `deleteTracing` | Delete | Deletes arbitrary files by path. |\n| `annotateTraces` | Read (disclosure) | Records a client-controlled attachment path that the reporter copies into the attachments directory, disclosing file contents. |\n\nThe writes do not let an attacker choose the file contents (they produce PNG images or trace archives), so the integrity impact is creating, overwriting, or deleting a file at an arbitrary path rather than writing a chosen payload. The reads (`upload`, `annotateTraces`) are more serious because they expose the full contents of an arbitrary file.\n\nThe fix adds, to every file-touching provider command, an `allowWrite` check for write/delete operations and path confinement to the project root (matching the existing `fs` command pattern), so client-supplied absolute paths and `../` traversal are rejected.",
"id": "GHSA-p63j-vcc4-9vmv",
"modified": "2026-08-13T18:19:12Z",
"published": "2026-07-21T19:36:12Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/vitest-dev/vitest/security/advisories/GHSA-p63j-vcc4-9vmv"
},
{
"type": "WEB",
"url": "https://github.com/vitest-dev/vitest/pull/10674"
},
{
"type": "WEB",
"url": "https://github.com/vitest-dev/vitest/pull/10679"
},
{
"type": "WEB",
"url": "https://github.com/vitest-dev/vitest/pull/10680"
},
{
"type": "WEB",
"url": "https://github.com/vitest-dev/vitest/commit/33f96a145ef09ca6a43b4e555eb273e64a87be23"
},
{
"type": "WEB",
"url": "https://github.com/vitest-dev/vitest/commit/5c18dd267ff7f47f24cab2f615a16b37d90feb7f"
},
{
"type": "WEB",
"url": "https://github.com/vitest-dev/vitest/commit/b795e36b34969bec50b47a9f29d26f799a6a04fb"
},
{
"type": "PACKAGE",
"url": "https://github.com/vitest-dev/vitest"
},
{
"type": "WEB",
"url": "https://github.com/vitest-dev/vitest/releases/tag/v3.2.7"
},
{
"type": "WEB",
"url": "https://github.com/vitest-dev/vitest/releases/tag/v4.1.10"
},
{
"type": "WEB",
"url": "https://github.com/vitest-dev/vitest/releases/tag/v5.0.0-beta.6"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L",
"type": "CVSS_V3"
}
],
"summary": "@vitest/browser: Browser Mode provider commands bypass the file-access permission gate"
}
GHSA-R28C-9Q8G-F849
Vulnerability from github – Published: 2026-07-24 16:24 – Updated: 2026-08-13 17:55Vulnerability Details
File: lib/previous-map.js
Line: 87-98 (loadFile), 129-144 (loadMap)
Root Cause
PostCSS auto-detects a /*# sourceMappingURL=... */ comment inside the CSS text it is asked to parse and, unless the caller explicitly passes map: false, attempts to load that path from disk as a "previous source map." This happens on every postcss.parse() / postcss().process() call by default (opt-out, not opt-in).
loadMap() builds the candidate path via join(dirname(opts.from), annotation), where annotation is the raw, attacker-controlled string from the CSS comment. path.join() normalizes but does not sandbox .. segments, so a ../../../ prefix walks the resolved path outside the intended directory. If opts.from is not set at all, the annotation is used completely unmodified — an absolute path in the CSS comment is read verbatim.
8.5.12 already fixed a strictly worse variant of this (any file, any extension, could be read) by requiring the resolved path to end in .map (loadFile()). That fix did not address the traversal itself, only the target extension. Since the join(dirname(file), map) logic has existed unchanged since PostCSS 8.0.0 (Feb 2020), any file ending in .map remains readable through this path in the current release (8.5.16).
Once loaded, MapGenerator.isMap() treats the mere presence of a loaded "previous map" as an implicit request to generate result.map, even when the caller never set the map option. If the loaded map has a sourcesContent field (common for maps emitted by bundlers/transpilers), that content is merged into result.map and returned to the caller — disclosing the traversed-to file's content to whoever supplied the CSS.
Attack Scenario
- A service accepts user-submitted CSS and runs it through PostCSS to lint/format/transform it, e.g.
postcss().process(userCss, { from: '/app/uploads/user123/input.css', to: '/app/uploads/user123/output.css' })— idiomatic usage;mapoption untouched. - Attacker submits CSS containing
/*# sourceMappingURL=../../../../some/other/app/dist/bundle.js.map */(or an absolute path iffromis unset). - PostCSS reads that
.mapfile and folds itssourcesContentintoresult.map. - The service does what most build pipelines do with a truthy
result.map— writes it next to the CSS output or returns it via API (source maps are meant to be consumed by browser devtools, so this is commonly public/served). - Attacker retrieves the emitted map and reads out the traversed file's content.
Impact
Disclosure of the contents of arbitrary .map files reachable via path traversal (or absolute path when from is unset) from the process's filesystem. Affects any application processing CSS it does not fully trust without explicitly passing map: false. No authentication or user interaction beyond submitting CSS text is required.
Vulnerable Code
loadFile(path, cssFile, trusted) {
if (!trusted && !this.unsafeMap) {
if (!/\.map$/i.test(path)) {
return undefined
}
}
this.root = dirname(path)
if (existsSync(path)) {
this.mapFile = path
return readFileSync(path, 'utf-8').toString().trim()
}
}
loadMap(file, prev) {
...
} else if (this.annotation) {
let map = this.annotation
if (file) map = join(dirname(file), map)
let unknown = this.loadFile(map, file, false)
...
}
}
Recommended Fix
Constrain the resolved path to remain inside the CSS file's own directory instead of relying solely on a filename-extension check:
loadFile(path, cssFile, trusted) {
if (!trusted && !this.unsafeMap) {
if (!/\.map$/i.test(path)) {
return undefined
}
if (!cssFile) return undefined
let root = resolve(dirname(cssFile))
let resolvedPath = resolve(root, path)
if (resolvedPath !== root && !resolvedPath.startsWith(root + sep)) {
return undefined
}
}
this.root = dirname(path)
if (existsSync(path)) {
this.mapFile = path
return readFileSync(path, 'utf-8').toString().trim()
}
}
I've implemented, tested (full existing test suite — 660/660 passing, plus new PoC-based regression checks for both the traversal and legitimate same-directory cases), and can share this fix on request or via a private fork if invited.
Verification
Dynamically confirmed on v8.5.16 (current npm release / repo HEAD) via a standalone Node.js harness against lib/postcss.js: a "secret" .map file placed two directories outside a simulated project directory was read via a crafted sourceMappingURL comment in otherwise-innocuous CSS, with its sourcesContent appearing verbatim in result.map.toString() — with no map option set by the caller. A second harness confirmed the simpler no-from case reads an absolute path directly. A third harness confirmed map: false is the only current workaround. The attached fix branch closes both vectors while keeping all 660 existing unit tests green.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 8.5.17"
},
"package": {
"ecosystem": "npm",
"name": "postcss"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "8.5.18"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-73646"
],
"database_specific": {
"cwe_ids": [
"CWE-22"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-24T16:24:55Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "## Vulnerability Details\n\n**File**: `lib/previous-map.js`\n**Line**: 87-98 (`loadFile`), 129-144 (`loadMap`)\n\n\n### Root Cause\nPostCSS auto-detects a `/*# sourceMappingURL=... */` comment inside the CSS text it is asked to parse and, unless the caller explicitly passes `map: false`, attempts to load that path from disk as a \"previous source map.\" This happens on every `postcss.parse()` / `postcss().process()` call by default (opt-out, not opt-in).\n\n`loadMap()` builds the candidate path via `join(dirname(opts.from), annotation)`, where `annotation` is the raw, attacker-controlled string from the CSS comment. `path.join()` normalizes but does not sandbox `..` segments, so a `../../../` prefix walks the resolved path outside the intended directory. If `opts.from` is not set at all, the annotation is used completely unmodified \u2014 an absolute path in the CSS comment is read verbatim.\n\n8.5.12 already fixed a strictly worse variant of this (any file, any extension, could be read) by requiring the resolved path to end in `.map` (`loadFile()`). That fix did not address the traversal itself, only the target extension. Since the `join(dirname(file), map)` logic has existed unchanged since PostCSS 8.0.0 (Feb 2020), any file ending in `.map` remains readable through this path in the current release (8.5.16).\n\nOnce loaded, `MapGenerator.isMap()` treats the mere presence of a loaded \"previous map\" as an implicit request to generate `result.map`, even when the caller never set the `map` option. If the loaded map has a `sourcesContent` field (common for maps emitted by bundlers/transpilers), that content is merged into `result.map` and returned to the caller \u2014 disclosing the traversed-to file\u0027s content to whoever supplied the CSS.\n\n### Attack Scenario\n1. A service accepts user-submitted CSS and runs it through PostCSS to lint/format/transform it, e.g. `postcss().process(userCss, { from: \u0027/app/uploads/user123/input.css\u0027, to: \u0027/app/uploads/user123/output.css\u0027 })` \u2014 idiomatic usage; `map` option untouched.\n2. Attacker submits CSS containing `/*# sourceMappingURL=../../../../some/other/app/dist/bundle.js.map */` (or an absolute path if `from` is unset).\n3. PostCSS reads that `.map` file and folds its `sourcesContent` into `result.map`.\n4. The service does what most build pipelines do with a truthy `result.map` \u2014 writes it next to the CSS output or returns it via API (source maps are meant to be consumed by browser devtools, so this is commonly public/served).\n5. Attacker retrieves the emitted map and reads out the traversed file\u0027s content.\n\n### Impact\nDisclosure of the contents of arbitrary `.map` files reachable via path traversal (or absolute path when `from` is unset) from the process\u0027s filesystem. Affects any application processing CSS it does not fully trust without explicitly passing `map: false`. No authentication or user interaction beyond submitting CSS text is required.\n\n### Vulnerable Code\n```js\nloadFile(path, cssFile, trusted) {\n if (!trusted \u0026\u0026 !this.unsafeMap) {\n if (!/\\.map$/i.test(path)) {\n return undefined\n }\n }\n this.root = dirname(path)\n if (existsSync(path)) {\n this.mapFile = path\n return readFileSync(path, \u0027utf-8\u0027).toString().trim()\n }\n}\n\nloadMap(file, prev) {\n ...\n } else if (this.annotation) {\n let map = this.annotation\n if (file) map = join(dirname(file), map)\n let unknown = this.loadFile(map, file, false)\n ...\n }\n}\n```\n\n### Recommended Fix\nConstrain the resolved path to remain inside the CSS file\u0027s own directory instead of relying solely on a filename-extension check:\n```js\nloadFile(path, cssFile, trusted) {\n if (!trusted \u0026\u0026 !this.unsafeMap) {\n if (!/\\.map$/i.test(path)) {\n return undefined\n }\n if (!cssFile) return undefined\n let root = resolve(dirname(cssFile))\n let resolvedPath = resolve(root, path)\n if (resolvedPath !== root \u0026\u0026 !resolvedPath.startsWith(root + sep)) {\n return undefined\n }\n }\n this.root = dirname(path)\n if (existsSync(path)) {\n this.mapFile = path\n return readFileSync(path, \u0027utf-8\u0027).toString().trim()\n }\n}\n```\nI\u0027ve implemented, tested (full existing test suite \u2014 660/660 passing, plus new PoC-based regression checks for both the traversal and legitimate same-directory cases), and can share this fix on request or via a private fork if invited.\n\n### Verification\nDynamically confirmed on v8.5.16 (current npm release / repo HEAD) via a standalone Node.js harness against `lib/postcss.js`: a \"secret\" `.map` file placed two directories outside a simulated project directory was read via a crafted `sourceMappingURL` comment in otherwise-innocuous CSS, with its `sourcesContent` appearing verbatim in `result.map.toString()` \u2014 with no `map` option set by the caller. A second harness confirmed the simpler no-`from` case reads an absolute path directly. A third harness confirmed `map: false` is the only current workaround. The attached fix branch closes both vectors while keeping all 660 existing unit tests green.",
"id": "GHSA-r28c-9q8g-f849",
"modified": "2026-08-13T17:55:54Z",
"published": "2026-07-24T16:24:55Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/postcss/postcss/security/advisories/GHSA-r28c-9q8g-f849"
},
{
"type": "WEB",
"url": "https://github.com/postcss/postcss/commit/95663d3eb7ba26f4854dd19d3b4f4425760cf56c"
},
{
"type": "PACKAGE",
"url": "https://github.com/postcss/postcss"
},
{
"type": "WEB",
"url": "https://github.com/postcss/postcss/releases/tag/8.5.18"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "PostCSS: Path Traversal in Previous Source Map Auto-Loading (sourceMappingURL) leads to Arbitrary .map File Disclosure"
}
GHSA-X445-F3H2-J279
Vulnerability from github – Published: 2026-07-23 14:31 – Updated: 2026-08-13 19:05Summary
Auth.js stores the OAuth/OIDC anti-CSRF checks (state, nonce, and the PKCE verifier) in global cookies that are not bound to the provider that created them. On callback, a check value minted during a sign-in started with one provider can satisfy the callback for a different provider, because the stored cookie is not verified against the callback provider's identity (provider id, issuer, client id, or redirect URI). In a multi-provider app that allows account linking while logged in, this provider-confusion / mix-up condition can let an attacker link their account at a second provider to a victim's user.
Am I affected?
You may be affected if all of the following hold:
- You use
next-auth<= 4.24.14or>= 5.0.0-beta.1, <= 5.0.0-beta.31, or@auth/core<= 0.41.2. - You configure multiple OAuth/OIDC providers.
- You allow users to link additional providers while logged in.
- At least one configured provider's authorization request is observable by an attacker, and at least one target provider's callback can be satisfied without a PKCE verifier (i.e. it relies only on
stateor only onnonce).
You are not affected if you use a single OAuth provider, do not allow logged-in account linking, or all providers enforce PKCE.
Impact
- Account-linking confusion: an attacker can get their account at a target provider linked to the victim's Auth.js user, granting the attacker persistent sign-in to the victim's account through that linked provider.
- Exploitation requires luring the victim into starting a legitimate same-origin flow; it cannot be performed by cross-site request forgery alone, which reduces practical likelihood.
Patched version
The fix binds the OAuth check cookies to the provider/authorization flow that created them, so a callback cannot consume a check value minted for a different provider. Upgrade to the first releases containing this fix (pending; this advisory will be updated with exact patched versions before publication).
Workarounds
If you cannot upgrade immediately:
- Enable PKCE (
checks: ["pkce"], in addition tostate/nonce) on every provider that supports it; PKCE blocks the practical code-swap variant because the attacker cannot observe the relying party's verifier. - Avoid offering logged-in account linking across multiple providers where one provider is lower-trust or attacker-observable.
- Treat
events.linkAccountas sensitive: add audit logging, user notification, or out-of-band confirmation so that any unexpected link is visible (defense-in-depth, not a root-cause fix).
Credit
Reported by @Nadav0077. Thank you for the responsible disclosure.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 0.41.2"
},
"package": {
"ecosystem": "npm",
"name": "@auth/core"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.41.3"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 5.0.0-beta.31"
},
"package": {
"ecosystem": "npm",
"name": "next-auth"
},
"ranges": [
{
"events": [
{
"introduced": "5.0.0-beta.1"
},
{
"fixed": "5.0.0-beta.32"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.24.14"
},
"package": {
"ecosystem": "npm",
"name": "next-auth"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "4.24.15"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-73419"
],
"database_specific": {
"cwe_ids": [
"CWE-345",
"CWE-346",
"CWE-940"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-23T14:31:51Z",
"nvd_published_at": "2026-08-12T21:17:41Z",
"severity": "MODERATE"
},
"details": "## Summary\n\nAuth.js stores the OAuth/OIDC anti-CSRF checks (`state`, `nonce`, and the PKCE verifier) in global cookies that are not bound to the provider that created them. On callback, a check value minted during a sign-in started with one provider can satisfy the callback for a different provider, because the stored cookie is not verified against the callback provider\u0027s identity (provider id, issuer, client id, or redirect URI). In a multi-provider app that allows account linking while logged in, this provider-confusion / mix-up condition can let an attacker link their account at a second provider to a victim\u0027s user.\n\n## Am I affected?\n\nYou may be affected if **all** of the following hold:\n\n- You use `next-auth` `\u003c= 4.24.14` or `\u003e= 5.0.0-beta.1, \u003c= 5.0.0-beta.31`, or `@auth/core` `\u003c= 0.41.2`.\n- You configure multiple OAuth/OIDC providers.\n- You allow users to link additional providers while logged in.\n- At least one configured provider\u0027s authorization request is observable by an attacker, and at least one target provider\u0027s callback can be satisfied without a PKCE verifier (i.e. it relies only on `state` or only on `nonce`).\n\nYou are **not** affected if you use a single OAuth provider, do not allow logged-in account linking, or all providers enforce PKCE.\n\n## Impact\n\n- Account-linking confusion: an attacker can get their account at a target provider linked to the victim\u0027s Auth.js user, granting the attacker persistent sign-in to the victim\u0027s account through that linked provider.\n- Exploitation requires luring the victim into starting a legitimate same-origin flow; it cannot be performed by cross-site request forgery alone, which reduces practical likelihood.\n\n## Patched version\n\nThe fix binds the OAuth check cookies to the provider/authorization flow that created them, so a callback cannot consume a check value minted for a different provider. Upgrade to the first releases containing this fix (pending; this advisory will be updated with exact patched versions before publication).\n\n## Workarounds\n\nIf you cannot upgrade immediately:\n\n- Enable PKCE (`checks: [\"pkce\"]`, in addition to `state`/`nonce`) on every provider that supports it; PKCE blocks the practical code-swap variant because the attacker cannot observe the relying party\u0027s verifier.\n- Avoid offering logged-in account linking across multiple providers where one provider is lower-trust or attacker-observable.\n- Treat `events.linkAccount` as sensitive: add audit logging, user notification, or out-of-band confirmation so that any unexpected link is visible (defense-in-depth, not a root-cause fix).\n\n## Credit\n\nReported by @Nadav0077. Thank you for the responsible disclosure.",
"id": "GHSA-x445-f3h2-j279",
"modified": "2026-08-13T19:05:32Z",
"published": "2026-07-23T14:31:51Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/nextauthjs/next-auth/security/advisories/GHSA-x445-f3h2-j279"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-73419"
},
{
"type": "WEB",
"url": "https://github.com/nextauthjs/next-auth/pull/13469"
},
{
"type": "WEB",
"url": "https://github.com/nextauthjs/next-auth/commit/5bca2399a79ba8d116ca5179b4b1ebcd152e7f05"
},
{
"type": "WEB",
"url": "https://github.com/nextauthjs/next-auth/commit/9f7a97fade9b1319bb9ac19fc9828d62e0a2a852"
},
{
"type": "PACKAGE",
"url": "https://github.com/nextauthjs/next-auth"
},
{
"type": "WEB",
"url": "https://github.com/nextauthjs/next-auth/releases/tag/@auth/core@0.41.3"
},
{
"type": "WEB",
"url": "https://github.com/nextauthjs/next-auth/releases/tag/next-auth@4.24.15"
},
{
"type": "WEB",
"url": "https://github.com/nextauthjs/next-auth/releases/tag/next-auth@5.0.0-beta.32"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "Auth.js: OAuth state, nonce, and PKCE check cookies are not bound to the provider that created them"
}
GHSA-XMF8-CVQR-RFGJ
Vulnerability from github – Published: 2026-07-23 14:42 – Updated: 2026-08-13 19:05Summary
The exported getToken() helper (next-auth/jwt and @auth/core/jwt) can throw an uncaught exception when it reads a malformed Authorization: Bearer … header. When no session cookie is present, getToken() URL-decodes the bearer value before validating it, and malformed percent-encoding causes the decode step to throw rather than being treated as an invalid token. Because getToken() is commonly called in API routes, middleware, and other request handlers, a single unauthenticated request can trigger an unhandled exception in code paths that authenticate requests.
Am I affected?
You are affected if all of the following hold:
- You use
next-auth<= 5.0.0-beta.25(or@auth/coreexposing the samegetToken()implementation). - Your application calls
getToken()directly — for example in a Route Handler, middleware, or server-side request handler. - You do not wrap that
getToken()call in your owntry/catch.
You are not affected if you only use the framework's auth() helper and never call getToken() yourself, or if every getToken() call site already has its own exception handling.
Impact
- Denial of service: an unauthenticated request carrying a malformed Bearer authorization header can raise an unhandled exception in any handler that calls
getToken(). - The impact is per-request and limited to availability; it does not expose tokens, sessions, or other data, and does not bypass authentication.
CWE-20: Improper Input Validation.
Patched version
The fix makes getToken() treat a malformed Bearer value as an invalid token and return null, matching how other undecodable tokens are already handled. Upgrade to the first release containing this fix (to be published; this advisory will be updated with the exact patched version before publication) and no code changes are required.
Workarounds
If you cannot upgrade immediately, either:
- Config/code-level: wrap your
getToken()calls so a thrown error is treated as "no token", e.g.
ts
let token = null
try {
token = await getToken({ req, secret })
} catch {
token = null
}
- Or strip/normalize the incoming
Authorizationheader at the edge (proxy, middleware) before it reachesgetToken(), rejecting values whose Bearer portion is not valid percent-encoding.
Credit
Reported by @deprrous. Thank you for the responsible disclosure.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "@auth/core"
},
"ranges": [
{
"events": [
{
"introduced": "0.1.0"
},
{
"fixed": "0.41.3"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 5.0.0-beta.31"
},
"package": {
"ecosystem": "npm",
"name": "next-auth"
},
"ranges": [
{
"events": [
{
"introduced": "5.0.0-beta.0"
},
{
"fixed": "5.0.0-beta.32"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.24.14"
},
"package": {
"ecosystem": "npm",
"name": "next-auth"
},
"ranges": [
{
"events": [
{
"introduced": "4.0.6"
},
{
"fixed": "4.24.15"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-73418"
],
"database_specific": {
"cwe_ids": [
"CWE-20"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-23T14:42:55Z",
"nvd_published_at": "2026-08-12T21:17:40Z",
"severity": "HIGH"
},
"details": "## Summary\n\nThe exported `getToken()` helper (`next-auth/jwt` and `@auth/core/jwt`) can throw an uncaught exception when it reads a malformed `Authorization: Bearer \u2026` header. When no session cookie is present, `getToken()` URL-decodes the bearer value before validating it, and malformed percent-encoding causes the decode step to throw rather than being treated as an invalid token. Because `getToken()` is commonly called in API routes, middleware, and other request handlers, a single unauthenticated request can trigger an unhandled exception in code paths that authenticate requests.\n\n## Am I affected?\n\nYou are affected if **all** of the following hold:\n\n- You use `next-auth` `\u003c= 5.0.0-beta.25` (or `@auth/core` exposing the same `getToken()` implementation).\n- Your application calls `getToken()` directly \u2014 for example in a Route Handler, middleware, or server-side request handler.\n- You do not wrap that `getToken()` call in your own `try/catch`.\n\nYou are **not** affected if you only use the framework\u0027s `auth()` helper and never call `getToken()` yourself, or if every `getToken()` call site already has its own exception handling.\n\n## Impact\n\n- Denial of service: an unauthenticated request carrying a malformed Bearer authorization header can raise an unhandled exception in any handler that calls `getToken()`.\n- The impact is per-request and limited to availability; it does not expose tokens, sessions, or other data, and does not bypass authentication.\n\nCWE-20: Improper Input Validation.\n\n## Patched version\n\nThe fix makes `getToken()` treat a malformed Bearer value as an invalid token and return `null`, matching how other undecodable tokens are already handled. Upgrade to the first release containing this fix (to be published; this advisory will be updated with the exact patched version before publication) and no code changes are required.\n\n## Workarounds\n\nIf you cannot upgrade immediately, either:\n\n- **Config/code-level:** wrap your `getToken()` calls so a thrown error is treated as \"no token\", e.g.\n\n ```ts\n let token = null\n try {\n token = await getToken({ req, secret })\n } catch {\n token = null\n }\n ```\n\n- Or strip/normalize the incoming `Authorization` header at the edge (proxy, middleware) before it reaches `getToken()`, rejecting values whose Bearer portion is not valid percent-encoding.\n\n## Credit\n\nReported by @deprrous. Thank you for the responsible disclosure.",
"id": "GHSA-xmf8-cvqr-rfgj",
"modified": "2026-08-13T19:05:18Z",
"published": "2026-07-23T14:42:55Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/nextauthjs/next-auth/security/advisories/GHSA-xmf8-cvqr-rfgj"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-73418"
},
{
"type": "WEB",
"url": "https://github.com/nextauthjs/next-auth/pull/13467"
},
{
"type": "WEB",
"url": "https://github.com/nextauthjs/next-auth/pull/13469"
},
{
"type": "WEB",
"url": "https://github.com/nextauthjs/next-auth/commit/5bca2399a79ba8d116ca5179b4b1ebcd152e7f05"
},
{
"type": "WEB",
"url": "https://github.com/nextauthjs/next-auth/commit/e707770f00c52b3479e43422b0200b059149ed53"
},
{
"type": "PACKAGE",
"url": "https://github.com/nextauthjs/next-auth"
},
{
"type": "WEB",
"url": "https://github.com/nextauthjs/next-auth/releases/tag/@auth/core@0.41.3"
},
{
"type": "WEB",
"url": "https://github.com/nextauthjs/next-auth/releases/tag/next-auth@4.24.15"
},
{
"type": "WEB",
"url": "https://github.com/nextauthjs/next-auth/releases/tag/next-auth@5.0.0-beta.32"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "Auth.js: getToken() throws an uncaught exception on malformed Bearer authorization headers"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.