Skip to content

[BUG] Fix silent security vulnerabilities and broken secret generation in Docker setup #1182

Description

@mbajji

TL;DR

The self-hosting setup currently suffers from three silent security and functional bugs:

  1. Public/Literal Secrets: Setup instructions present OpenSSL commands as raw .env values, leading users to save publicly known command strings as live secrets.
  2. Invalid Encryption Key Format: The documented ENCRYPTION_KEY command produces an 88-character Base64 string, but the backend requires a 64-character hex string, causing features like proxy and API key storage to crash at runtime.
  3. Secret Truncation via $: .envexample contains unescaped $ characters, causing Docker Compose to treat them as unset variables and silently truncate keys/passwords which could lead to things to crash.

Description

Following the documented setup in docs/self-hosting-docker.md (or copying .envexample directly) can result in broken functionality or compromised security. There are three interrelated issues where setup succeeds silently, but leaves the instance insecure or partially broken. The third bug is the one that led to the other 2 to be found.

Environment Tested:

  • Branch/Commit: master
  • OS / Runtime: Windows / Docker Compose (Docker 28.4.0)

1. Documentation Presents Commands as .env Values (docs/self-hosting-docker.md)

Issue:
Step 4 of docs/self-hosting-docker.md instructs users to "Create an environment file to save your variables nano .env with the following contents:" and lists a block of key-value pairs where the values are OpenSSL commands:

JWT_SECRET=openssl rand -base64 48
DB_PASSWORD=openssl rand -base64 24
ENCRYPTION_KEY=openssl rand -base64 64
SESSION_SECRET=openssl rand -base64 48
MINIO_SECRET_KEY=openssl rand -base64 24

While most people can infer that these are terminal commands to generate random strings, users who are new to Docker or .env files (or those who simply copy-paste the block without reading closely) will end up with the literal command strings saved inside their .env file.

Impact:
Because the file is copied as-is, the application sets its active secrets to the literal string "openssl rand -base64 48". Every instance configured this way shares the exact same publicly documented keys, allowing anyone to forge valid JWT tokens, hijack sessions, or decrypt sensitive stored data (like LLM API keys and proxy passwords).
Additionally, the containers start and function normally without raising any errors, leaving the instance silently exposed.

To Reproduce:

  1. Copy the example block directly into a .env file.
  2. Run docker compose up -d.
  3. Check the container's environment variables:
docker compose exec backend printenv JWT_SECRET
# Output: openssl rand -base64 48

2. Documented ENCRYPTION_KEY Command Generates Invalid Format

Issue:
The guide recommends running openssl rand -base64 64 to generate the ENCRYPTION_KEY. However, the application validation logic (server/src/utils/auth.ts) strictly requires a 64-character hex string:

const HEX_64_RE = /^[0-9a-fA-F]{64}$/;

The recommended Base64 command generates 88 characters wrapped across two lines, which fails regex validation during runtime tasks like saving proxy configurations.

Impact:
Saving proxy settings, robot credentials, or LLM API keys fails at runtime without throwing a clear setup error during initial container startup.

To Reproduce:

  1. Set ENCRYPTION_KEY to the output of openssl rand -base64 64
  2. Restart the backend: docker compose up -d
  3. Log in and save any proxy URL(https://www.google.com/) under proxy settings (in localhost)
  4. Look at the result of docker after running docker compose logs backend --tail 1

Error Output:
on localhost/cloud: Image
On terminal:

backend-1  | Could not save proxy configuration - Error: ENCRYPTION_KEY is missing or invalid. Set a 64-character hex string in your .env file.

3. Docker Compose Silently Truncates Secrets Containing $ (ENVEXAMPLE)

Most programmers who have some experience with .env will just copy ENVEXAMPLE as is and follow the readme to set up docker and may not read the docs since the example env is already given.

Issue:
Line 3 of ENVEXAMPLE includes an unescaped dollar sign in the default secret:

JWT_SECRET=a9Z$kLq7^f03GzNw!bP9dH4xV6sT2yXl3O8vR@uYq3

Docker Compose interprets $kLq7 as an environment variable reference since it starts with $. Since kLq7 is unset, Docker Compose evaluates it to an empty string, silently dropping characters before injecting the variable into the container.

Image

Impact:

  • Running Compose yields warnings: The "kLq7" variable is not set. Defaulting to a blank string.
  • The container receives a truncated 37-character secret instead of the intended 42-character value.
  • Any custom password or secret created by a user that includes an unescaped $ (e.g., in DB_PASSWORD or MINIO_SECRET_KEY) will be altered silently.

To Reproduce:

  1. Set JWT_SECRET=test$FOO in .env.
  2. Execute docker compose up -d backend.
  3. Check the received variable:
docker compose exec backend printenv JWT_SECRET
# Output: test

I am happy to open a PR with these fixes if this sounds good!

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions