VibeOps Blog

How to let an AI deploy your app without giving it your API keys

Every AI deployment tool asks for the same thing eventually: paste your token here. Vercel token, AWS access key, database URL, Cloudflare API key. The moment you paste it, that string is in a prompt, in a context window, in a provider's logs, and probably in a transcript you can't delete.

That trade — convenience for credentials — is not actually required. Deployment is a sequence of shell commands. The model is good at deciding which commands. It doesn't need to read the secrets those commands consume.

The problem with pasting a token into a chat

Once a credential enters a model's context, four things happen that you no longer control:

  • It's sent to a third party. Even with a zero-retention policy, it left your machine.
  • It's in the transcript. Scroll-back, session exports, crash reports, and your own terminal history.
  • It gets echoed. Models repeat inputs. A summary step, an error message, a "here's what I ran" recap — any of them can print the token back out.
  • It survives the session. Rotating a leaked key is easy. Knowing that you need to rotate it is the hard part.

The standard advice is to scope the token narrowly and rotate it often. That's real mitigation, but it's mitigation of a problem you can avoid having.

The pattern: hold the value, pass a reference

The fix is old and boring, which is why it works. Separate the decision from the value.

  1. The secret is entered by you, into a local store. Not into a chat box. On macOS that's the Keychain; on Windows, Credential Manager; on Linux, the Secret Service API. The OS already solved encrypted-at-rest storage.
  2. The model gets a reference, never the value. It plans with $VERCEL_TOKEN, a name and nothing more. It knows the deploy needs a Vercel token. It does not know what the token is.
  3. The runtime substitutes at execution time. The reference is resolved into the actual environment of the actual child process, on your machine, after the plan is approved. The command runs with the real value; the transcript keeps the placeholder.
  4. Output is scrubbed on the way back. Command output is where secrets leak most often — a verbose CLI printing its config, a stack trace with a connection string in it. Every held value gets redacted from stdout and stderr before anything is fed back to the model.

The result: the credential travels from your keyboard, to the OS keychain, to a process environment variable. It never enters a prompt. If the provider were breached tomorrow, there would be nothing of yours in the blast radius.

What the model still needs to know

A common objection: doesn't the agent need the value to do anything useful? Almost never.

It needs to know a secret exists and what it's for — enough to write vercel deploy --token $VERCEL_TOKEN instead of guessing at auth. It needs the shape of your repo, the framework, the build command, the target platform. None of that is sensitive in the way a long-lived credential is.

The one genuinely awkward case is debugging an auth failure, where "is the token wrong?" is a real question. Answer it the way you would with a colleague who doesn't have prod access: check the error code, check the scope, re-enter the value yourself. A 401 is enough signal to act on.

Approval gates on writes

Secret handling covers exfiltration. It doesn't cover mistakes. An agent with a valid token can still delete the wrong project.

So the second half of the pattern is a gate: every command that writes — deploys, provisions, deletes, changes DNS — is shown to you in full before it runs, and does not run until you say yes. Reads run freely, because reading is how the agent builds a plan worth approving.

Two gates, two different threats. Secret isolation stops the credential from leaving. Approval stops the command from running. Neither substitutes for the other.

Where to start

If you're building this yourself: put the keychain in front of the model, resolve references in the child process, and scrub output on the way back. Roughly a day of work, and it removes an entire class of incident.

If you'd rather not build it, VibeOps is a local harness that does exactly this — the model plans the deploy, your machine holds the credential, and every write waits for your approval.