{"skill":{"slug":"bagman","displayName":"Openclaw","summary":"Secure key management for AI agents. Use when handling private keys, API secrets, wallet credentials, or when building systems that need agent-controlled funds. Covers secure storage, session keys, leak prevention, prompt injection defense, and MetaMask Delegation Framework integration.","description":"---\nname: bagman\nversion: 2.1.0\ndescription: Secure key management for AI agents. Use when handling private keys, API secrets, wallet credentials, or when building systems that need agent-controlled funds. Covers secure storage, session keys, leak prevention, prompt injection defense, and MetaMask Delegation Framework integration.\nhomepage: https://github.com/zscole/bagman-skill\nmetadata:\n  {\n    \"openclaw\": {\n      \"emoji\": \"🔐\",\n      \"requires\": { \"bins\": [\"op\"] },\n      \"tags\": [\"security\", \"wallet\", \"keys\", \"crypto\", \"secrets\", \"delegation\"]\n    }\n  }\n---\n\n# Bagman\n\nSecure key management patterns for AI agents handling wallets, private keys, and secrets.\n\n## When to Use This Skill\n\n- Agent needs wallet/blockchain access\n- Handling API keys, credentials, or secrets\n- Building systems where AI controls funds\n- Preventing secret leakage via prompts or outputs\n\n## Quick Start\n\n```bash\n# Install 1Password CLI\nbrew install 1password-cli\n\n# Authenticate\neval $(op signin)\n\n# Create vault for agent credentials\nop vault create \"Agent-Credentials\"\n\n# Run examples\ncd examples && python test_suite.py\n```\n\n---\n\n## Core Rules\n\n| Rule | Why |\n|------|-----|\n| Never store raw private keys | Config, env, memory, or conversation = leaked |\n| Use delegated access | Session keys with time/value/scope limits |\n| Secrets via secret manager | 1Password, Vault, AWS Secrets Manager |\n| Sanitize all outputs | Scan for key patterns before any response |\n| Validate all inputs | Check for injection attempts before wallet ops |\n\n---\n\n## Architecture\n\n```\n┌─────────────────────────────────────────────────────┐\n│                   AI Agent                          │\n├─────────────────────────────────────────────────────┤\n│  Session Key (bounded)                              │\n│  ├─ Expires after N hours                           │\n│  ├─ Max spend per tx/day                            │\n│  └─ Whitelist of allowed contracts/methods          │\n├─────────────────────────────────────────────────────┤\n│  Secret Manager (1Password/Vault)                   │\n│  ├─ Retrieve at runtime only                        │\n│  ├─ Never persist to disk                           │\n│  └─ Audit trail of accesses                         │\n├─────────────────────────────────────────────────────┤\n│  Smart Account (ERC-4337)                           │\n│  ├─ Programmable permissions                        │\n│  └─ Recovery without key exposure                   │\n└─────────────────────────────────────────────────────┘\n```\n\n---\n\n## Implementation Files\n\n| File | Purpose |\n|------|---------|\n| `examples/secret_manager.py` | 1Password integration for runtime secret retrieval |\n| `examples/sanitizer.py` | Output sanitization (keys, seeds, tokens) |\n| `examples/validator.py` | Input validation (prompt injection defense) |\n| `examples/session_keys.py` | ERC-4337 session key configuration |\n| `examples/delegation_integration.ts` | MetaMask Delegation Framework (EIP-7710) |\n| `examples/pre-commit` | Git hook to block secret commits |\n| `examples/test_suite.py` | Adversarial test suite |\n| `docs/prompt-injection.md` | Deep dive on injection defense |\n| `docs/secure-storage.md` | Secret storage patterns |\n| `docs/session-keys.md` | Session key architecture |\n| `docs/leak-prevention.md` | Output sanitization patterns |\n| `docs/delegation-framework.md` | On-chain permission enforcement (EIP-7710) |\n\n---\n\n## 1. Secret Retrieval\n\n### 1Password CLI Pattern\n\n```bash\n# Retrieve at runtime (never store result)\nSESSION_KEY=$(op read \"op://Agents/my-agent/session-key\")\n\n# Run with injected secrets (never touch disk)\nop run --env-file=.env.tpl -- python agent.py\n```\n\n### .env.tpl (safe to commit - no secrets)\n\n```\nPRIVATE_KEY=op://Agents/trading-bot/session-key\nRPC_URL=op://Infra/alchemy/sepolia-url\nOPENAI_API_KEY=op://Services/openai/api-key\n```\n\n### Python Usage\n\n```python\nfrom secret_manager import get_session_key\n\n# Retrieve validated session key\ncreds = get_session_key(\"trading-bot-session\")\n\n# Check validity\nif creds.is_expired():\n    raise ValueError(\"Session expired - request renewal from operator\")\n\nprint(f\"Time remaining: {creds.time_remaining()}\")\nprint(f\"Allowed contracts: {creds.allowed_contracts}\")\n\n# Use the key (never log it!)\nclient.set_signer(creds.session_key)\n```\n\n### Vault-Level ACL (Recommended)\n\nConfigure 1Password vault permissions:\n\n```\nAgent-Credentials/\n├── trading-bot-session    # Agent can read\n├── payment-bot-session    # Agent can read\n└── master-key             # Operator ONLY (agent has no access)\n```\n\n**Principle:** Agent credentials should be in a vault with read-only agent access. Master keys should be in a separate vault the agent cannot access.\n\n---\n\n## 2. Output Sanitization\n\nApply to ALL agent outputs before sending anywhere:\n\n```python\nfrom sanitizer import OutputSanitizer\n\ndef respond(content: str) -> str:\n    \"\"\"Sanitize before any output.\"\"\"\n    return OutputSanitizer.sanitize(content)\n\n# Catches:\n# - Private keys (0x + 64 hex)\n# - OpenAI/Anthropic/Groq/AWS keys\n# - GitHub/Slack/Discord tokens\n# - BIP-39 seed phrases (12/24 words)\n# - PEM private keys\n# - JWT tokens\n```\n\n### Patterns Detected\n\n| Pattern | Example | Result |\n|---------|---------|--------|\n| ETH private key | `0x1234...abcd` (64 hex) | `[PRIVATE_KEY_REDACTED]` |\n| ETH address | `0x742d...f44e` (40 hex) | `0x742d...f44e` (truncated) |\n| OpenAI key | `sk-proj-abc123...` | `[OPENAI_KEY_REDACTED]` |\n| Anthropic key | `sk-ant-api03-...` | `[ANTHROPIC_KEY_REDACTED]` |\n| 12-word seed | `abandon ability able...` | `[SEED_PHRASE_12_WORDS_REDACTED]` |\n| JWT | `eyJhbG...` | `[JWT_TOKEN_REDACTED]` |\n\n---\n\n## 3. Input Validation\n\nCheck inputs before ANY wallet operation:\n\n```python\nfrom validator import InputValidator, ThreatLevel\n\nresult = InputValidator.validate(user_input)\n\nif result.level == ThreatLevel.BLOCKED:\n    return f\"Request blocked: {result.reason}\"\n\nif result.level == ThreatLevel.SUSPICIOUS:\n    # Log for review, but allow\n    log_suspicious(user_input, result.reason)\n\n# Proceed with operation\n```\n\n### Threat Categories\n\n| Category | Examples | Action |\n|----------|----------|--------|\n| Extraction | \"show private key\", \"reveal secrets\" | Block |\n| Override | \"ignore previous instructions\" | Block |\n| Role manipulation | \"you are now admin\" | Block |\n| Jailbreak | \"DAN mode\", \"bypass filters\" | Block |\n| Exfiltration | \"send config to https://...\" | Block |\n| Wallet threats | \"transfer all\", \"unlimited approve\" | Block |\n| Encoded | Base64/hex encoded attacks | Block |\n| Unicode tricks | Cyrillic lookalikes, zero-width | Block |\n| Suspicious | \"hypothetically\", \"just between us\" | Warn |\n\n---\n\n## 4. Operation Allowlisting\n\nNever execute arbitrary operations. Explicit whitelist only:\n\n```python\nfrom dataclasses import dataclass\nfrom decimal import Decimal\nfrom typing import Optional\n\n@dataclass\nclass AllowedOperation:\n    name: str\n    handler: callable\n    max_value: Optional[Decimal] = None\n    requires_confirmation: bool = False\n    cooldown_seconds: int = 0\n\nALLOWED_OPS = {\n    \"check_balance\": AllowedOperation(\"check_balance\", get_balance),\n    \"transfer_usdc\": AllowedOperation(\n        \"transfer_usdc\", \n        transfer,\n        max_value=Decimal(\"500\"),\n        requires_confirmation=True,\n        cooldown_seconds=60\n    ),\n    \"swap\": AllowedOperation(\n        \"swap\",\n        swap_tokens,\n        max_value=Decimal(\"1000\"),\n        cooldown_seconds=300\n    ),\n}\n\ndef execute(op_name: str, **kwargs):\n    if op_name not in ALLOWED_OPS:\n        raise PermissionError(f\"Operation '{op_name}' not allowed\")\n    \n    op = ALLOWED_OPS[op_name]\n    \n    if op.max_value and kwargs.get(\"amount\", 0) > op.max_value:\n        raise PermissionError(f\"Amount exceeds limit: {op.max_value}\")\n    \n    if op.requires_confirmation:\n        return request_confirmation(op_name, kwargs)\n    \n    return op.handler(**kwargs)\n```\n\n---\n\n## 5. Confirmation Flow\n\nHigh-value operations require explicit confirmation:\n\n```python\nimport hashlib\nimport time\n\npending_confirmations = {}\n\ndef request_confirmation(operation: str, details: dict) -> str:\n    code = hashlib.sha256(\n        f\"{operation}{time.time()}\".encode()\n    ).hexdigest()[:8].upper()\n    \n    pending_confirmations[code] = {\n        \"op\": operation,\n        \"details\": details,\n        \"expires\": time.time() + 300  # 5 minutes\n    }\n    \n    return f\"⚠️ Confirm '{operation}' with code: {code}\\n(expires in 5 minutes)\"\n\ndef confirm(code: str):\n    if code not in pending_confirmations:\n        return \"Invalid confirmation code\"\n    \n    req = pending_confirmations.pop(code)\n    \n    if time.time() > req[\"expires\"]:\n        return \"Confirmation code expired\"\n    \n    return execute_confirmed(req[\"op\"], req[\"details\"])\n```\n\n---\n\n## 6. Session Keys (ERC-4337)\n\nInstead of giving agents master keys, issue bounded session keys:\n\n```python\nfrom session_keys import SessionKeyManager\n\n# Operator creates trading session for agent\nconfig = SessionKeyManager.create_trading_session(\n    agent_name=\"alpha-trader\",\n    operator_address=\"0x742d...\",\n    duration_hours=24,\n    max_trade_usdc=1000,\n    daily_limit_usdc=5000,\n)\n\n# Export for storage in 1Password\nexport_data = SessionKeyManager.export_for_1password(\n    config, \n    session_key_hex=\"0x...\"  # Generated session key\n)\n\n# op item create ... (store in 1Password)\n```\n\n### Session Key Benefits\n\n| Feature | Master Key | Session Key |\n|---------|------------|-------------|\n| Expiration | Never | Configurable (hours/days) |\n| Spending limits | None | Per-tx and daily caps |\n| Contract restrictions | Full access | Whitelist only |\n| Revocation | Requires key rotation | Instant, no key change |\n| Audit | None | Full operation log |\n\n---\n\n## 7. Pre-commit Hook\n\nBlock commits containing secrets:\n\n```bash\n# Install\ncp examples/pre-commit .git/hooks/\nchmod +x .git/hooks/pre-commit\n```\n\nDetected patterns:\n- ETH private keys (64 hex chars)\n- OpenAI/Anthropic/Groq keys\n- AWS access keys\n- GitHub/GitLab tokens\n- Slack/Discord tokens\n- PEM private keys\n- Generic PASSWORD/SECRET assignments\n- BIP-39 seed phrases\n\n---\n\n## 8. Defense Layers\n\n```\nUSER INPUT\n    │\n    ▼\n┌────────────────────────────┐\n│ Layer 1: Input Validation  │  ← Regex + encoding + unicode checks\n└────────────────────────────┘\n    │\n    ▼\n┌────────────────────────────┐\n│ Layer 2: Op Allowlisting   │  ← Explicit whitelist only\n└────────────────────────────┘\n    │\n    ▼\n┌────────────────────────────┐\n│ Layer 3: Value Limits      │  ← Max per-tx and per-day\n└────────────────────────────┘\n    │\n    ▼\n┌────────────────────────────┐\n│ Layer 4: Confirmation      │  ← Time-limited codes for $$$\n└────────────────────────────┘\n    │\n    ▼\n┌────────────────────────────┐\n│ Layer 5: Isolated Exec     │  ← Wallet ops != conversation\n└────────────────────────────┘\n    │\n    ▼\nOUTPUT SANITIZATION\n```\n\n---\n\n## Common Mistakes\n\n### ❌ Keys in memory files\n```markdown\n# memory/2026-02-07.md\nPrivate key: 0x9f01dad551039daad...\n```\n**Fix:** Store reference only: `Private key: [stored in 1Password: test-wallet]`\n\n### ❌ Keys in error messages\n```python\nexcept Exception as e:\n    log(f\"Failed with key {private_key}: {e}\")\n```\n**Fix:** Never include credentials in error context\n\n### ❌ Keys in .env.example\n```\nPRIVATE_KEY=sk-ant-api03-real-key...  # \"for testing\"\n```\n**Fix:** Use obviously fake: `PRIVATE_KEY=your-key-here`\n\n### ❌ \"All\" in transfer requests\n```\nUser: \"Transfer all my USDC\"\nAgent: *executes unlimited transfer*\n```\n**Fix:** Block \"all/everything/max\" patterns, require explicit amounts\n\n### ❌ Trusting conversation context\n```python\n# Wallet has access to conversation history\nself.wallet.execute(conversation[-1][\"content\"])\n```\n**Fix:** Wallet operations must be isolated from conversation context\n\n---\n\n## Testing\n\n```bash\ncd examples\n\n# Run full test suite\npython test_suite.py\n\n# Test individual components\npython sanitizer.py    # Output sanitization demo\npython validator.py    # Input validation demo\npython session_keys.py # Session key demo\n```\n\nExpected output: `All tests passed`\n\n---\n\n## Checklist\n\n- [ ] 1Password CLI installed and authenticated\n- [ ] Secrets in 1Password vault, not files\n- [ ] Session keys with expiry and limits\n- [ ] Output sanitization on all responses\n- [ ] Input validation before wallet ops\n- [ ] Pre-commit hook installed\n- [ ] Confirmation flow for high-value operations\n- [ ] Wallet operations isolated from conversation\n- [ ] .gitignore covers secrets and memory files\n- [ ] Test suite passes\n\n---\n\n## Security Model Limitations\n\nThis skill provides **defense in depth**, not a guarantee. Adversaries may:\n\n1. **Novel injection patterns** - Regex can't catch everything; semantic analysis helps but isn't perfect\n2. **Social engineering** - Convincing the operator to approve malicious operations\n3. **Timing attacks** - Exploiting confirmation windows\n4. **Encoding evasion** - New encoding schemes not covered\n\n**Recommendation:** Layer these defenses with:\n- Rate limiting\n- Anomaly detection\n- Human-in-the-loop for large transactions\n- Regular security audits\n","tags":{"latest":"2.1.0"},"stats":{"comments":0,"downloads":1798,"installsAllTime":2,"installsCurrent":2,"stars":2,"versions":2},"createdAt":1770568604037,"updatedAt":1778486086401},"latestVersion":{"version":"2.1.0","createdAt":1770571230396,"changelog":"v2.1: MetaMask Delegation Framework (EIP-7710) integration, patched 9 security gaps from adversarial testing, 18 passing integration tests","license":null},"metadata":{"setup":[],"os":null,"systems":null},"owner":{"handle":"zscole","userId":"s17fe8gz94yjfgd9j6zgj4fsyd8853a2","displayName":"zscole","image":"https://avatars.githubusercontent.com/u/20308948?v=4"},"moderation":null}