#How do I stop my claw from dropping API keys in our private chats?

1 messages · Page 1 of 1 (latest)

grizzled flare
#

Even accidentally. Without revoking file read privileges. Version 2026.4.15

rain ferryBOT
sacred flameBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> âś… Mark Solution

rain ferryBOT
tidal muskBOT
#

Short answer: not reliably, if the raw key still lives in a file the agent can read.

The hard fix is to keep file read enabled, but move secrets off plaintext config and into SecretRefs. Then OpenClaw keeps secrets in the runtime snapshot, and SecretRef-managed provider creds persist as non-secret markers, not the resolved key.

What to use:

  • Fresh setup: openclaw onboard --secret-input-mode ref
  • Existing setup: openclaw secrets configure
  • Then verify/scrub leftovers: openclaw secrets audit --check

Relevant docs:

One important nuance: logging.redactSensitive: "tools" helps with logs/status output, but it is not the same as preventing the model from quoting plaintext it can read.

#

So, bluntly:

  • Prompt rules / AGENTS.md reduce accidents
  • SecretRefs are the real answer
  • If a key remains in a readable plaintext file, there is no airtight “never leak it” switch

Paste openclaw --version and I can tell you the safest migration path for your setup.

grizzled flare
#

Yeah i'm in the process of setting up a keyring coicidentally and that's when she dropped em TWICE

tidal muskBOT
#

Yeah, that’s a rotate-now situation, sadly.

If the real keys hit chat twice, I’d assume they’re burned:

  1. Rotate/revoke those keys now
  2. Delete the leaked chat messages if you can
  3. Move the creds to SecretRefs so OpenClaw reads markers, not plaintext files

Best fix going forward:

  • openclaw secrets configure
  • then openclaw secrets audit --check

If you’re still wiring up the keyring, map it through a SecretRef provider (env, file, or exec). That’s the supported way to keep file read available without leaving raw API keys in readable config.

Docs:

#

One more blunt note: prompt rules can reduce accidents, but they are not a hard boundary. If the model can read plaintext secrets, assume it can eventually spill them.

Paste openclaw --version and I can give you the quickest safe setup for your exact keyring path.

grizzled flare
#

i'm on 2026.4.15 on debian 13

#

i already have .env setup for everything but gws can't use it

tidal muskBOT
#

2026.4.15 is new enough, yep. I’d use SecretRefs immediately, not prompt-only guardrails.

My recommendation on Debian 13:

Best quick fix

  1. Rotate the leaked keys
  2. Run:
    openclaw secrets configure
    openclaw secrets audit --check
    openclaw secrets reload
    
  3. Store the creds as refs, not plaintext

Simplest reliable ref on Debian: env-backed refs
Example manual pattern:

#
openclaw config set models.providers.openai.apiKey \
  --ref-provider default \
  --ref-source env \
  --ref-id OPENAI_API_KEY

If you’re using a real keyring and want that instead, use a file or exec SecretRef provider. That works too, but the gateway service/user has to be able to read from that keyring at runtime.

So the decision is basically:

  • Env refs: easiest, least fragile, my recommendation
  • Keyring via file/exec ref: stronger separation, a bit more setup

Docs:

#

If by gws you mean the gateway service, that’s probably the issue.

A repo-local .env is often not enough for the daemon, because OpenClaw loads:

  • .env from the current working directory
  • plus the global fallback ~/.openclaw/.env

For a systemd user service on Debian, the reliable move is:

  1. Put the keys in ~/.openclaw/.env
  2. Point your creds at those env vars via SecretRefs
  3. Restart and verify

Useful commands:

openclaw secrets configure
#
openclaw gateway restart
openclaw models status

Alternative if you want shell env import:

{
  env: {
    shellEnv: {
      enabled: true,
      timeoutMs: 15000
    }
  }
}
grizzled flare
#

nah gws as in google workspace

tidal muskBOT
#

Ah, gotcha, my bad.

If you mean the Google Chat / Google Workspace service account side, env is supported.

OpenClaw supports:

  • GOOGLE_CHAT_SERVICE_ACCOUNT
  • GOOGLE_CHAT_SERVICE_ACCOUNT_FILE
  • and channels.googlechat.serviceAccountRef

For your don’t-ever-spill-it goal, I would not use serviceAccountFile in an agent-readable location. Better:

{
  channels: {
    googlechat: {
      serviceAccountRef: {
#
        source: "env",
        provider: "default",
        id: "GOOGLE_CHAT_SERVICE_ACCOUNT"
      }
    }
  }
}

That way:

  • the config holds a ref
  • not the raw JSON
  • and the model doesn’t need to read a credentials file to use it

Docs:

grizzled flare
#

i'm mainly using gmail/drive via oauth

tidal muskBOT
#

Ah, okay, that changes the answer a bit.

For Gmail/Drive via OAuth, the annoying truth is:

  • OpenClaw stores those creds in auth profiles on the gateway host
  • OAuth-mode profiles do not support SecretRef-backed credentials

So for that specific case, there is not currently a supported “keep full file read and make OAuth tokens impossible to read” switch.

Docs backing that:

So your real options are:

  1. Keep OAuth, but make the auth/state store unreadable to the agent
#
  • you can still keep normal file read for your workspace/project files
  1. Split trust boundaries

    • run the gateway/state under a separate user or host
    • let the agent use Gmail/Drive tools, but not browse the token store as files
  2. Switch to static creds/service-account flows where possible

    • those can use SecretRefs
    • but that depends on the exact Google workflow, and it’s not a drop-in replacement for every Gmail/Drive OAuth use case

So, bluntly: for Google OAuth specifically, prompt rules are only a soft guard. If the model can read the auth store, it can still leak it.

If you want, I can help you design the least painful split so you keep normal file read for your project, but wall off the OAuth state.

grizzled flare
#

so when i use gws auth login it mentions something about using env variables GOOGLE_WORKSPACE_CLIENT_ID and ...CLIENT_SECRET, which i've set in .env but it doesn't ever seem to use them. It also stores my plaintext secret in client_secret.json in the .config/gws directory, and i'd like for that to not be plaintext but idk how since i don't think it can use .env string replacement

tidal muskBOT
#

Two important bits:

  1. The current gws env var names include _CLI_
    Use:

    • GOOGLE_WORKSPACE_CLI_CLIENT_ID
    • GOOGLE_WORKSPACE_CLI_CLIENT_SECRET

    If you set GOOGLE_WORKSPACE_CLIENT_ID / ...CLIENT_SECRET, gws will ignore them.

  2. gws does not need OpenClaw .env string replacement
    It reads env vars directly, and current docs say it can also load them from a .env file.

So the clean way to avoid plaintext ~/.config/gws/client_secret.json is:

  • set the ..._CLI_CLIENT_ID and ..._CLI_CLIENT_SECRET vars in the environment where gws auth login actually runs
  • don’t keep ~/.config/gws/client_secret.json
  • then run gws auth login
#

One important caveat: this protects against file reads, not against a tool/agent that can inspect process env or run arbitrary commands. So it helps for your exact “don’t leak via readable files” goal, but it is not absolute isolation.

If you’re launching gws through the OpenClaw gateway/service, a repo-local .env may not be the one that process sees. In that case put the vars in the service’s real env, not just a shell-local file.

Docs/source that back this:

  • <https://github.com/googleworkspace/cli/blob/main/README.md>
  • env vars listed there are GOOGLE_WORKSPACE_CLI_CLIENT_ID and GOOGLE_WORKSPACE_CLI_CLIENT_SECRET

If you already used the _CLI_ names and 2026.4.15 still ignores them, that smells like an upstream gws bug/regression, not an OpenClaw config limitation.

grizzled flare
#

i have those variables set, but when i delete client_secret.json it says gws ouath is "not configured" until i put the json file back

tidal muskBOT
#

Yeah, that sounds like a real gws bug or docs mismatch.

If deleting ~/.config/gws/client_secret.json makes gws auth login say OAuth is “not configured”, then in practice 2026.4.15 is still depending on that file for the login flow, even if the ..._CLI_CLIENT_ID / ..._CLI_CLIENT_SECRET env vars are set.

So the honest answer is:

  • env-only does not seem to be working for this flow
  • there probably is not a supported “no plaintext client_secret.json” path right now for gws auth login

One nuance, though: the bigger secret is the refresh token, and gws docs say those are encrypted at rest. client_secret.json is still not great to leave lying around, but it is a smaller problem than a plaintext refresh token.

If your goal is “assistant can keep file read privileges and still can’t spill this”, then the real fix is stronger isolation, like:

  • run gws / OpenClaw under a different Unix user
  • or use a short-lived token flow instead of stored OAuth client material
  • or wait for/fix an upstream env-only auth path

Given your repro, I’d file it here:

#

https://github.com/googleworkspace/cli/issues

Something like: docs say GOOGLE_WORKSPACE_CLI_CLIENT_ID / _SECRET are an alternative to client_secret.json, but gws auth login still reports OAuth “not configured” unless the file exists.

grizzled flare
#

well i only need the secret json to login to gws to generated the enc credentials, so i just removed the plaintext key from there and put a ref to the env variable name and i can manually replace it in the future if i need it again

tidal muskBOT
#

Yeah, that’s a pretty sane workaround.

As long as the encrypted creds are already generated, normal gws use should keep working. You’d only need the real client secret back for things like:

  • a fresh gws auth login
  • re-consent / scope changes
  • recovering from revoked/broken auth

Only caveat: that “ref” in client_secret.json is basically your own placeholder, not something gws will resolve automatically, so future-you will need to swap the real value back in before reauth.

Glad you found a workable middle ground 👍

If this fixed it, please right-click the solution message → Apps → ✅ Mark Solution so Answer Overflow can index it for the next person.

grizzled flare
#

i think the answer to this thread is "use an OS keyring" tbh

tidal muskBOT
#

Yep, mostly.

I’d phrase it as:

Use an OS keyring for the actual long-lived auth material.
That’s the right answer for the sensitive part.

Small nuance: it doesn’t fully solve gws wanting client_secret.json around for the login/bootstrap path, but it does solve the more important bit, which is keeping refresh tokens / reusable creds out of plaintext files.

So, short version:

  • best general answer: use an OS keyring
  • annoying current caveat: gws auth login may still want plaintext client client config at setup time

That’s a good summary for the thread.

If this fixed it, please right-click the solution message → Apps → ✅ Mark Solution so Answer Overflow can index it.