{"id":"CVE-2026-49455","aliases":["EUVD-2026-70654","GHSA-75w3-gmqx-993q"],"status":"published","title":"Waku: Cross-Origin CSRF on RSC Server Action Dispatch","description":"Waku is the minimal React framework. Prior to version 1.0.0-beta.1, Waku's RSC request dispatcher invokes server actions without validating the request's Origin (or Sec-Fetch-Site) header. A cross-origin web attacker can therefore cause a victim browser to issue an authenticated POST to a registered server action endpoint using a CORS-safelisted content type (text/plain), which does not trigger a preflight. Any state-mutating server action that the application exposes via 'use server' can be invoked with the victim's cookies attached. This issue has been patched in version 1.0.0-beta.1.","severity":{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00174,"percentile":0.06857,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-352"],"published":"2026-07-08T20:27:11Z","modified":"2026-10-28T02:30:29Z","fixes":[{"ecosystem":"npm","package":"waku","fixed_in":["1.0.0-beta.1"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"waku","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"1.0.0-beta.0"},{"fixed":"1.0.0-beta.1"}]}]},{"source":"osv","ecosystem":"npm","package":"waku","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"1.0.0-beta.1"}]}]}],"products":[{"vendor":"wakujs","product":"waku"}],"references":[{"url":"https://github.com/wakujs/waku/security/advisories/GHSA-75w3-gmqx-993q","tags":["x_refsource_CONFIRM","advisory","web"]},{"url":"https://github.com/wakujs/waku/releases/tag/v1.0.0-beta.1","tags":["x_refsource_MISC","web"]},{"url":"https://github.com/advisories/GHSA-75w3-gmqx-993q"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/49xxx/CVE-2026-49455.json","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-49455","tags":["advisory"]},{"url":"https://github.com/wakujs/waku","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-49455","title":"Waku: Cross-Origin CSRF on RSC Server Action Dispatch","description":"Waku is the minimal React framework. Prior to version 1.0.0-beta.1, Waku's RSC request dispatcher invokes server actions without validating the request's Origin (or Sec-Fetch-Site) header. A cross-origin web attacker can therefore cause a victim browser to issue an authenticated POST to a registered server action endpoint using a CORS-safelisted content type (text/plain), which does not trigger a preflight. Any state-mutating server action that the application exposes via 'use server' can be invoked with the victim's cookies attached. This issue has been patched in version 1.0.0-beta.1.","status":"published","published":"2026-09-03T18:15:42.014Z","modified":"2026-09-03T18:34:19.918Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N","level":"medium","assessor":"cna"}],"cwes":["CWE-352"],"updated_at":"2026-11-02T13:34:59.78118Z"}],"euvd":[{"id":"EUVD-2026-70654","description":"Waku is the minimal React framework. Prior to version 1.0.0-beta.1, Waku's RSC request dispatcher invokes server actions without validating the request's Origin (or Sec-Fetch-Site) header. A cross-origin web attacker can therefore cause a victim browser to issue an authenticated POST to a registered server action endpoint using a CORS-safelisted content type (text/plain), which does not trigger a preflight. Any state-mutating server action that the application exposes via 'use server' can be invoked with the victim's cookies attached. This issue has been patched in version 1.0.0-beta.1.","status":"published","published":"2026-09-03T18:15:42Z","modified":"2026-09-03T18:34:19Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N","level":"medium"}],"updated_at":"2026-11-02T18:01:13.160542Z"}],"ghsa":[{"id":"GHSA-75w3-gmqx-993q","title":"Waku: Cross-Origin CSRF on RSC Server Action Dispatch","description":"## Summary\n\nWaku's RSC request dispatcher invokes server actions without validating the request's `Origin` (or `Sec-Fetch-Site`) header. A cross-origin web attacker can therefore cause a victim browser to issue an authenticated `POST` to a registered server action endpoint using a CORS-safelisted content type (`text/plain`), which does not trigger a preflight. Any state-mutating server action that the application exposes via `'use server'` can be invoked with the victim's cookies attached. A working proof-of-concept demonstrates the vulnerability against waku 1.0.0-beta.0 dev server: a cross-origin POST with `Content-Type: text/plain` invokes a registered `'use server'` action and returns HTTP 200 with an RSC stream response. The same defect affects the progressive-enhancement (no-JavaScript) server action path: a cross-origin HTML form auto-submitting `multipart/form-data` reaches the dispatch through a second unguarded branch of the request handler, dynamically confirmed on 2026-05-17. Both branches were confirmed exploitable from opaque-origin contexts (sandboxed iframes, `file://` navigation, browser extension pages), which send `Origin: null` — a value no Origin guard exists to reject. This is the same vulnerability class previously disclosed for Next.js Server Actions (GHSA-mq59-m269-xvcx); waku's implementation is broader in that no Origin check exists at all in the default request handler.\n\n\n## Root cause\n\nIn `packages/waku/src/lib/utils/request.ts`:\n\n```ts\n// line 29\nif (pathname.startsWith(rscPathPrefix)) {\n  rscPath = decodeRscPath(pathname.slice(rscPathPrefix.length));\n  const actionId = decodeFuncId(rscPath);\n  if (actionId) {\n    const body = await getActionBody(req);\n    const args = await decodeReply(body, { temporaryReferences });\n    const action = await loadServerAction(actionId);\n    // ...action is invoked with attacker-supplied args\n  }\n}\n```\n\nThe sibling `else if (req.method === 'POST')` branch (line 61) does enforce a method check, but only for non-RSC paths. The RSC dispatch branch has no equivalent guard. For comparison, frameworks in the same category (Next.js, Remix) compare the request's `Origin` header against the configured host before invoking a server action.\n\n## Trigger (one-line summary)\n\nA cross-origin `POST` with `Content-Type: text/plain` to `/\u003crscBase\u003e/\u003cencoded-action-path\u003e` reaches `loadServerAction` and invokes a registered `'use server'` action with the victim's browser-attached cookies.\n\n## Affected entry surfaces\n\n- All HTTP adapters exposed by waku (`packages/waku/src/adapters/node.ts`, `cloudflare.ts`, `vercel.ts`, `edge.ts`) — each chains through the same `request.ts:getInput` dispatcher.\n- Any server action declared with `'use server'` and reachable from the Vite module graph (i.e., normal application code).\n\n## Suggested fix outline\n\nAdd an `Origin` (and ideally `Sec-Fetch-Site`) validation step in the RSC dispatch branch of `getInput`, gated against the configured base URL host, with an opt-in `allowedOrigins` configuration option for legitimate cross-origin scenarios. Exact patch sketches will be provided in the follow-up comment.\n\n## Disclosure\n\n| Field | Value |\n|---|---|\n| Reporter | j0hndo (dohyun4466@gmail.com) |\n| Discovery date | 2026-05-15 |\n| Embargo | 90 days from acknowledgement (operator open to extension on request) |\n| Comparable precedent | Next.js GHSA-mq59-m269-xvcx (\"null origin can bypass Server Actions CSRF checks\"), CVSS 5.3, fixed Next.js 16.1.7 |\n| References | OWASP CSRF cheat sheet; Fetch spec § CORS-safelisted request-header (text/plain). |\n\n## Workarounds (publish-safe)\n\nUntil a framework-level fix is released, operators can mitigate by placing an `Origin`-validating reverse proxy or middleware in front of waku that rejects requests whose `Origin` header does not match the application's host on `POST` requests to the configured `rscBase` prefix. Note that Vite's `server.allowedHosts` guard (which rejects unrecognized `Host` headers with HTTP 403) applies only to `waku dev`; production deployments using `waku build \u0026\u0026 waku start` do not have an equivalent guard and are fully exposed without an external mitigation layer.","status":"published","published":"2026-07-08T20:27:11Z","modified":"2026-07-08T20:27:12Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N","level":"medium"}],"cwes":["CWE-352"],"updated_at":"2026-11-02T14:40:41.501474Z"}],"nvd":[{"id":"CVE-2026-49455","description":"Waku is the minimal React framework. Prior to version 1.0.0-beta.1, Waku's RSC request dispatcher invokes server actions without validating the request's Origin (or Sec-Fetch-Site) header. A cross-origin web attacker can therefore cause a victim browser to issue an authenticated POST to a registered server action endpoint using a CORS-safelisted content type (text/plain), which does not trigger a preflight. Any state-mutating server action that the application exposes via 'use server' can be invoked with the victim's cookies attached. This issue has been patched in version 1.0.0-beta.1.","status":"published","published":"2026-09-03T19:17:28.1Z","modified":"2026-09-09T20:20:21.673Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N","level":"medium","assessor":"secondary"}],"cwes":["CWE-352"],"updated_at":"2026-11-02T14:12:43.737972Z"}],"osv":[{"id":"CVE-2026-49455","title":"Waku: Cross-Origin CSRF on RSC Server Action Dispatch","description":"Waku is the minimal React framework. Prior to version 1.0.0-beta.1, Waku's RSC request dispatcher invokes server actions without validating the request's Origin (or Sec-Fetch-Site) header. A cross-origin web attacker can therefore cause a victim browser to issue an authenticated POST to a registered server action endpoint using a CORS-safelisted content type (text/plain), which does not trigger a preflight. Any state-mutating server action that the application exposes via 'use server' can be invoked with the victim's cookies attached. This issue has been patched in version 1.0.0-beta.1.","status":"published","published":"2026-09-03T18:15:42.014Z","modified":"2026-10-28T02:30:29.824933014Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N","level":"medium"}],"cwes":["CWE-352"],"updated_at":"2026-11-02T15:45:07.060148Z"},{"id":"GHSA-75w3-gmqx-993q","title":"Waku: Cross-Origin CSRF on RSC Server Action Dispatch","description":"## Summary\n\nWaku's RSC request dispatcher invokes server actions without validating the request's `Origin` (or `Sec-Fetch-Site`) header. A cross-origin web attacker can therefore cause a victim browser to issue an authenticated `POST` to a registered server action endpoint using a CORS-safelisted content type (`text/plain`), which does not trigger a preflight. Any state-mutating server action that the application exposes via `'use server'` can be invoked with the victim's cookies attached. A working proof-of-concept demonstrates the vulnerability against waku 1.0.0-beta.0 dev server: a cross-origin POST with `Content-Type: text/plain` invokes a registered `'use server'` action and returns HTTP 200 with an RSC stream response. The same defect affects the progressive-enhancement (no-JavaScript) server action path: a cross-origin HTML form auto-submitting `multipart/form-data` reaches the dispatch through a second unguarded branch of the request handler, dynamically confirmed on 2026-05-17. Both branches were confirmed exploitable from opaque-origin contexts (sandboxed iframes, `file://` navigation, browser extension pages), which send `Origin: null` — a value no Origin guard exists to reject. This is the same vulnerability class previously disclosed for Next.js Server Actions (GHSA-mq59-m269-xvcx); waku's implementation is broader in that no Origin check exists at all in the default request handler.\n\n\n## Root cause\n\nIn `packages/waku/src/lib/utils/request.ts`:\n\n```ts\n// line 29\nif (pathname.startsWith(rscPathPrefix)) {\n  rscPath = decodeRscPath(pathname.slice(rscPathPrefix.length));\n  const actionId = decodeFuncId(rscPath);\n  if (actionId) {\n    const body = await getActionBody(req);\n    const args = await decodeReply(body, { temporaryReferences });\n    const action = await loadServerAction(actionId);\n    // ...action is invoked with attacker-supplied args\n  }\n}\n```\n\nThe sibling `else if (req.method === 'POST')` branch (line 61) does enforce a method check, but only for non-RSC paths. The RSC dispatch branch has no equivalent guard. For comparison, frameworks in the same category (Next.js, Remix) compare the request's `Origin` header against the configured host before invoking a server action.\n\n## Trigger (one-line summary)\n\nA cross-origin `POST` with `Content-Type: text/plain` to `/\u003crscBase\u003e/\u003cencoded-action-path\u003e` reaches `loadServerAction` and invokes a registered `'use server'` action with the victim's browser-attached cookies.\n\n## Affected entry surfaces\n\n- All HTTP adapters exposed by waku (`packages/waku/src/adapters/node.ts`, `cloudflare.ts`, `vercel.ts`, `edge.ts`) — each chains through the same `request.ts:getInput` dispatcher.\n- Any server action declared with `'use server'` and reachable from the Vite module graph (i.e., normal application code).\n\n## Suggested fix outline\n\nAdd an `Origin` (and ideally `Sec-Fetch-Site`) validation step in the RSC dispatch branch of `getInput`, gated against the configured base URL host, with an opt-in `allowedOrigins` configuration option for legitimate cross-origin scenarios. Exact patch sketches will be provided in the follow-up comment.\n\n## Disclosure\n\n| Field | Value |\n|---|---|\n| Reporter | j0hndo (dohyun4466@gmail.com) |\n| Discovery date | 2026-05-15 |\n| Embargo | 90 days from acknowledgement (operator open to extension on request) |\n| Comparable precedent | Next.js GHSA-mq59-m269-xvcx (\"null origin can bypass Server Actions CSRF checks\"), CVSS 5.3, fixed Next.js 16.1.7 |\n| References | OWASP CSRF cheat sheet; Fetch spec § CORS-safelisted request-header (text/plain). |\n\n## Workarounds (publish-safe)\n\nUntil a framework-level fix is released, operators can mitigate by placing an `Origin`-validating reverse proxy or middleware in front of waku that rejects requests whose `Origin` header does not match the application's host on `POST` requests to the configured `rscBase` prefix. Note that Vite's `server.allowedHosts` guard (which rejects unrecognized `Host` headers with HTTP 403) applies only to `waku dev`; production deployments using `waku build \u0026\u0026 waku start` do not have an equivalent guard and are fully exposed without an external mitigation layer.","status":"published","published":"2026-07-08T20:27:11Z","modified":"2026-07-08T20:56:35.443454Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N","level":"medium"}],"cwes":["CWE-352"],"updated_at":"2026-11-02T15:46:40.657155Z"}]}}
