Skip to main content

Keys on the Wire

Your AI agent never holds your API keys. It sends a placeholder; the real secret is swapped in on the wire.

Stops credential stealers (Shai-Hulud and similar) and prompt-injected agents from leaking your secrets. A compromised agent has nothing to take.

PyPI License: Apache-2.0 CI

How it works

  1. Your agent sends a request with a placeholder, not the key.
  2. Keys on the Wire swaps in the real secret from your vault, in transit.
  3. The agent never sees the key. Nothing to leak, nothing to steal.

How Keys on the Wire substitutes secrets on the wire

Under the hood it's a loopback HTTPS proxy. It fetches each credential from your vault just in time and injects it into the outbound request, so the calling process (your agent, or anything else you route through it) never holds the real bytes.

Vault backends: macOS Keychain, Bitwarden Secrets Manager, Google Secret Manager, AWS Secrets Manager, static (no vault, for trying it out) and env. On a Mac the Keychain backend needs no cloud vault account and no extra dependency: your secrets stay where they already are. (kow setup still defaults to Bitwarden; pass the backend you want.) See Adapter architecture.

See it in action

Keys on the Wire demo: prompt injection vs. credential isolation

Quickstart

1. Install (Linux pipx, macOS brew):

pipx install 'keys-on-the-wire[bitwarden]'
# macOS: brew install inflightsec/keys-on-the-wire/keys-on-the-wire
sudo kow setup --bws

2. Install the skill so your agent writes the binding for you:

/plugin marketplace add inflightsec/keys-on-the-wire
/plugin install kow@keys-on-the-wire

3. Broker a service. Say "route the Stripe API through Keys on the Wire." The skill mints the placeholder and prints the exact note to paste into your vault. It never sees your key.

4. Add the real key to your vault with that note, then route your agent through the proxy:

kow env && kow run claude

Done. The agent only ever sends the placeholder; Keys on the Wire swaps in the real key on the wire.

New to this? The Quickstart guide walks the first run in full, and Prerequisites covers vault setup. Prefer shell env vars over kow run? See Usage.

Before you point it at production keys

  • Trial it behind one process. kow run -- <command> sets the proxy and CA variables in that process only; your login shell never inherits them. Scoping to a single process.
  • Fail-closed is the only mode. If kow is down, routed calls fail; a binding that denies returns 503 rather than passing the request bare.
  • It stops theft, not misuse. kow takes the key out of the agent's context; it does not judge why an API is being called. Narrowing a binding with methods: and paths: is the lever, and it is enforced. Is it for you? draws the full boundary.
  • Auth beyond static headers ships: OAuth2 refresh and client-credentials, JWT bearer, GitHub App, HMAC and AWS SigV4, with presets for Google, Microsoft, Auth0, Slack, Atlassian and Okta.

Broker an MCP server

Each MCP server keeps a long-lived token in cleartext in your client config, readable by every other server the client loads. kow mcp install swaps that standing secret for a placeholder and routes the server's egress through the proxy:

kow mcp install github --host api.github.com --env-var GITHUB_PERSONAL_ACCESS_TOKEN \
  --server-cmd "npx -y @modelcontextprotocol/server-github"

It prints the vault note and the exact claude mcp add --env command. Design and threat model: ADR-0040.

The binding is one line

Onboarding a credential is not hand-written YAML. The bundled kow skill asks the auth shape and host, then tells you exactly what to paste into your secret's Notes field:

# kow-binding
api.acme.com

That marker line is what makes it a binding; without it the note stays a plain human description, never parsed (ADR-0025). The assistant proposes, you apply. It never sees or stores the secret.

Docs

Start here — Is it for you? if you're evaluating · Prerequisites to set up your vault · Quickstart for a 10-minute first run.

Understand — Concepts for placeholder, binding, CA and fail-closed in plain terms · Architecture for the threat model, the G1 to G9 invariants and residual risks.

Install and operate — Linux · Docker · macOS · Usage · Single process · Linux isolation · macOS isolation · Google Secret Manager

Reference — bindings.example.yaml is the full config schema · Adapter architecture for vault backends and how to add one · Comparison versus Vault Agent, Doppler, op run and others · CHANGELOG · SECURITY · CONTRIBUTING · CREDITS

Open source, no lock-in

Every feature is in this repo under Apache-2.0. No paywalled tier, no hosted service, no telemetry. The proxy never phones home: its only outbound connections are your vault and the upstream APIs your agent calls. If an alternative fits your setup better, use that.

One optional dependency is not open source, the Bitwarden backend's bitwarden-sdk, which you install only if you use that backend. See LICENSE and NOTICE.

Metadata

Release files for keys-on-the-wire 1.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for keys-on-the-wire 1.1.1
File Size Uploaded
keys_on_the_wire-1.1.1.tar.gz 987.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for keys-on-the-wire 1.1.1
File Interpreter ABI Platform
keys_on_the_wire-1.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 1.2 MB

Release files / keys_on_the_wire-1.1.1.tar.gz

Download URL keys_on_the_wire-1.1.1.tar.gz
Size 987.1 kB
Tags Source
SHA-256 checksum
How to use checksums
429560de8b5482aa8cf106185c73a7abdb0c5add81624380d68fa34f3499fdaf
BLAKE2b-256 checksum
How to use checksums
4afb40ffc9d245ecda866e0462d35f84f54fa7a0be6df80bd339ada2feb450d6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.

Transparency log

Release files / keys_on_the_wire-1.1.1-py3-none-any.whl

Download URL keys_on_the_wire-1.1.1-py3-none-any.whl
Size 262.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8bf877b1b7a25411b413cf97698f5e05968d3a4db8cb22c95b220d23cc726f0b
BLAKE2b-256 checksum
How to use checksums
4fc652c85cc12c958d91fafa2b2fc042b18215f6bb10d874eafd633d4f244c11
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.1.1 This release

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page