Skip to content

fix(security): remove insecure default secret from GOOSE_EXTERNAL_BACKEND#7783

Merged
jh-block merged 3 commits intomainfrom
jhugo/fix-issue-7555
Mar 10, 2026
Merged

fix(security): remove insecure default secret from GOOSE_EXTERNAL_BACKEND#7783
jh-block merged 3 commits intomainfrom
jhugo/fix-issue-7555

Conversation

@jh-block
Copy link
Collaborator

@jh-block jh-block commented Mar 10, 2026

Summary

When GOOSE_EXTERNAL_BACKEND env var is set, the server secret was hardcoded to "test", creating a security footgun if this flag is accidentally set in production. This PR:

  • Server & tunnel: Both now generate cryptographically random secrets instead of defaulting to "test" when GOOSE_SERVER__SECRET_KEY is unset. The server passes the generated secret to the tunnel manager via app state, ensuring both use the same key.
  • Desktop client: When GOOSE_EXTERNAL_BACKEND is set, GOOSE_SERVER__SECRET_KEY is now required — the client fails fast with a clear error if it's unset.
  • Justfile: The debug-ui recipe explicitly sets GOOSE_SERVER__SECRET_KEY (defaulting to test) so the dev workflow continues to work.

Type of Change

  • Bug fix
  • Security fix

AI Assistance

  • This PR was created or reviewed with AI assistance

Testing

Rust compilation verified with cargo check. The dev workflow (CONTRIBUTING.md pattern) remains unchanged: developers set GOOSE_SERVER__SECRET_KEY=test on both server and client. The Justfile debug-ui recipe now sets this automatically.

Related Issues

Fixes #7555

…KEND

When GOOSE_EXTERNAL_BACKEND env var is set, the server secret was hardcoded to 'test', creating a security footgun if this flag is accidentally set in production. Both client and server now generate cryptographically random secrets instead of defaulting to 'test', while supporting explicit configuration via GOOSE_SERVER__SECRET_KEY env var for development workflows.

Fixes #7555

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2781fd7bd1

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

- agent.rs: persist generated secret to env so tunnel reads the same
  value instead of generating a second independent random secret
- main.ts: fail fast with a clear error when GOOSE_EXTERNAL_BACKEND is
  set but GOOSE_SERVER__SECRET_KEY is missing, instead of silently
  using an unshared random secret

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 498e82445b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Replace the unsafe `std::env::set_var` call (UB under multi-threaded
tokio runtime) with a `server_secret` field on TunnelManager. The
agent command now passes the generated secret to the tunnel manager
via `set_server_secret()`, ensuring both components use the same key
without global environment mutation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jh-block jh-block requested a review from jamadeo March 10, 2026 13:02
@jh-block jh-block added this pull request to the merge queue Mar 10, 2026
Merged via the queue into main with commit b6d6984 Mar 10, 2026
19 of 21 checks passed
@jh-block jh-block deleted the jhugo/fix-issue-7555 branch March 10, 2026 15:35
lifeizhou-ap added a commit that referenced this pull request Mar 11, 2026
* main: (45 commits)
  fix: resolve {{ recipe_dir }} in nested sub-recipe paths during secret discovery (#7797)
  Add @DOsinga as CODEOWNER for documentation (#7799)
  feat: Add summarize tool for deterministic reads (#7054)
  fix(api): use camelCase in CallToolResponse and add type discriminators to ContentBlock (#7487)
  feat: ACP providers for claude code and codex (#6605)
  chore(deps): bump express-rate-limit from 8.2.1 to 8.3.0 in /evals/open-model-gym/mcp-harness (#7703)
  feat(openai): capture reasoning summaries from responses API (#7375)
  Fix some dependencies (#7794)
  fix: improve keyring availability error detection (#7766)
  feat: add MiniMax provider with Anthropic-compatible API (#7640)
  feat: add Tensorix as a declarative provider (#7712)
  fix(security): remove insecure default secret from GOOSE_EXTERNAL_BACKEND (#7783)
  refactor: Convert Tanzu provider to declarative JSON config (#7124)
  replaces https://github.com/block/goose/pull/7340/changes (#7786)
  feat(summon): make skill supporting files individually loadable via load() (#7583)
  Keep toast open on failed extension (#7771)
  fix(ui-desktop): unify path resolution around GOOSE_PATH_ROOT (#7335)
  fix: pass OAuth scopes to DCR and extract granted_scopes from token response (#7571)
  fix: write to real file if config.yaml is symlink (#7669)
  fix: preserve pairings when stopping gateway (#7733)
  ...
lifeizhou-ap added a commit that referenced this pull request Mar 11, 2026
* main: (69 commits)
  fix: resolve {{ recipe_dir }} in nested sub-recipe paths during secret discovery (#7797)
  Add @DOsinga as CODEOWNER for documentation (#7799)
  feat: Add summarize tool for deterministic reads (#7054)
  fix(api): use camelCase in CallToolResponse and add type discriminators to ContentBlock (#7487)
  feat: ACP providers for claude code and codex (#6605)
  chore(deps): bump express-rate-limit from 8.2.1 to 8.3.0 in /evals/open-model-gym/mcp-harness (#7703)
  feat(openai): capture reasoning summaries from responses API (#7375)
  Fix some dependencies (#7794)
  fix: improve keyring availability error detection (#7766)
  feat: add MiniMax provider with Anthropic-compatible API (#7640)
  feat: add Tensorix as a declarative provider (#7712)
  fix(security): remove insecure default secret from GOOSE_EXTERNAL_BACKEND (#7783)
  refactor: Convert Tanzu provider to declarative JSON config (#7124)
  replaces https://github.com/block/goose/pull/7340/changes (#7786)
  feat(summon): make skill supporting files individually loadable via load() (#7583)
  Keep toast open on failed extension (#7771)
  fix(ui-desktop): unify path resolution around GOOSE_PATH_ROOT (#7335)
  fix: pass OAuth scopes to DCR and extract granted_scopes from token response (#7571)
  fix: write to real file if config.yaml is symlink (#7669)
  fix: preserve pairings when stopping gateway (#7733)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Desktop: env var GOOSE_EXTERNAL_BACKEND forces X-Secret-Key to 'test'

2 participants