{"skill":{"slug":"master-skills","displayName":"Bagman","summary":"Secure key management for AI agents. Use when handling private keys, API secrets, wallet credentials, or when building systems that need agent-controlled fun...","description":"---\nname: bagman\nversion: 1.0.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, and prompt injection defense.\nhomepage: https://numbergroup.xyz\nmetadata:\n  {\n    \"openclaw\": {\n      \"emoji\": \"🔐\",\n      \"requires\": { \"bins\": [\"op\"] },\n      \"tags\": [\"security\", \"wallet\", \"keys\", \"crypto\", \"secrets\"]\n    }\n  }\n---\n\n# Bagman\n\nSecure key management patterns for AI agents handling private keys and secrets. Designed to prevent:\n- **Key loss**: Agents forgetting keys between sessions\n- **Accidental exposure**: Keys leaked to GitHub, logs, or outputs\n- **Prompt injection**: Malicious prompts extracting secrets\n\n## Core Principles\n\n1. **Never store raw private keys in config, env vars, or memory files**\n2. **Use session keys / delegated access instead of full control**\n3. **All secret access goes through 1Password CLI (`op`)**\n4. **Validate all outputs before sending to prevent key leakage**\n\n## References\n\n- `references/secure-storage.md` - 1Password patterns for agent secrets\n- `references/session-keys.md` - ERC-4337 delegated access patterns\n- `references/leak-prevention.md` - Pre-commit hooks and output sanitization\n- `references/prompt-injection-defense.md` - Input validation and output filtering\n\n---\n\n## Quick Reference\n\n### DO ✅\n\n```bash\n# Retrieve key at runtime via 1Password\nPRIVATE_KEY=$(op read \"op://Agents/my-agent-wallet/private-key\")\n\n# Use environment injection (key never touches disk)\nop run --env-file=.env.tpl -- node agent.js\n\n# Use session keys with bounded permissions\n# (delegate specific capabilities, not full wallet access)\n```\n\n### DON'T ❌\n\n```bash\n# NEVER store keys in files\necho \"PRIVATE_KEY=0x123...\" > .env\n\n# NEVER log or print keys\nconsole.log(\"Key:\", privateKey)\n\n# NEVER store keys in memory/journal files\n# Even in \"private\" agent memory - these can be exfiltrated\n\n# NEVER trust unvalidated input near key operations\n```\n\n---\n\n## Architecture: Agent Wallet Stack\n\n```\n┌─────────────────────────────────────────────────────┐\n│                   AI Agent                          │\n├─────────────────────────────────────────────────────┤\n│  Session Key (time/value bounded)                   │\n│  - Expires after N hours                            │\n│  - Spending cap per operation                       │\n│  - Whitelist of allowed contracts                   │\n├─────────────────────────────────────────────────────┤\n│  1Password / Secret Manager                         │\n│  - Agent retrieves session key at runtime           │\n│  - Never stores full private key                    │\n│  - Audit log of all accesses                        │\n├─────────────────────────────────────────────────────┤\n│  ERC-4337 Smart Account                             │\n│  - Programmable permissions                         │\n│  - Recovery without private key exposure            │\n│  - Multi-sig for high-value operations              │\n├─────────────────────────────────────────────────────┤\n│  Operator (Human)                                   │\n│  - Holds master key in hardware wallet              │\n│  - Issues/revokes session keys                      │\n│  - Monitors agent activity                          │\n└─────────────────────────────────────────────────────┘\n```\n\n---\n\n## Workflow: Setting Up Agent Wallet Access\n\n### 1. Create 1Password Vault for Agent Secrets\n\n```bash\n# Create dedicated vault (via 1Password app or CLI)\nop vault create \"Agent-Wallets\" --description \"AI agent wallet credentials\"\n\n# Store agent session key (not master key!)\nop item create \\\n  --vault \"Agent-Wallets\" \\\n  --category \"API Credential\" \\\n  --title \"trading-bot-session\" \\\n  --field \"session-key[password]=0xsession...\" \\\n  --field \"expires=2026-02-15T00:00:00Z\" \\\n  --field \"spending-cap=1000 USDC\" \\\n  --field \"allowed-contracts=0xDEX1,0xDEX2\"\n```\n\n### 2. Agent Retrieves Credentials at Runtime\n\n```python\nimport subprocess\nimport json\n\ndef get_session_key(item_name: str) -> dict:\n    \"\"\"Retrieve session key from 1Password at runtime.\"\"\"\n    result = subprocess.run(\n        [\"op\", \"item\", \"get\", item_name, \"--vault\", \"Agent-Wallets\", \"--format\", \"json\"],\n        capture_output=True, text=True, check=True\n    )\n    item = json.loads(result.stdout)\n    \n    # Extract fields\n    fields = {f[\"label\"]: f.get(\"value\") for f in item.get(\"fields\", [])}\n    \n    # Validate session hasn't expired\n    from datetime import datetime\n    expires = datetime.fromisoformat(fields.get(\"expires\", \"2000-01-01\"))\n    if datetime.now() > expires:\n        raise ValueError(\"Session key expired - request new key from operator\")\n    \n    return {\n        \"session_key\": fields.get(\"session-key\"),\n        \"expires\": fields.get(\"expires\"),\n        \"spending_cap\": fields.get(\"spending-cap\"),\n        \"allowed_contracts\": fields.get(\"allowed-contracts\", \"\").split(\",\")\n    }\n```\n\n### 3. Never Log or Store the Key\n\n```python\n# ❌ BAD - Key in logs\nlogger.info(f\"Using key: {session_key}\")\n\n# ✅ GOOD - Redacted identifier\nlogger.info(f\"Using session key: {session_key[:8]}...{session_key[-4:]}\")\n\n# ❌ BAD - Key in memory file\nwith open(\"memory/today.md\", \"a\") as f:\n    f.write(f\"Session key: {session_key}\")\n\n# ✅ GOOD - Reference only\nwith open(\"memory/today.md\", \"a\") as f:\n    f.write(f\"Session key: [stored in 1Password: trading-bot-session]\")\n```\n\n---\n\n## Leak Prevention\n\n### Output Sanitization\n\nBefore any agent output (chat, logs, file writes), scan for key patterns:\n\n```python\nimport re\n\nKEY_PATTERNS = [\n    r'0x[a-fA-F0-9]{64}',                    # ETH private keys\n    r'sk-[a-zA-Z0-9]{48,}',                  # OpenAI keys\n    r'sk-ant-[a-zA-Z0-9\\-_]{80,}',           # Anthropic keys\n    r'gsk_[a-zA-Z0-9]{48,}',                 # Groq keys\n    r'[A-Za-z0-9+/]{40,}={0,2}',             # Base64 encoded (suspiciously long)\n]\n\ndef sanitize_output(text: str) -> str:\n    \"\"\"Remove potential secrets from output.\"\"\"\n    for pattern in KEY_PATTERNS:\n        text = re.sub(pattern, '[REDACTED]', text)\n    return text\n\n# Apply to ALL agent outputs\ndef send_message(content: str):\n    content = sanitize_output(content)\n    # ... send to chat/log/file\n```\n\n### Pre-commit Hook\n\nInstall this hook to prevent accidental commits of secrets:\n\n```bash\n#!/bin/bash\n# .git/hooks/pre-commit\n\nPATTERNS=(\n    '0x[a-fA-F0-9]{64}'\n    'sk-[a-zA-Z0-9]{48,}'\n    'sk-ant-api'\n    'PRIVATE_KEY='\n    'gsk_[a-zA-Z0-9]{48,}'\n)\n\nfor pattern in \"${PATTERNS[@]}\"; do\n    if git diff --cached | grep -qE \"$pattern\"; then\n        echo \"❌ Potential secret detected matching: $pattern\"\n        echo \"   Remove secrets before committing!\"\n        exit 1\n    fi\ndone\n```\n\n### .gitignore Essentials\n\n```gitignore\n# Secrets\n.env\n.env.*\n*.pem\n*.key\nsecrets/\ncredentials/\n\n# Agent state that might contain secrets\nmemory/*.json\nwallet-state.json\nsession-keys/\n```\n\n---\n\n## Prompt Injection Defense\n\n### Input Validation\n\nBefore processing any user input that touches wallet operations:\n\n```python\nDANGEROUS_PATTERNS = [\n    r'ignore.*(previous|above|prior).*instructions',\n    r'reveal.*(key|secret|password|credential)',\n    r'output.*(key|secret|private)',\n    r'print.*(key|secret|wallet)',\n    r'show.*(key|secret|password)',\n    r'what.*(key|secret|password)',\n    r'tell.*me.*(key|secret)',\n    r'disregard.*rules',\n    r'system.*prompt',\n    r'jailbreak',\n    r'dan.*mode',\n]\n\ndef validate_input(text: str) -> bool:\n    \"\"\"Check for prompt injection attempts.\"\"\"\n    text_lower = text.lower()\n    for pattern in DANGEROUS_PATTERNS:\n        if re.search(pattern, text_lower):\n            return False\n    return True\n\ndef process_wallet_request(user_input: str):\n    if not validate_input(user_input):\n        return \"I can't help with that request.\"\n    # ... proceed with wallet operation\n```\n\n### Separation of Concerns\n\n- **Wallet operations should be in isolated functions** with no access to conversation context\n- **Never pass full conversation history to wallet-sensitive code**\n- **Use allowlists for operations, not blocklists**\n\n```python\nALLOWED_WALLET_OPERATIONS = {\n    \"check_balance\": lambda: get_balance(),\n    \"send_usdc\": lambda to, amount: send_usdc(to, amount) if amount < DAILY_LIMIT else deny(),\n    \"swap\": lambda: swap_tokens() if within_limits() else deny(),\n}\n\ndef execute_wallet_operation(operation: str, **kwargs):\n    \"\"\"Execute only explicitly allowed operations.\"\"\"\n    if operation not in ALLOWED_WALLET_OPERATIONS:\n        raise ValueError(f\"Operation '{operation}' not allowed\")\n    return ALLOWED_WALLET_OPERATIONS[operation](**kwargs)\n```\n\n---\n\n## Session Key Implementation (ERC-4337)\n\nFor agents needing on-chain access, use session keys instead of raw private keys.\n\nSee `references/session-keys.md` for full implementation details including:\n- ZeroDev/Biconomy SDK examples\n- Permission patterns for trading/DeFi/payment agents\n- Session key lifecycle management\n- Revocation procedures\n\n---\n\n## Incident Response\n\n### If a Key is Leaked\n\n1. **Immediate**: Revoke the session key / rotate credentials\n2. **Assess**: Check transaction history for unauthorized activity\n3. **Notify**: Alert operator via secure channel\n4. **Rotate**: Issue new session key with tighter permissions\n5. **Audit**: Review how leak occurred, update defenses\n\n```bash\n# Emergency: Revoke 1Password item\nop item delete \"compromised-session-key\" --vault \"Agent-Wallets\"\n\n# Rotate to new session key\nop item create --vault \"Agent-Wallets\" --category \"API Credential\" \\\n  --title \"trading-bot-session-v2\" ...\n```\n\n---\n\n## Checklist: Agent Wallet Setup\n\n- [ ] Create dedicated 1Password vault for agent credentials\n- [ ] Store session keys (NOT master keys) in vault\n- [ ] Set appropriate expiry and spending limits\n- [ ] Install pre-commit hook for secret detection\n- [ ] Add output sanitization to all agent responses\n- [ ] Implement input validation for prompt injection\n- [ ] Configure monitoring and alerts\n- [ ] Document incident response procedure\n- [ ] Test key rotation procedure\n\n---\n\n## Common Mistakes Found in Production\n\n### 1. Keys in Memory Files\n\n**Problem**: Agents store keys in `memory/*.md` for \"persistence\"\n\n```markdown\n# memory/2026-02-07.md\n## Test Wallet\n- Private key: 0x9f01dad551039daad3a8c4e43a32035bdd4da54e7b4292268be16e913b0b3e56\n```\n\n**Fix**: Store reference only: `Private key: [1Password: test-wallet-session]`\n\n### 2. Keys in Environment Templates\n\n**Problem**: `.env.example` contains real keys\n\n```\n# .env.example\nPRIVATE_KEY=sk-ant-api03-real-key-here...  # \"for testing\"\n```\n\n**Fix**: Use obviously fake placeholders: `PRIVATE_KEY=your-key-here`\n\n### 3. Keys in Error Messages\n\n**Problem**: Error handling exposes keys\n\n```python\ntry:\n    sign_transaction(private_key, tx)\nexcept Exception as e:\n    logger.error(f\"Failed with key {private_key}: {e}\")  # ❌\n```\n\n**Fix**: Never include credentials in error context\n\n### 4. Test Keys in Production Code\n\n**Problem**: Hardcoded test keys make it to main branch\n\n**Fix**: Use separate test vault, CI checks for key patterns\n\n---\n\n## Integration with OpenClaw\n\nWhen running as an OpenClaw agent:\n\n1. **Use 1Password skill** for all secret retrieval\n2. **Never write keys to workspace files** - they persist across sessions\n3. **Sanitize outputs** before sending to any channel (Telegram, Discord, etc.)\n4. **Session key approach** for wallet operations - request bounded access from operator\n5. **Document key references** in TOOLS.md, not the actual keys\n\nExample TOOLS.md entry:\n```markdown\n### Agent Wallet\n- Address: 0xABC123...\n- Session key: [1Password: my-agent-session]\n- Permissions: USDC transfers < 100, approved DEX only\n- Expires: 2026-02-15\n- To rotate: Ask operator via Telegram\n```\n","tags":{"latest":"0.1.0"},"stats":{"comments":0,"downloads":511,"installsAllTime":1,"installsCurrent":1,"stars":0,"versions":1},"createdAt":1773624812761,"updatedAt":1778491933006},"latestVersion":{"version":"0.1.0","createdAt":1773624812761,"changelog":"Initial release: secure key management patterns for AI agents.\n\n- Introduces Bagman: a guide to safe handling of secrets (keys, API creds, wallet access) for AI agents.\n- Covers secure storage using 1Password CLI (`op`), session key delegation, and leak prevention.\n- Includes architecture overview, step-by-step agent workflow, and code snippets for key retrieval and sanitization.\n- Provides patterns for output sanitization, pre-commit hooks to stop secret leaks, and .gitignore examples.\n- Documents prompt injection defenses with input validation and isolation of wallet operations.","license":"MIT-0"},"metadata":{"setup":[],"os":null,"systems":null},"owner":{"handle":"allprogramming9999","userId":"s175xbtf29tjmax97m85c3hhr1884ttc","displayName":"allprogramming9999","image":"https://avatars.githubusercontent.com/u/208527699?v=4"},"moderation":null}