Skip to content

bug: extension install hooks bypass core .env schema, then break PUT /api/settings/env with 503 #345

@yasinBursali

Description

@yasinBursali

Bug

When a built-in extension (e.g. librechat) is enabled via dream enable <ext> or the Custom install menu, the install hook appends extension-specific env keys to .env via the host-agent env-update path. These keys are not in the core dream-server/.env.schema.json. On subsequent calls to PUT /api/settings/env, the schema-aware validator rejects the first extension-added key with 503 {"detail":{"message":"Unknown key: <KEY>"}} before reaching any user-submitted changes.

Result: after installing any extension whose install hook writes .env keys, the dashboard Settings panel's Save button is completely broken — identical symptom to fork issue #337 (HOST_RAM_GB), different root cause.

Reproduction on integration-test install

```bash

Install at /Volumes/X/dream-server-test currently has librechat enabled.

The .env contains 6 LibreChat-specific keys:

$ grep -E '^(JWT_SECRET|JWT_REFRESH_SECRET|LIBRECHAT_MONGO_PASSWORD|LIBRECHAT_MEILI_KEY|CREDS_KEY|CREDS_IV)=' /Volumes/X/dream-server-test/.env | cut -d= -f1
JWT_SECRET
JWT_REFRESH_SECRET
LIBRECHAT_MONGO_PASSWORD
LIBRECHAT_MEILI_KEY
CREDS_KEY
CREDS_IV

None are in core schema

$ grep -E '"(JWT_SECRET|JWT_REFRESH_SECRET|LIBRECHAT_MONGO_PASSWORD|LIBRECHAT_MEILI_KEY|CREDS_KEY|CREDS_IV)"' /Volumes/X/dream-server-test/.env.schema.json
(no output)

raw_text PUT fails

$ KEY=$(grep ^DASHBOARD_API_KEY= /Volumes/X/dream-server-test/.env | cut -d= -f2)
$ python3 -c "
import json, urllib.request
raw = open('/Volumes/X/dream-server-test/.env').read()
req = urllib.request.Request('http://127.0.0.1:3002/api/settings/env',
method='PUT', headers={'Authorization': f'Bearer $KEY', 'Content-Type': 'application/json'},
data=json.dumps({'raw_text': raw}).encode())
urllib.request.urlopen(req)"
urllib.error.HTTPError: HTTP Error 503
body: {"detail":{"message":"Unknown key: JWT_SECRET"}}
```

Identical symptom happens regardless of which extension install hook ran — any extension that adds env keys breaks Settings save.

Why the extension install hook succeeds but subsequent saves fail

The install hook writes .env via the host-agent, which may bypass the schema-validated PUT path (it uses a direct file write or a different endpoint). The schema validator only runs on user-initiated PUT /api/settings/env calls from the dashboard. So the install-time write succeeds, the extension starts, the dashboard can display values — but the user can never save anything because the existing file fails validation on read.

Discovered during

Testing my fix for #337 on the drifted integration-test install. My schema fix unblocks HOST_RAM_GB, but then the validator hits the first LibreChat key and 503s on the same code path. Verified the HOST_RAM_GB fix in isolation by temporarily swapping to the 84-line pre-LibreChat baseline.

Platforms affected

Proposed fix directions

Pick one or a combination:

A. Declarative — extension manifest registers its env keys

Each extension's manifest.yaml gains an env_keys: array listing the keys it writes. The core _handle_env_update loads core schema AND all enabled-extension manifests' env_keys lists and treats extension keys as valid (perhaps as opaque strings). Clean separation of concerns, survives enable/disable cycles.

B. Validator relaxation — prefix whitelist

_handle_env_update allows any key matching a prefix pattern like LIBRECHAT_*, LANGFUSE_*, QDRANT_* (one per extension). Requires per-extension whitelist maintenance in core code, which is worse than A.

C. Validator relaxation — warn-on-unknown instead of reject

_handle_env_update logs a warning for unknown keys but accepts the PUT. Passes them through unchanged. Least principled but unblocks users immediately. Conflicts with Option A of fork issue #337 (which deliberately chose strict-reject over silent-accept).

Recommended: A + C — extension manifests register their keys (long-term correct model), and until extensions are migrated the validator degrades to warn-on-unknown so users aren't blocked. Migration path: extensions can register their keys via a simple manifest addition, and the validator gradually tightens as coverage grows.

Priority

High. On any install with any extension whose install hook writes env keys (LibreChat is one, others probably exist), the Settings panel is unusable — identical user-visible symptom to #337.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions