shi-gg/linkdave · Security

Linkdave Missing Authentication on REST and WebSocket endpoints

GHSA ID
GHSA-xv8g-fj9h-6gmv
Severity
critical
Published
Updated
CVSS v4
9.3 · 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

Description

The linkdave server does not enforce authentication on its REST and WebSocket routes in versions prior to 0.1.5.

Impact

An attacker with network access to the server port can:

  • Connect to the WebSocket endpoint (/ws) and receive a valid session_id in the OpReady response.
  • Use that session to invoke all REST player controls on any guild corresponding to their session id[1].
  • Enumerate server statistics and runtime information via the unauthenticated /stats endpoint (still public after the fix).

[1] If on >=0.1.0, attackers are restricted to creating, controlling and deleting players created within their own session ID.

Vulnerable Routes

The following routes were entirely unauthenticated in >= 0.0.1, < 0.1.5:

Method Path Description
POST /sessions/{session_id}/players/{guild_id}/play Start audio playback
POST /sessions/{session_id}/players/{guild_id}/pause Pause playback
POST /sessions/{session_id}/players/{guild_id}/resume Resume playback
POST /sessions/{session_id}/players/{guild_id}/stop Stop playback
POST /sessions/{session_id}/players/{guild_id}/seek Seek to position
PATCH /sessions/{session_id}/players/{guild_id}/volume Set volume
DELETE /sessions/{session_id}/players/{guild_id} Disconnect from voice channel
GET /ws WebSocket event stream

Patches

Update to 0.1.5.

- image: ghcr.io/shi-gg/linkdave:0.1.4
+ image: ghcr.io/shi-gg/linkdave:latest

or

docker pull ghcr.io/shi-gg/linkdave:latest

After 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.

Server configuration (e.g. compose.yml):

environment:
    LINKDAVE_PASSWORD: ${LINKDAVE_PASSWORD}
echo "LINKDAVE_PASSWORD=$(openssl rand -hex 16)" >> .env

To restart the stack, run

docker compose up -d

TypeScript client (0.1.5+):

The client automatically handles authentication. Pass the password when constructing the client:

const linkdave = new LinkDaveClient({
    nodes: [
        {
            name: "main",
            url: process.env.LINKDAVE_URI,
            password: process.env.LINKDAVE_PASSWORD
        }
    ]
});

Workarounds

If 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.

CWEs

References