Architecture

How NoxKey stores, protects, and delivers secrets — without trusting the caller.

System Overview

Two components, one Unix socket, zero network calls.

┌─────────────────────────────────────────────────────────────────┐ Your Terminal / AI Agent $ eval "$(noxkey get org/proj/KEY)" CLI (Bash) ──────── Unix Socket ────────▶ Menu Bar App (Swift) 2,047 lines /tmp/noxkey.sock 5,877 lines Touch ID / Passcode macOS Keychain (Secure Enclave) ┌────────────────────────────────────┘ Encrypted Response (AES-256-CBC) Self-deleting temp script /tmp/noxkey-agent-$$/*.sh • chmod 700 • deletes itself after source • auto-removed after 60s export KEY="value" ← in process env only, never on disk └─────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────┐ DLP Guard (PostToolUse hook) Agent output ──▶ noxkey guard ──▶ Match 8-char peek fingerprints against all stored secrets Clean ◄───┤───► BLOCKED pass through prevent secret from entering conversation └─────────────────────────────────────────────────────────────────┘

Data Model

Every secret is a Keychain item with structured metadata.

Secret (Keychain Item)

service "noxkey" account org/project/KEY value encrypted by Secure Enclave access Touch ID + passcode fallback

Secret Metadata (JSON label)

type token | password | key | cert peek first 8 chars (for DLP matching) expires ISO 8601 date strict always require Touch ID rotate rotation instructions URL bundle group label for organization desc human description

Session

prefix org/project/ pid resolved ancestor PID startTime boot-relative (anti-recycle) timeout default 4h, configurable cache in-memory only, never persisted

Known Caller

path /usr/local/bin/claude firstSeen ISO 8601 timestamp storage ~/.config/noxkey/known_callers.json purpose first-seen warning on new callers

Security Boundaries

Five layers between a secret and an attacker.

Layer 1

macOS Keychain

Secrets encrypted at rest by the Secure Enclave. Not readable without biometric or passcode authentication. No custom crypto — Apple's implementation.

Layer 2

Touch ID Gate

Every read requires biometric auth. Strict mode secrets always require Touch ID, even during an unlocked session. Passcode fallback for non-biometric Macs.

Layer 3

Session Binding

Sessions are bound to a specific process tree ancestor (terminal PID + boot-relative start time). PID recycling is detected. Sessions auto-expire after 4h.

Layer 4

Encrypted Handoff

When an AI agent calls noxkey get, the value is AES-256-CBC encrypted, written to a self-deleting temp script (chmod 700), and auto-removed after 60 seconds.

Layer 5

DLP Guard

Scans all agent output against 8-character peek fingerprints of stored secrets. Blocks leaked values before they enter the conversation context. Configured as a Claude Code PostToolUse hook.

Agent Access Model

AI agents get secrets safely. They never get the raw value in their context.

CommandAgent AccessWhat happens
noxkey ls Allowed Lists key names only, no values
noxkey peek Allowed First 8 characters — safe for verification
noxkey get Allowed Returns encrypted self-deleting script, not raw value
noxkey set Allowed Store from clipboard (--clipboard)
--raw Blocked Process-tree detection blocks raw output for AI agents
load / export / bundle Blocked Bulk export commands blocked — prevents mass exfiltration

How agent detection works

The CLI walks the process tree from the calling PID upward, checking each ancestor's process name against known AI agent signatures (Claude, Cursor, Codex, Windsurf, Copilot). The server independently verifies the same check. Both must agree before granting access. This runs on every command — no config needed.

Threat Model

What NoxKey protects against, and what it doesn't.

ThreatProtection
Secret in .env file on disk Secrets stored in Keychain, not files. noxkey import migrates .env → Keychain, then you delete the file.
Secret pasted into AI chat DLP guard scans agent output and blocks matches. Encrypted handoff means get never returns plaintext to the agent context.
Secret in shell history noxkey set --clipboard reads from clipboard, never from arguments. Value never appears in history.
Compromised agent exfiltrates keys Agent can only run get (encrypted handoff). --raw, load, export are blocked. Bulk exfiltration not possible.
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 short-lived temp scripts and 60s auto-delete, but this is an inherent limitation of env var injection.
Network interception NoxKey makes zero network calls. All communication is via a local Unix socket with filesystem permissions.

How it compares

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
DLP / leak scanning 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