Skip to content

[Bug]: Sensitive provider env value stored inline in settings.json is wiped on first save #10022

Description

@UzEE

Area

apps/server

Steps to reproduce

  1. Stop the server. In settings.json under the T3 userdata directory, add a provider instance with a sensitive variable whose value sits inline, and make sure no matching provider-env-* file exists under secrets/:

    {
      "providerInstances": {
        "claudex": {
          "driver": "claudeAgent",
          "enabled": true,
          "environment": [
            { "name": "ANTHROPIC_BASE_URL", "value": "http://localhost:8317", "sensitive": false },
            { "name": "ANTHROPIC_AUTH_TOKEN", "value": "sk-inline-token", "sensitive": true }
          ],
          "config": {}
        }
      }
    }
  2. Start the server. The provider works, because load reads the inline value.

  3. From any client, save that provider instance without touching the token. Toggling the enabled switch is enough. The cross-device settings sync triggers the same save.

  4. Read settings.json again, then start a new thread on that provider.

Expected behavior

The token keeps its value. Either it stays in the file or the save moves it into the secret store. A save that never touched a field should not change what that field resolves to.

Actual behavior

The entry becomes "value": "", "valueRedacted": true and no provider-env-* secret file exists. Every provider session started after that gets an empty token. Sessions already running keep their old environment, so the failures look random.

The cause is in apps/server/src/serverSettings.ts. Clients only ever receive the redacted form of a sensitive variable. On save, the redacted branch of persistProviderEnvironmentSecrets writes that placeholder straight back. It never checks that the secret store holds a value, and it drops the inline value the server still has in memory for that variable. One save and the token is gone from disk.

This is a papercut more than a bug. The documented path is to enter secrets through Settings, and that path works. But writing settings.json directly is a normal thing for a coding agent to do when it sets up a provider, which is how my config got this way. I never edited the file by hand. The app accepted the config, ran with it for weeks, then destroyed it on an unrelated save with no warning.

Impact

Minor bug or occasional failure. It only affects configs written outside the UI, but when it hits, the failure is silent and shows up later as a provider auth error on whichever thread starts next, with nothing pointing back at the save.

Version or commit

0.0.39-nightly.20260903.1270. Reproduced with a server test against main at c7dc3cb.

Environment

Linux (WSL2), Node 24.11.1, Claude Code provider behind a local CLIProxyAPI.

Logs or stack traces

# proxy response for every session started after the save
401 {"error":"Invalid API key"}

# server-level repro (temporary test, not committed)
AssertionError: expected '' to equal 'sk-inline-token'

Related issues

None match. #9230, #317, and #1267 are about variables not reaching the provider at all, not about a save erasing a stored value. Closed PRs #3524 and #3061 touched the settings editor's draft rows in the browser and never changed what the server writes.

Workaround

Re-enter the value in Settings > Providers for that instance. That path writes it to the secret store and the placeholder in settings.json becomes valid.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    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