{"id":"GHSA-xv8g-fj9h-6gmv","summary":"Linkdave Missing Authentication on REST and WebSocket endpoints","details":"The `linkdave` server does not enforce authentication on its REST and WebSocket routes in versions prior to `0.1.5`.\n\n### Impact\n\nAn attacker with network access to the server port can:\n- Connect to the WebSocket endpoint (`/ws`) and receive a valid `session_id` in the `OpReady` response.\n- Use that session to invoke all REST player controls on any guild corresponding to their session id[1].\n- Enumerate server statistics and runtime information via the unauthenticated `/stats` endpoint (still public after the fix).\n\n[1] If on [`\u003e=0.1.0`](https://github.com/shi-gg/linkdave/releases/tag/v0.1.0), attackers are restricted to creating, controlling and deleting players created within their own session ID.\n\n### Vulnerable Routes\n\nThe following routes were entirely unauthenticated in `\u003e= 0.0.1, \u003c 0.1.5`:\n\n| Method | Path | Description |\n|--------|------|-------------|\n| `POST` | `/sessions/{session_id}/players/{guild_id}/play` | Start audio playback |\n| `POST` | `/sessions/{session_id}/players/{guild_id}/pause` | Pause playback |\n| `POST` | `/sessions/{session_id}/players/{guild_id}/resume` | Resume playback |\n| `POST` | `/sessions/{session_id}/players/{guild_id}/stop` | Stop playback |\n| `POST` | `/sessions/{session_id}/players/{guild_id}/seek` | Seek to position |\n| `PATCH` | `/sessions/{session_id}/players/{guild_id}/volume` | Set volume |\n| `DELETE` | `/sessions/{session_id}/players/{guild_id}` | Disconnect from voice channel |\n| `GET` | `/ws` | WebSocket event stream |\n\n### Patches\n\nUpdate to [`0.1.5`](https://github.com/shi-gg/linkdave/commit/0f9a00d9d549b16278db81fce6dfec350c2abc01).\n\n```diff\n- image: ghcr.io/shi-gg/linkdave:0.1.4\n+ image: ghcr.io/shi-gg/linkdave:latest\n```\nor\n```sh\ndocker pull ghcr.io/shi-gg/linkdave:latest\n```\n\nAfter upgrading, set the `LINKDAVE_PASSWORD` environment variable to a strong secret value. If this variable is left unset, the server will still accept all connections without authentication even on `\u003e= 0.1.5`.\n\n**Server configuration (e.g. `compose.yml`):**\n```sh\nenvironment:\n    LINKDAVE_PASSWORD: ${LINKDAVE_PASSWORD}\n```\n```sh\necho \"LINKDAVE_PASSWORD=$(openssl rand -hex 16)\" \u003e\u003e .env\n```\n\nTo restart the stack, run\n```sh\ndocker compose up -d\n```\n\n**TypeScript client (`0.1.5+`):**\n\nThe client automatically handles authentication. Pass the password when constructing the client:\n```ts\nconst linkdave = new LinkDaveClient({\n    nodes: [\n        {\n            name: \"main\",\n            url: process.env.LINKDAVE_URI,\n            password: process.env.LINKDAVE_PASSWORD\n        }\n    ]\n});\n```\n\n### Workarounds\n\nIf upgrading is not immediately possible, restrict network access to the server's port using a firewall so it is only accessible from trusted internal IP addresses.","aliases":["GO-2026-4661"],"modified":"2026-03-23T04:56:29.322172632Z","published":"2026-03-10T01:18:20Z","database_specific":{"github_reviewed":true,"github_reviewed_at":"2026-03-10T01:18:20Z","nvd_published_at":null,"cwe_ids":["CWE-306"],"severity":"CRITICAL"},"references":[{"type":"WEB","url":"https://github.com/shi-gg/linkdave/security/advisories/GHSA-xv8g-fj9h-6gmv"},{"type":"WEB","url":"https://github.com/shi-gg/linkdave/commit/0f9a00d9d549b16278db81fce6dfec350c2abc01"},{"type":"PACKAGE","url":"https://github.com/shi-gg/linkdave"}],"affected":[{"package":{"name":"github.com/shi-gg/linkdave","ecosystem":"Go","purl":"pkg:golang/github.com/shi-gg/linkdave"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"0.1.5"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/03/GHSA-xv8g-fj9h-6gmv/GHSA-xv8g-fj9h-6gmv.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V4","score":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N"}]}