Skip to main content

Security Model (AI-Safe Access)

secretctl follows the "Access Without Exposure" principle, ensuring AI agents can use your secrets without ever seeing them.

Core Principles​

  1. AI agents never receive plaintext secrets
  2. Secrets are injected as environment variables at runtime
  3. Command output is automatically sanitized to redact leaked secrets
  4. A policy file controls which commands AI can execute

This design aligns with industry best practices for secrets management.

How It Works​

┌─────────────┐     ┌──────────────────┐     ┌─────────────┐
│ AI Agent │────▶│ secretctl MCP │────▶│ Command │
│ (Claude) │ │ Server │ │ (aws, etc) │
└─────────────┘ └──────────────────┘ └─────────────┘
│ │ │
│ "Run aws s3 ls │ Inject secrets │
│ with aws/*" │ as env vars │
│ │ │
▼ ▼ ▼
Never sees Manages secrets Receives env
secret values and policy vars securely

What AI Agents Can Do​

CapabilityDescription
List secretsSee key names and metadata (not values)
Check existenceVerify if a secret key exists
Get masked valuesSee last 4 characters only (****WXYZ)
Run commandsExecute allowed commands with secrets injected

What AI Agents Cannot Do​

RestrictionReason
Read plaintextNo secret_get tool exists
Access blocked commandsPolicy enforcement
Bypass output sanitizationAutomatic redaction
Run arbitrary commandsAllowlist-only policy

Policy Configuration​

Deny-by-Default​

Always use default_action: deny in your policy:

version: 1
default_action: deny # Recommended
allowed_commands:
- aws
- gcloud
- kubectl

Commands Blocked by Default​

Even with default_action: allow, these commands are always blocked:

  • env - Can leak all environment variables
  • printenv - Can leak all environment variables
  • set - Can leak shell state
  • export - Can leak all exports

Denied Commands​

Explicitly deny dangerous commands:

denied_commands:
- rm
- dd
- mkfs

Output Sanitization​

When a command is executed via secret_run, the output is automatically scanned for secret values. Any matches are replaced with [REDACTED:key].

Example:

If aws/secret_key contains AKIAIOSFODNN7EXAMPLE:

# Original output
Access key: AKIAIOSFODNN7EXAMPLE

# Sanitized output
Access key: [REDACTED:aws/secret_key]

Limitations​

Output sanitization uses exact string matching. It does not detect:

  • Base64-encoded secrets
  • Hex-encoded secrets
  • Partial string matches

Threat Categories​

secretctl's AI-Safe Access design protects against these threat categories:

1. Direct Secret Exposure​

ThreatProtectionStatus
AI requests plaintext secretNo secret_get tool exists✅ Mitigated
AI extracts from command outputOutput sanitization✅ Mitigated
AI infers from partial dataFixed-length masking (****WXYZ)✅ Mitigated

2. Prompt Injection Attacks​

ThreatProtectionStatus
Malicious prompt requests secretsTool-level restrictions✅ Mitigated
Injected command in secret_runCommand allowlist policy✅ Mitigated
Encoded secret extractionNot detected (see limitations)⚠️ Not Mitigated

3. Command Execution Risks​

ThreatProtectionStatus
Environment variable dumpenv/printenv/set blocked✅ Mitigated
Shell escape sequencesCommand validation✅ Mitigated
Timeout/resource exhaustion300s timeout, resource limits✅ Mitigated
Arbitrary command executionDeny-by-default policy✅ Mitigated

4. Indirect Disclosure​

ThreatProtectionStatus
Timing attacksNot applicable (local only)N/A
Side-channel via output lengthFixed masking format✅ Mitigated
Model training data leakageNo plaintext to AI✅ Mitigated

Sanitization Details​

Sanitization uses exact string matching to replace secret values in command output.

What IS Detected​

PatternExampleReplacement
Exact matchAKIAIOSFODNN7EXAMPLE[REDACTED:aws/key]
In JSON output{"key": "secret123"}{"key": "[REDACTED:api/key]"}
In URLshttps://api.example.com?token=abc123[REDACTED:api/token]

What is NOT Detected​

⚠️ Known Limitations:

PatternExampleWhy Not Detected
Base64 encodingQUtJQUlPU0ZPRE5ON0VYQU1QTEU=Only exact match
Hex encoding414b494149...Only exact match
URL encoding%41%4B%49%41...Only exact match
Partial matchesFirst 10 chars of secretOnly exact match
Case variationsSECRET123 vs secret123Case-sensitive match
Split outputSEC + RET123 (across lines)Single-pass detection
Compressed datagzip/deflate encodedBinary not scanned

Sanitization Timing​

Command executes → stdout/stderr captured → Sanitization runs → Result to AI
↑
All secret values checked

Important: Sanitization happens after command completion. Secrets are exposed to the subprocess but never returned to the AI.

Best Practices​

  1. Use strong master password - The MCP server requires your master password
  2. Limit allowed commands - Only allow commands you actually need
  3. Review policy regularly - Audit your allowed commands list
  4. Use key prefixes - Organize secrets with prefixes (e.g., aws/, db/)
  5. Set expirations - Use --expires when setting sensitive secrets
  6. Monitor audit logs - Check secretctl audit list for unusual activity
  7. Avoid encoding secrets - Don't store base64/hex encoded values as secrets
  8. Use short-lived tokens - Prefer tokens with expiration over long-lived credentials