Skip to content

Bug: macOS gateway install --force resolves SecretRef values into plaintext LaunchAgent plist and triggers token mismatch loop #53742

@beto-sudo

Description

@beto-sudo

Summary

openclaw gateway install --force resolves every SecretRef in openclaw.json and writes the resolved values as plaintext into the macOS LaunchAgent plist (~/Library/LaunchAgents/ai.openclaw.gateway.plist).

This defeats the purpose of moving secrets out of openclaw.json and into ~/.openclaw/.env using ${ENV:...} references.

It also appears to cause a confusing warning loop where openclaw doctor --fix and openclaw gateway restart report:

Config token differs from service token. Run openclaw gateway install --force to sync the token

…but running install --force just re-embeds the resolved values into the plist again.

Why this is a problem

  • Secrets that were intentionally externalized to ~/.openclaw/.env are copied back into a persistent service definition as plaintext.
  • This undermines the security/privacy model of SecretRef usage in openclaw.json.
  • It creates a circular remediation path:
    • OpenClaw warns that the service token differs from the config token.
    • The suggested fix is openclaw gateway install --force.
    • That command hardcodes the resolved secret values into the LaunchAgent plist.
    • The warning can still persist even though the gateway itself is healthy.

In practice, the gateway continues to work (RPC probe: ok), so the mismatch warning appears functionally cosmetic but still sends the user into an infinite loop of “fix” steps.

Steps to reproduce

  1. Move secrets from openclaw.json into ~/.openclaw/.env.
  2. Use SecretRef / env references in openclaw.json, e.g.:
{
  "gateway": {
    "token": "${ENV:OPENCLAW_GATEWAY_TOKEN}"
  }
}
  1. Run:
openclaw gateway install --force
  1. Inspect the LaunchAgent plist:
plutil -p ~/Library/LaunchAgents/ai.openclaw.gateway.plist
  1. Observe that all resolved secrets (for example OPENCLAW_GATEWAY_TOKEN, ANTHROPIC_API_KEY, TELEGRAM_BOT_TOKEN, etc.) appear as plaintext values in the plist.
  2. Run:
openclaw gateway restart
  1. Observe the warning:

Config token differs from service token. Run openclaw gateway install --force to sync the token

  1. Repeat install --force and/or doctor --fix; the warning can continue indefinitely.

Expected behavior

One of these should happen instead:

  1. openclaw gateway install should preserve SecretRef indirection and configure the LaunchAgent to load environment values at runtime, rather than serializing the resolved values into the plist.
  2. The LaunchAgent should reference ~/.openclaw/.env (or another env source) so secrets remain external to the plist.
  3. The “config token differs from service token” check should compare effective/resolved values correctly and avoid warning when the runtime values already match.

Actual behavior

  • SecretRef values are resolved during gateway install --force.
  • The resolved values are embedded into ~/Library/LaunchAgents/ai.openclaw.gateway.plist as plaintext.
  • Subsequent restart/doctor flows can warn that the config token differs from the service token even though the gateway is functioning normally.

Environment

  • OpenClaw: 2026.3.23 (ccfeecb)
  • macOS: 26.3.1 (arm64)
  • Node: 25.5.0
  • Gateway service type: LaunchAgent

Suggested direction

This feels like both a security bug and a service-install/runtime parity bug.

A robust fix would likely be:

  • keep secrets in .env / external secret sources,
  • have the LaunchAgent load them at runtime,
  • and make the token consistency check compare effective values rather than the serialized plist representation.

Happy to provide sanitized examples of the generated plist if helpful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions