How NoxKey stores, protects, and delivers secrets — without trusting the caller.
Two components, one Unix socket, zero network calls.
Every secret is a Keychain item with structured metadata.
service "noxkey"
account org/project/KEY
value encrypted by Secure Enclave
access Touch ID + passcode fallback
field_type api_key | token | password | totp_seed | username | email | url | text
kind login | api_key | recovery_codes | custom
security_level easy | normal | strict | off_limits
peek first 8 chars (for verification, never the full value)
bundle group label for organization
desc human description
prefix org/project/
pid resolved ancestor PID
startTime boot-relative (anti-recycle)
timeout default 4h, configurable
cache in-memory only, never persisted
path /usr/local/bin/claude
firstSeen ISO 8601 timestamp
storage app sandbox container
purpose first-seen warning on new callers
Five layers between a secret and an attacker.
The app ships without com.apple.security.network.client, so the kernel blocks every outbound socket. No telemetry, no sync, no exfiltration path. Verify with codesign -d --entitlements -.
Secrets encrypted at rest by the Secure Enclave. Not readable without biometric or passcode authentication. No custom crypto — Apple’s implementation.
Every read requires biometric auth. Strict mode secrets always require Touch ID, even during an unlocked session. Passcode fallback for non-biometric Macs.
Sessions are bound to a specific process tree ancestor (terminal PID + boot-relative start time). PID recycling is detected. Sessions auto-expire after 4h.
When an AI agent calls noxkey_get over MCP, the value is ChaChaPoly (AEAD) encrypted, written to a self-deleting temp script (chmod 600) that rms itself on first source, with a 120-second hard timeout as a safety net.
Every noxkey_get response carries an in-tool instruction telling the model not to echo, cat, printenv, or hardcode the loaded value. The MCP server’s system instructions repeat the rule. The agent uses the secret through $ENV_VAR; the raw value never re-enters the conversation.
AI agents get secrets through five MCP tools. Raw values never enter the model’s context.
| MCP Tool | Tier | What happens |
|---|---|---|
| noxkey_show | Core | Browse the tree (no values). With an account: peek the first 8 chars to verify. No Touch ID. |
| noxkey_get | Core | Per-request approval card → encrypted self-deleting handoff. Full path = single secret; prefix = batch under one Touch ID. Optional session: '4h' keeps the prefix unlocked. |
| noxkey_set | Core | Store via clipboard: true (preferred — the value never enters the conversation). Always pass field_type (api_key, token, password, totp_seed, username, email, url, text). Touch ID required. |
| noxkey_scan | Advanced · user-triggered | Read-only scan for .env-family files. Returns key names + 8-char peeks, no values. Pair with noxkey_admin(action: 'import') to write the batch under one Touch ID. |
| noxkey_admin | Advanced | Maintenance actions: delete, meta, organize, import, plus org/project/email management. |
| Bulk-exfil variants | Blocked | When an AI agent is detected, request shapes that would return raw values (--raw, --copy, load, export, bundle) are refused. |
Dev secrets use org/project/KEY (e.g. noboxdev/gitpulse/DATABASE_URL; use <org>/general/<KEY> when the project is unclear). Logins use login/<host>/USERNAME + login/<host>/PASSWORD (e.g. login/github.com/USERNAME) — one pair per host. Calling noxkey_get(account: 'login/github.com') returns BOTH USERNAME and PASSWORD in one handoff under a single Touch ID.
For longer tasks, pass session: '4h' (or similar) to noxkey_get. The Swift-side keychain stays unlocked for that prefix — subsequent calls within the window skip Touch ID. Sessions are per-prefix and revoke instantly when you quit the app.
Handoff scripts are single-use: they rm themselves on first source, with a 120-second hard timeout. If source returns no such file or directory, call noxkey_get again for a fresh path — do NOT retry the same source command.
Agents must NEVER cat/read the handoff file (only source it), echo loaded env vars, or use env | grep / compgen to introspect them — the response already lists what was loaded.
The bundled MCP server walks the process tree from the calling PID upward (up to 20 levels) using proc_pidinfo, checking each ancestor’s name against known AI agent signatures (Claude, Cursor, Codex, Windsurf, Copilot). The app independently verifies the same check. Both must agree before granting access. This runs on every MCP request — no config needed.
What NoxKey protects against, and what it doesn't.
| Threat | Protection |
|---|---|
| Secret in .env file on disk | Secrets stored in Keychain, not files. Drop your .env onto the import sheet — review the keys, Touch ID writes the batch — then delete the file. |
| Secret pasted into AI chat | Encrypted handoff means noxkey_get never returns plaintext to the agent context — the value reaches the agent's shell as an env var via a self-deleting temp script, never as a chat message. |
| Secret in shell history | Humans paste from clipboard via the menu bar UI; agents call MCP. Neither path puts a value on a command line. |
| Compromised agent exfiltrates keys | Per-request approval card surfaces the agent and key before anything leaves the Keychain. Bulk MCP variants are blocked when an agent is detected. |
| PID recycling after session unlock | Sessions store boot-relative process start time alongside PID. Recycled PIDs have different start times and are rejected. |
| Stolen laptop (disk access) | Keychain is encrypted by the Secure Enclave. Without biometric or passcode, values are unreadable. |
| Malicious process as same user | Not fully protected. A process running as your user can read /proc/PID/environ after a secret is loaded into env vars. NoxKey mitigates with single-use handoff scripts that delete themselves on source (with a 120-second hard timeout), but env var injection has inherent limits. |
| Network interception | NoxKey makes zero network calls. All communication is via a local Unix socket with filesystem permissions. |
NoxKey vs common approaches to secret management.
| Capability | .env files | 1Password CLI | Proxy injection | NoxKey |
|---|---|---|---|---|
| Secrets off disk | No | Yes | Yes | Yes |
| Biometric auth | No | Yes | No | Yes |
| AI agent detection | No | No | No | Yes |
| Encrypted handoff | No | No | Yes (proxy) | Yes (temp script) |
| Session scoping | No | Partial | Per-session | Per-prefix + PID binding |
| Zero network calls | Yes | No | No | Yes |
| Works offline | Yes | No | No | Yes |