Security
How Pipedash stores and encrypts tokens, protects the web API and WebSocket, handles telemetry and receives vulnerability reports.
Pipedash keeps provider tokens in one of 4 token stores and encrypts them with AES-256-GCM in the database stores. The web API uses the vault password as a bearer token. This page lists the encryption parameters and the routes that skip authentication.
Token storage
Pipedash supports 4 token stores. The token storage page explains how Pipedash selects one.
| Store | Where tokens live |
|---|---|
| System keyring | One JSON token map in the OS keyring under service pipedash and account tokens. Desktop only |
| Encrypted SQLite | The columns providers.encrypted_token and providers.token_nonce |
| Encrypted PostgreSQL | The table encrypted_tokens with provider ID, nonce and ciphertext |
| Environment | Variables that a token reference such as ${VAR} or env:VAR names in config.toml. PIPEDASH_TOKEN_<provider_id> has no effect |
At startup the desktop app uses the keyring when the backend is SQLite, PIPEDASH_VAULT_PASSWORD is unset and the database holds no encrypted tokens. It starts locked when SQLite holds encrypted tokens and the variable is unset, or when the backend is PostgreSQL and the variable is unset. Background tasks wait while it is locked, and the interface prompts for the password.
Encryption parameters
Both database stores encrypt each token with AES-256-GCM. They use a random 12-byte nonce and a 32-byte key. Each store derives the key from the vault password with Argon2id, version 0x13, and a 32-byte output.
| Use | Memory cost | Time cost | Parallelism |
|---|---|---|---|
| SQLite token key | 65536 KiB | 3 | 1 |
| PostgreSQL token key | 4096 KiB | 1 | 1 |
| SQLite backup key | 65536 KiB | 3 | 1 |
| Keyring backup key | 4096 KiB | 1 | 1 |
The salts are fixed, so the same password gives the same key on every install. A strong vault password carries the protection. The setup wizard requires at least 8 characters.
PostgreSQL needs an explicit vault password. A passwordless setup gets a random password that Pipedash does not save, so tokens written without one cannot be read after a restart.
API authentication
The web server reads PIPEDASH_VAULT_PASSWORD on each request. When the variable is missing, the API accepts every request. When it is set, protected routes require this header:
Authorization: Bearer <vault password>A mismatch returns 401. These paths skip the check:
- Paths outside
/api/v1/, which serve the embedded frontend - Paths that start with
/api/v1/health,/api/v1/setupor/api/v1/vault - The exact paths
/api/v1/wsand/api/v1/plugins
/api/v1/plugins/metadata is not exempt. The setup route returns a conflict error when the instance is already configured. The REST API page lists the routes.
When the vault password is set, a WebSocket client must send its first message as JSON:
{ "type": "auth", "token": "<vault password>" }The server closes the socket when the first message is not valid, has another type or carries the wrong token. Events then arrive as { "type": "<event name>", "payload": ... }.
CORS
PIPEDASH_CORS_ALLOW_ALL set to true or 1 allows any origin, method and header.
Telemetry
Pipedash sends no analytics, tracking or telemetry. Credentials, pipeline configuration and preferences stay on the device, and connections go directly from the device to the providers. The privacy page has the policy. A server deployment with PostgreSQL stores its data in the PostgreSQL database it connects to.
Vulnerability reports
Vulnerability reports go to the GitHub issue tracker. Issues there are public, so a report omits token values, exploit steps and payloads. It names the affected component and version instead.