Client-side secret redaction: credentials never leave your machine
Your agent needs to read your environment to debug it. Your provider does not need your AWS keys. Where redaction runs decides everything.
AI dev tools have an uncomfortable default: to help you, they read your stuff. And your stuff is full of credentials.
Not because you're sloppy — because that's what a working dev environment is. .env files. A DATABASE_URL with the password inline. Exported cloud keys. The bearer token in that curl command you pasted somewhere to ask "why is this 401ing?"
The moment any of that lands in a prompt, it has left your machine. It's in a request body, in someone's logs, maybe in someone's cache. "We trust the provider" is a real position — but it is not the same position as "the provider never had it."
Building rysh, an agentic terminal multiplexer, this came up in almost every conversation with security-minded teams. So let me walk through the layer that handles it — and, just as importantly, exactly where its guarantees stop.
The scene where it matters
You're debugging a deploy. You ask the agent in your pane:
> why is the worker failing to connect to postgres?
A useful agent wants to look at your environment — that's where the answer usually lives. rysh ships an env_read tool for exactly this. Here's the thing though: a naive implementation of that tool dumps env output straight into the conversation, and now AWS_SECRET_ACCESS_KEY, DATABASE_URL, and STRIPE_SECRET_KEY are all part of a request to a model API.
rysh's env_read redacts instead. Values that match credential shapes are scrubbed before they enter the conversation:
[tool] env_read
DATABASE_URL = postgres://worker:[REDACTED]@db.internal:5432/app
AWS_ACCESS_KEY_ID = [REDACTED]
AWS_SECRET_ACCESS_KEY= [REDACTED]
DEPLOY_ENV = staging
WORKER_POOL_SIZE = 4
Notice what survives: the variable names, the non-secret values, the structure of the URL. That's almost always what the model actually needs. "Your DATABASE_URL points at db.internal but the worker runs in the public subnet" is a diagnosis that requires zero knowledge of the password. The name is the signal; the value is just liability.
Why "client-side" is the load-bearing word
Plenty of products say "we redact secrets." The question to ask is: where does the redaction run?
If it runs server-side — in the vendor's cloud, before the model call — then the vendor's infrastructure saw your credential. It was on the wire, in TLS termination, in a request buffer, potentially in a crash dump. The redaction protects the model, not you.
Client-side redaction runs where the prompt is assembled: on your machine, in the same process that's building the request. The credential is scrubbed before any bytes leave. That's a categorically different promise, and it's the only version of the promise that survives a hostile security review.
The precise, bounded claim rysh makes is this: redaction guards the provider path — the text that gets assembled into requests to the model. Scrubbing happens before the request exists.
What one-way redaction can't do
Redaction is one-way: [REDACTED] is gone, and the model can't do anything with a hole.
Usually that's fine. But sometimes the agent legitimately needs to use a secret — write your .env for a new service, run a migration against the real database, call an authenticated endpoint. One-way redaction can't help there; if the model only ever sees a hole, it can't route the value to the tool that needs it.
That's a different problem with a different mechanism: reversible, format-preserving tokens that the model can reason about and local tools can restore — which is SecretNAT, and it deserves (and has) its own article. The short version of the layering:
- Redaction — one-way scrubbing for things the model should know about but never have (
env_readoutput). - SecretNAT — reversible translation for things the model needs to work with but still never have.
- Your gateway/DLP — if your org runs one, keep it; endpoint scrubbing and wire-level policy are complementary, not competing.
Where the guarantee stops (read this part)
I'd rather over-scope the caveats than under-scope them:
- This is about the provider path. Redaction governs what flows into model requests. It is not a DLP product for your whole machine, and it makes no claims about channels that aren't the model API.
- A shared pane is a screen share. rysh lets you share panes with teammates. Treat that the way you'd treat any screen share: what's visible on your screen is what you're choosing to show. Don't rely on redaction claims for surfaces it doesn't cover.
- Detection is heuristic. Credential-shaped strings are caught by pattern; an exotic secret format could slip through, and an odd-looking non-secret could get scrubbed. For secrets you specifically care about, the deterministic move is to register them explicitly — see the SecretNAT known tier.
- Nothing here replaces a secrets manager. Redaction is hygiene at the model boundary, not storage, rotation, or access control.
The takeaway
An agent that can't see your environment is useless for real work. An agent whose provider gets your environment verbatim is a breach with a delay on it. The resolution isn't picking one — it's separating knowing about from having, and enforcing that split on your machine, before the request is built.
Ask your current tool where its redaction runs. If the answer involves someone else's server, you already have your answer.
rysh is in private beta — self-hostable, your infra, your own Anthropic key, built on Claude. If "we can't let a model near our env vars" is blocking agent adoption at your company, that's exactly the conversation our design-partner program exists for: free access, direct line to the founder, your threat model shapes the roadmap. Apply here.
Related: SecretNAT: your AI needs the shape of a secret, not its value · Approval gates