Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"schema_version": "1.4.0",
"id": "GHSA-xv8g-fj9h-6gmv",
"modified": "2026-03-10T01:18:20Z",
"modified": "2026-03-10T01:18:22Z",
"published": "2026-03-10T01:18:20Z",
"aliases": [],
"summary": "Linkdave Missing Authentication on REST and WebSocket endpoints",
"details": "### Impact\nThe `linkdave` HTTP server does not enforce authentication on its REST and WebSocket routes. Because this server may be exposed to the internet, any unauthenticated remote attacker can connect to these endpoints.\n\n### Patches\n[1.2.5](https://github.com/shi-gg/linkdave/commit/0f9a00d9d549b16278db81fce6dfec350c2abc01)\n\n### Workarounds\nIf upgrading is not immediately possible, users can mitigate this issue by:\n- Restricting network access to the server's port using a firewall so it is only accessible from trusted internal IP addresses.",
"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 [`>=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 `>= 0.0.1, < 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 `>= 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)\" >> .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.",
"severity": [
{
"type": "CVSS_V4",
Expand Down
Loading