Skip to content

fix: resolve gateway secret from OpenClaw credentials store#25

Open
enzoricciulli wants to merge 1 commit into
contextablemark:mainfrom
enzoricciulli:fix/resolve-gateway-secret-from-credentials-store
Open

fix: resolve gateway secret from OpenClaw credentials store#25
enzoricciulli wants to merge 1 commit into
contextablemark:mainfrom
enzoricciulli:fix/resolve-gateway-secret-from-credentials-store

Conversation

@enzoricciulli
Copy link
Copy Markdown

Problem

On local installs where OpenClaw manages credentials via its credentials store (e.g. ~/.openclaw/credentials/gateway_token), resolveGatewaySecret() returns null because it only checks plugin config and env vars. This causes /v1/clawg-ui to return:

{"error":{"message":"Gateway not configured","type":"server_error"}}

This is common when the gateway runs as a launchd agent — the HMAC secret exists in the credentials store but is not duplicated into the process environment.

Fix

Add a 4th fallback that reads <state_dir>/credentials/gateway_token using api.runtime.state.resolveStateDir(). If the file is missing or unreadable, it silently falls through — no new failure modes.

Priority order (unchanged for existing sources):

  1. Plugin config (gateway.auth.token)
  2. OPENCLAW_GATEWAY_TOKEN env var
  3. CLAWDBOT_GATEWAY_TOKEN env var
  4. (new) OpenClaw credentials store (<state_dir>/credentials/gateway_token)
  5. null → 500 Gateway not configured

No config schema changes. Narrow, backward-compatible fix.

If no secret is found in plugin config or env vars, fall back to
reading <state_dir>/credentials/gateway_token via
api.runtime.state.resolveStateDir(). This covers local installs where
the HMAC secret lives in the credentials store rather than the process
environment (e.g. launchd agents without shell profile sourcing).

Existing priority order is preserved — env vars still take precedence
over the credential file. No config schema changes.
Copy link
Copy Markdown
Owner

@contextablemark contextablemark left a comment

Choose a reason for hiding this comment

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

Hi @enzoricciulli

Thank you for the submission! Overall, it's a clean, well-scoped fix and it's great that it's backward-compatible.

In addition to my inline suggestion, I would also expect some additional tests for the credentials-store fallback, since it isn't covered by any existing tests. It would be good to add cases for insuring that it :

  • Reads token from credentials store when config and env are absent (happy path)

  • Returns null when credentials file does not exist (or is empty or contains only whitespace) and fallback is attempted

  • Prefers existing plugin config over credentials store (i.e., preserves backwards compatibility)

Other extension test files (e.g. extensions/phone-control/index.test.ts, extensions/nostr/src/nostr-state-store.test.ts) provide examples of how to mock runtime.state.resolveStateDir)

Thanks again!

Comment thread src/gateway-secret.ts
return token;
}
} catch {
// File not found or unreadable — fall through
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

The bare catch {} silently swallows all errors, including permission issues that a user would want to know about. A logger.warn() (or debug... not sure about the level) with the error would help troubleshoot misconfigured credentials stores without changing the control flow:

Please consider adding something like :

Suggested change
// File not found or unreadable — fall through
api.logger?.warn?.("credentials store fallback failed", { path: credPath, err });

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.

2 participants