Secure encrypted credential vault for AI agents. Store API keys and secrets locally with AES-256-GCM encryption, audit logging, and WebSocket integration for seamless agent access. Zero cloud dependency — your secrets never leave your machine.
- Download
- Quick Start
- Security Model
- User Guide
- Architecture
- API Reference
- WebSocket Protocol
- Configuration
- Best Practices
- Troubleshooting
- License
No terminal required — native menubar app with system tray integration.
| Intel Mac | Apple Silicon (M1/M2/M3/M4) |
|---|---|
| IronVault.dmg | IronVault-arm64.dmg |
First launch: macOS will warn about an unsigned app. Right-click the app → Open, or go to System Settings → Privacy & Security → "Open Anyway".
All releases · Security Audit v1.3.0 (Score: 9.5/10)
- Download the
.dmgfor your Mac (see above) - Drag IronVault to Applications
- Launch from Applications or Spotlight
- Create a master password (12+ characters, mixed case, numbers, symbols)
- Start adding credentials
git clone https://github.com/nKOxxx/AgentVault.git
cd AgentVault
npm install
npm startOpen http://localhost:8765, create a master password, and add your first key.
See README-STANDALONE.md for the portable version that runs without installation.
IronVault is built security-first. Every design decision prioritizes the protection of your credentials.
| Component | Implementation |
|---|---|
| Algorithm | AES-256-GCM (authenticated encryption with associated data) |
| Key Derivation | PBKDF2-SHA256, 100,000 iterations |
| IV | 16 cryptographically random bytes per encryption operation |
| Auth Tag | 16-byte GCM authentication tag prevents tampering |
| Implementation | Node.js native crypto module (hardware-accelerated via OpenSSL) |
Master Password
│
▼
PBKDF2-SHA256 (100k iterations + 16-byte random salt)
│
▼
256-bit Encryption Key (held in RAM only)
│
├──► Encrypt credentials (AES-256-GCM + random IV)
├──► Encrypt audit log entries
└──► Encrypt LLM configuration
- The master password is never stored — only the derived key is held in memory while the vault is unlocked
- Each encryption operation uses a unique random IV, preventing pattern detection
- GCM mode provides authenticated encryption — any tampering is detected and rejected
- The encryption key is cleared from memory when you lock the vault or after 15 minutes of inactivity
| Protection | Detail |
|---|---|
| Rate Limiting | 5 failed unlock attempts → 15-minute lockout |
| Auto-Lock | Vault locks after 15 minutes of inactivity |
| Network Scope | Localhost only (127.0.0.1) — no remote access |
| CORS | Restricted to localhost origins |
| File Permissions | Vault files created with 0o600 (owner read/write only) |
| WebSocket Auth | 32-byte random token required for agent connections |
| Password Requirements | 12+ chars, uppercase, lowercase, number, special character |
| Security Headers | CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy |
| Feature | Status |
|---|---|
nodeIntegration |
❌ Disabled |
contextIsolation |
✅ Enabled |
| External links | Opened in system browser (not in-app) |
| Preload bridge | Minimal, read-only API surface |
| Data directory | Platform-standard secure location |
- ❌ No cloud sync — your data stays on your machine
- ❌ No telemetry or analytics
- ❌ No password recovery — if you forget your master password, data is unrecoverable
- ❌ No remote access — only localhost connections accepted
- Launch IronVault (desktop app or
npm start) - You'll see the Create Your Vault screen
- Choose a strong master password:
- Minimum 12 characters
- Must include: uppercase, lowercase, numbers, and special characters
- Write it down and store it safely — there is no recovery mechanism
- Confirm your password and click Create Vault
- Click + Add Credential (or press
Ctrl+N) - Select a service type:
- OpenAI — API keys (
sk-...) - Anthropic — API keys (
sk-ant-...) - GitHub — Personal access tokens (
ghp_...) - Render — API keys and service IDs
- X/Twitter — OAuth credentials (API key, secret, access token, bearer)
- Custom — Any key/value pair
- OpenAI — API keys (
- Enter a descriptive name (e.g., "Production API Key")
- Paste your credential value
- Click Save Credential — it's encrypted immediately
- Copy 📋 — Decrypts and copies the credential to your clipboard
- Share 📤 — Sends the credential to a connected AI agent via WebSocket
- Delete 🗑️ — Permanently removes the credential (cannot be undone)
- Click the 📋 Audit Log tab
- All vault operations are logged with timestamps:
- Credential additions, access, sharing, deletions
- Vault lock/unlock events
- Failed password attempts
- Audit entries are encrypted when the vault is unlocked
- Click 🔒 Lock or press
Ctrl+L - The vault auto-locks after 15 minutes of inactivity
- Locking clears the encryption key from memory
| Shortcut | Action |
|---|---|
Ctrl+N / Cmd+N |
Add new credential |
Ctrl+L / Cmd+L |
Lock the vault |
Escape |
Close modal/dialog |
- Unlock the vault
- Your agent connects to
ws://localhost:8766 - Agent authenticates with the WebSocket token (found in
.ws-token) - Share credentials individually or use "Share All"
- The agent confirms receipt — sharing status is tracked per credential
┌─────────────────────────────────────────────────┐
│ IronVault │
│ │
│ ┌─────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ Web UI │◄──►│ Express │◄──►│ SQLite DB │ │
│ │ :8765 │ │ Server │ │ (encrypted) │ │
│ └─────────┘ └────┬─────┘ └──────────────┘ │
│ │ │
│ ┌────▼─────┐ ┌──────────────┐ │
│ │WebSocket │◄──►│ AI Agent │ │
│ │ :8766 │ │ (external) │ │
│ └──────────┘ └──────────────┘ │
│ │ │
│ ┌────▼─────┐ │
│ │ Audit │ │
│ │ Log │ │
│ └──────────┘ │
└─────────────────────────────────────────────────┘
Data Flow:
User ──► Master Password ──► PBKDF2 ──► 256-bit Key (RAM only)
│
Credential ──► AES-256-GCM + Random IV ──► Encrypted Value ──► SQLite
| File | Purpose |
|---|---|
vault.db |
SQLite database with encrypted credential values |
audit.log |
Encrypted security event log |
.ws-token |
WebSocket authentication token (0o600 permissions) |
| Platform | Path |
|---|---|
| macOS | ~/Library/Application Support/IronVault/ |
| Windows | %APPDATA%/IronVault/ |
| Linux | ~/.config/IronVault/ |
All endpoints run on http://localhost:8765. Endpoints marked 🔓 require the vault to be unlocked.
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/api/status |
— | Vault status (initialized, unlocked, key count, agent connected) |
POST |
/api/init |
— | Initialize vault with master password |
POST |
/api/unlock |
— | Unlock vault (rate limited: 5 attempts/15 min) |
POST |
/api/logout |
— | Lock vault (clears encryption key from memory) |
GET |
/api/keys |
🔓 | List all credentials (metadata only, no secret values) |
POST |
/api/keys |
🔓 | Add a new credential |
GET |
/api/keys/:id/value |
🔓 | Get decrypted credential value |
PUT |
/api/keys/:id |
🔓 | Update a credential (supports key rotation) |
DELETE |
/api/keys/:id |
🔓 | Delete a credential |
POST |
/api/keys/:id/share |
🔓 | Share credential with connected agent |
POST |
/api/keys/:id/unshare |
🔓 | Revoke sharing status |
POST |
/api/keys/share-all |
🔓 | Share all unshared credentials |
GET |
/api/audit |
🔓 | Get audit log (default: last 50 entries) |
GET |
/api/ws-token |
🔓 | Get WebSocket auth token |
GET |
/api/config |
🔓 | Get LLM configuration |
POST |
/api/config |
🔓 | Save LLM configuration (encrypted) |
POST |
/api/reset |
🔓 | Delete all vault data (irreversible) |
curl -X POST http://localhost:8765/api/keys \
-H "Content-Type: application/json" \
-d '{"name": "OpenAI Prod", "service": "openai", "value": "sk-..."}'curl http://localhost:8765/api/keys/CREDENTIAL_ID/valueIronVault runs a WebSocket server on port 8766 for real-time credential sharing with AI agents.
// Agent → IronVault
{ "type": "auth", "token": "<32-byte-hex-token-from-.ws-token>" }
// IronVault → Agent (success)
{ "type": "auth_success" }
// IronVault → Agent (failure — connection closed)
{ "type": "auth_failed", "error": "Invalid token" }// IronVault → Agent (shared credential)
{
"type": "shared_secret",
"keyId": "abc123...",
"timestamp": "2026-04-01T10:00:00Z",
"data": {
"name": "OpenAI Prod",
"service": "openai",
"url": "https://api.openai.com",
"value": "sk-..."
}
}
// Agent → IronVault (confirmation)
{
"type": "key_received",
"keyId": "abc123...",
"keyName": "OpenAI Prod",
"agentName": "My AI Agent"
}// Agent → IronVault
{ "type": "get_key", "keyId": "abc123..." }
// IronVault → Agent
{
"type": "key_data",
"keyId": "abc123...",
"data": { "name": "...", "service": "...", "value": "..." }
}PORT=8765 # HTTP server port (default: 8765)
WS_PORT=8766 # WebSocket port (default: 8766)
MAX_KEYS=20 # Maximum credentials per vault (default: 20)
TRUST_PROXY=true # Trust reverse proxy headers (for nginx/traefik)
FORCE_HTTPS=true # Force HTTPS redirect (production behind proxy)- Use descriptive names — "OpenAI Production" is better than "key1"
- Rotate regularly — IronVault tracks rotation intervals and reminds you
- Share selectively — only share credentials your agent actually needs
- Revoke when done — unshare credentials after agent tasks complete
- Back up
vault.dbregularly — this file contains all your encrypted credentials - Store backups encrypted — the vault file is encrypted, but keep backups in a secure location
- Remember your master password — without it, backups are useless
- Test restores — periodically verify your backup can be unlocked
- IronVault binds to
127.0.0.1only — it's not accessible from other machines - If you need remote access, use a reverse proxy with TLS (see
TRUST_PROXYandFORCE_HTTPS) - The WebSocket token in
.ws-tokenis sensitive — protect it like a password - Never expose ports 8765/8766 to the public internet
The vault auto-locks after 15 minutes of inactivity. Unlock it again with your master password.
After 5 failed password attempts, you're locked out for 15 minutes. Wait and try again.
Another instance of IronVault (or another service) is using port 8765/8766. Stop the other process or change the port via environment variables.
- Ensure the vault is unlocked
- Check the WebSocket token in
.ws-tokenmatches what your agent is using - Verify your agent is connecting to
ws://localhost:8766
Right-click the app → Open, then click Open in the dialog. Or go to System Settings → Privacy & Security and click Open Anyway.
There is no recovery mechanism. The encryption is designed so that without the password, data is unrecoverable. This is a security feature, not a bug. If you have a backup of vault.db, you'll still need the original password to unlock it.
MIT — see LICENSE.
IronVault — Your secrets, your machine, your control.