GHSA-W3HV-X4FP-6H6J
Vulnerability from github – Published: 2026-03-25 17:27 – Updated: 2026-03-25 17:28Impact
The WebSocket upgrade handler in the server validates authentication (API key token or session cookie) but does not check the Origin header. A malicious webpage on a different origin could initiate a WebSocket connection to ws://localhost:3000/ws if it can leverage the user's session cookie (which is SameSite=Lax, allowing top-level navigations).
This enables cross-origin WebSocket hijacking — if a user visits a malicious site while a Grackle session is active, the attacker's page could open a WebSocket and subscribe to real-time events (session output, task updates, environment state).
Affected code:
- packages/server/src/ws-bridge.ts:80-91 — connection handler accepts WebSocket upgrades without checking req.headers.origin
Patches
Fix: Validate req.headers.origin against an allowlist before accepting connections:
const origin = req.headers.origin || "";
if (origin && !origin.includes("localhost") && !origin.includes("127.0.0.1")) {
ws.close(4003, "Invalid origin");
return;
}
Workarounds
Ensure the Grackle server is only accessible on 127.0.0.1 (the default). Do not use --allow-network in untrusted network environments.
Resources
- CWE-346: Origin Validation Error
- File:
packages/server/src/ws-bridge.ts
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 0.70.2"
},
"package": {
"ecosystem": "npm",
"name": "@grackle-ai/server"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.70.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-346"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-25T17:27:48Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "### Impact\n\nThe WebSocket upgrade handler in the server validates authentication (API key token or session cookie) but does not check the `Origin` header. A malicious webpage on a different origin could initiate a WebSocket connection to `ws://localhost:3000/ws` if it can leverage the user\u0027s session cookie (which is `SameSite=Lax`, allowing top-level navigations).\n\nThis enables **cross-origin WebSocket hijacking** \u2014 if a user visits a malicious site while a Grackle session is active, the attacker\u0027s page could open a WebSocket and subscribe to real-time events (session output, task updates, environment state).\n\n**Affected code:**\n- `packages/server/src/ws-bridge.ts:80-91` \u2014 connection handler accepts WebSocket upgrades without checking `req.headers.origin`\n\n### Patches\n\n**Fix:** Validate `req.headers.origin` against an allowlist before accepting connections:\n```typescript\nconst origin = req.headers.origin || \"\";\nif (origin \u0026\u0026 !origin.includes(\"localhost\") \u0026\u0026 !origin.includes(\"127.0.0.1\")) {\n ws.close(4003, \"Invalid origin\");\n return;\n}\n```\n\n### Workarounds\n\nEnsure the Grackle server is only accessible on `127.0.0.1` (the default). Do not use `--allow-network` in untrusted network environments.\n\n### Resources\n\n- CWE-346: Origin Validation Error\n- File: `packages/server/src/ws-bridge.ts`",
"id": "GHSA-w3hv-x4fp-6h6j",
"modified": "2026-03-25T17:28:05Z",
"published": "2026-03-25T17:27:48Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/nick-pape/grackle/security/advisories/GHSA-w3hv-x4fp-6h6j"
},
{
"type": "PACKAGE",
"url": "https://github.com/nick-pape/grackle"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "@grackle-ai/server has Missing WebSocket Origin Header Validation"
}
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.