Overview
IronClaw stores all credentials (API keys, tokens, passwords) in AES-256-GCM encrypted form. Secrets are never exposed to WASM tools; instead, they are injected at the host boundary during HTTP requests.Security Model
Encryption
Master Key
The master key encrypts all secrets. It can come from:- OS Keychain (recommended): Auto-generated and stored securely in your system keychain
- Environment variable: Set
SECRETS_MASTER_KEYfor CI/Docker deployments
Key Derivation (HKDF-SHA256)
Each secret gets its own derived key using HKDF:- Same plaintext → different ciphertext (due to unique salt)
- Key rotation doesn’t require re-encrypting all secrets
- Salt is stored alongside the encrypted value
Authenticated Encryption (AES-256-GCM)
Secrets are encrypted with AES-256 in GCM (Galois/Counter Mode):- Confidentiality: Ciphertext reveals nothing about plaintext
- Integrity: Tampering is detected via authentication tag
- Nonce uniqueness: Each encryption uses a fresh random nonce
GCM mode provides authenticated encryption, meaning any modification to the ciphertext will be detected during decryption.
Secret Storage
Database Schema
Secrets are stored in PostgreSQL (or libSQL for embedded deployments):Field Descriptions
| Field | Purpose |
|---|---|
encrypted_value | Nonce + ciphertext + auth tag |
key_salt | Salt for HKDF key derivation |
provider | Optional: which service this secret is for |
expires_at | Optional: expiration timestamp |
last_used_at | Last injection timestamp (for audit) |
usage_count | Number of times injected (for monitoring) |
Secret names are case-insensitive and unique per user. Storing a secret with the same name replaces the previous value.
Credential Injection
When Secrets Are Decrypted
Secrets are decrypted only when:- A WASM tool makes an HTTP request
- The target host matches a credential mapping
- The secret name is in the tool’s
allowed_secretslist
- Listing secrets (only names and metadata)
- Checking existence (
secret_existshost function) - Tool output or logs
Injection Locations
Secrets can be injected into different parts of HTTP requests:Authorization Bearer
Authorization Basic
Custom Header
Query Parameter
Credential Registry
TheSharedCredentialRegistry aggregates mappings from all installed tools:
- Append-only: Mappings accumulate as tools are installed
- Thread-safe: Uses
RwLockfor concurrent access - Host matching: Supports exact and wildcard patterns
- Cleanup: Mappings removed when tools are unregistered
Leak Detection
Scanning Pipeline
Secrets are scanned at two points:- Before outbound requests: Prevents exfiltration via URL, headers, or body
- After responses/outputs: Prevents accidental exposure in logs or returned data
Detection Patterns
The leak detector recognizes common secret formats:| Pattern | Example | Action |
|---|---|---|
| OpenAI API key | sk-proj-abc123... | Block |
| Anthropic API key | sk-ant-api03-abc... | Block |
| AWS Access Key | AKIAIOSFODNN7EXAMPLE | Block |
| GitHub Token | ghp_xxxxxxxxxxxx... | Block |
| Stripe Key | sk_live_abc123... | Block |
| Bearer Token | Bearer eyJhbGc... | Redact |
| High-entropy hex | 64-char hex string | Warn |
The leak detector uses Aho-Corasick for fast multi-pattern matching plus regex for complex patterns. See
leak_detector.rs for the full list.Actions on Detection
- Block: Reject the entire request/output
- Redact: Replace secret with
[REDACTED] - Warn: Log a warning but allow
Masked Previews
When a leak is detected, the log shows a masked preview:Access Control
Allowed Secrets List
Each tool declares which secrets it can use:openai_key→ exact matchopenai_*→ matchesopenai_key,openai_org, etc.
Permission Check
AccessDenied.
Usage Tracking
Audit Trail
Every time a secret is injected, the database records:- Detect unused secrets (candidates for removal)
- Monitor excessive usage (potential compromise)
- Audit which tools accessed which secrets
Example Queries
Secret Expiration
Setting Expiration
Expired secrets remain in the database but are inaccessible. Delete them manually to free storage.
Best Practices
For Users
- Use short-lived credentials: Set expiration dates when possible
- Rotate regularly: Update secrets every 90 days minimum
- Monitor usage: Check
last_used_atfor suspicious activity - Secure master key: Never commit
SECRETS_MASTER_KEYto version control - Backup carefully: Encrypted secrets are useless without the master key
For Developers
- Minimize scope: Only request secrets your tool actually needs
- Use credential mappings: Let IronClaw handle injection instead of requesting secrets directly
- Log carefully: Never log decrypted secret values
- Handle errors gracefully: Don’t expose secret names in user-facing errors
- Test with dummy secrets: Use fake credentials for development
For System Administrators
- Use keychain on workstations: More secure than environment variables
- Use environment variables in CI/Docker: Pass via secure secrets managers
- Enable encryption at rest: Encrypt database backups
- Audit access: Log all secret retrievals for forensics
- Implement key rotation: Have a plan for rotating the master key
Configuration
Master Key from Environment
Master Key from Keychain
On first run, IronClaw will:- Generate a random 32-byte key
- Store it in your OS keychain (Keychain Access on macOS, Credential Manager on Windows, Secret Service on Linux)
- Load it automatically on subsequent runs
In-Memory Store (Testing)
For tests or ephemeral deployments:Related Sections
- WASM Sandbox - Capability-based tool isolation
- Prompt Injection Defense - Input validation and sanitization
- Data Protection - Database encryption and local storage
