airgap 0.1.1

Security for the modern age of AI: defend against bad AI agents and malicious npm packages
# airgap

Security for the modern AI age. Hide secrets from AI agents, while letting them
do their work. `airgap` launches a target program (e.g. an AI coding agent)
inside its own mount namespace and transparently replaces secrets (e.g. `.env`,
SSH/PGP private keys) with redacted versions.

An agent running under `airgap` can still **read** and **modify** the protected
files, but it never sees the actual secrets. `airgap` also has an additional
layer to defend against malicious packages: it asks for your permission when
unexpected files are being accessed — for instance by a malicious npm install
script.

## Protected secrets

So far `airgap` protects:

- **`.env` and `.env.*`** (e.g. `.env.local`, `.env.production`) — matched by
  filename. Values are redacted to `<redacted value>` while keys stay visible;
  edits, additions, and deletions are persisted back to the real file.
- **SSH / PGP private keys** — matched by content (any file starting with a
  private-key header: OpenSSH/ed25519, RSA, EC/PKCS#8, or PGP). The key body is
  redacted while the `BEGIN`/`END` markers are kept.

More secret types will be added.

These are redacted anywhere under the **working directory** or your **home
directory** (`$HOME`) — so both a project's `.env` and `~/.ssh` keys are covered.
Matching is dynamic: files created after launch are caught too.

## Platform support

- **Linux** — fully supported. `airgap` relies on mount namespaces and a FUSE
  overlay, which are Linux features.
- **macOS** — not yet, but incoming.

## Install

```
cargo install airgap
```

`airgap` creates a mount namespace and mounts a FUSE filesystem, which require
`CAP_SYS_ADMIN`. Grant it to the installed binary once so you can run it as a
normal user (no `sudo` per invocation):

```
sudo setcap cap_sys_admin+ep "$(command -v airgap)"
```

Note: the capability is an attribute of the file, so it is lost whenever the
binary is reinstalled. Re-run `setcap` after each `cargo install`.

## Usage

```
airgap <program> [args...]
```

`airgap` runs `<program>` with `[args...]`, passing through argv, the
environment, and the working directory unchanged. When `<program>` exits,
`airgap` exits with the same code.

By default `<program>` must be a program airgap has a profile for (matched by
executable name):

- **AI agents**`opencode`, `claude` — run with redaction only.
- **Package managers**`npm`, `npx`, `yarn`, `pnpm` — run with redaction
  **plus** an interactive file gate: because their install hooks run arbitrary
  third-party code, airgap asks you to allow or reject the first read of each new
  file (so a `postinstall` script reading `~/.ssh/id_rsa` is caught). Approving a
  file grants only that file; decisions last for the run. A few benign paths are
  pre-approved (`~/.npm/_logs`, `~/.npm/_cacache`, `~/.gitconfig`,
  `$CWD/node_modules`, `$CWD/package.json`, `$CWD/package-lock.json`).

Running anything else requires the `--allow-unknown-program` opt-out (run it with
redaction only). `--profile <agent|npm>` forces a specific profile onto any
program. `--debug` logs each file access the gate pre-allows (allowlist hits) to
stderr. Program matching is a guardrail against accidental misuse, not a security
boundary.

### Demo

Compare `.env`'s content with and without using `airgap`:

```
$ cat .env
API_KEY=sk-live-9f8c2a1b4e7d
DB_PASSWORD=hunter2

$ airgap cat .env
API_KEY=<redacted value>
DB_PASSWORD=<redacted value>
```

With an AI agent:

```
$ airgap claude

 show me ./test/fixtures/.env contents

  Read 1 file

Here's the file:

DATABASE_URL="<redacted value>"
API_KEY="<redacted value>"
AWS_SECRET_ACCESS_KEY="<redacted value>"
DEBUG="<redacted value>"

...
```

## Use with Claude / opencode

To always run your AI agent under `airgap`, alias it in your shell config
(`~/.bashrc`, `~/.zshrc`, ...):

```
alias claude="airgap claude"
alias opencode="airgap opencode"
```

Now `claude` (or `opencode`) transparently runs inside `airgap`.

## Use with npm

Run your package manager under `airgap` to guard against malicious install
scripts — for example a `postinstall` script that tries to reach for your SSH
keys or `.env` during `npm install`:

```
$ airgap npm install
...
airgap: npm wants to read the file /home/you/.ssh/id_rsa — allow? [y/N] n
airgap: npm wants to read the file /home/you/.env — allow? [y/N] n
```

Answer `n` to reject the access.

Or alias it in your shell config:

```
alias npm="airgap npm"
```