AI agent wallets are high-value targets. An agent running 24/7 with autonomous withdrawal permissions, funded by its operator, and potentially holding weeks of accumulated trading profits is exactly what attackers look for. The vector is almost always the same: a leaked API key. Not a sophisticated exploit of the platform, not a blockchain vulnerability — a plain text secret found in a git commit, a log file, a Docker environment variable, or a teammate's compromised laptop.
This guide covers the complete security lifecycle for an AI agent's Purple Flea wallet: the threat model, key hygiene practices, self-imposed rate limits, anomaly detection, multi-sig for large balances, cold storage strategy, and the exact steps to take if you suspect a breach.
The most common breach vector: Hardcoded API keys committed to a public GitHub repository. GitHub's secret scanning catches many of these, but not all. Once a key appears in git history, it must be treated as permanently compromised — even after deletion, it may have been scraped.
1. The Threat Model
Understanding what an attacker wants helps you prioritize defenses. For agent wallets, there are two primary attack goals:
| Attack Type | Severity | Description | Defense |
|---|---|---|---|
| Key Sweep | CRITICAL | Attacker finds a withdrawal-capable API key and sweeps the full wallet balance to their address in a single transaction | Withdrawal limits, IP whitelisting, withdrawal key isolation |
| Payment Redirect | HIGH | Attacker uses a compromised key to change the wallet's default payout address, then waits for the next legitimate withdrawal | Address change notifications, 24h delay on address updates |
| Slow Drain | HIGH | Small, frequent unauthorized withdrawals below anomaly thresholds, designed to avoid alerting the operator | Baseline monitoring, daily reconciliation, transaction logging |
| API Abuse | MEDIUM | Compromised key used to place losing trades, wager at the casino, or register junk domains — depleting balance without direct withdrawal | Separate read-only vs action keys, trading limits, per-service key isolation |
| Social Engineering | MEDIUM | Attacker poses as Purple Flea support, tricks operator into sharing key or granting API access | Purple Flea will never ask for your API key; treat all such requests as attacks |
2. API Key Security
Never Hardcode API Keys
The single most common mistake — and the single most impactful fix. Never put an API key in source code. Not even in a private repository. Private repos get made public. Private repos get cloned to compromised machines. Private repos get forked and the fork becomes public.
# WRONG: hardcoded API key in source code WALLET_KEY = "pf_live_wallet_a7x2k9mq4r8bz3..." # DO NOT DO THIS response = requests.get(url, headers={"Authorization": f"Bearer {WALLET_KEY}"})
import os from dotenv import load_dotenv load_dotenv() # loads from .env file (never committed to git) # Correct: load from environment WALLET_KEY = os.environ["PF_WALLET_KEY"] # raises if missing — intentional # Optional: validate format before use if not WALLET_KEY.startswith("pf_live_"): raise ValueError("Invalid PF_WALLET_KEY format")
Your .env file should be listed in .gitignore before the file is created. Add it now, even if you're not using it yet:
.env .env.local .env.production *.key secrets/ credentials.json
Rotate Keys Every 30 Days
Key rotation limits the blast radius of a slow-draining compromise that hasn't been detected. If your key is rotated every 30 days and an attacker gained access on day 1, they have at most 30 days of window — not indefinite access. Set a calendar reminder. The Purple Flea Wallet API supports creating new keys and immediately invalidating old ones without any service interruption:
# Create new key (returns new key value) curl -X POST https://wallet.purpleflea.com/api/v1/keys \ -H "Authorization: Bearer $PF_WALLET_KEY" \ -d '{"name":"agent-primary","permissions":["read","withdraw"]}' # Invalidate the old key (pass old key ID, use new key to auth) curl -X DELETE https://wallet.purpleflea.com/api/v1/keys/$OLD_KEY_ID \ -H "Authorization: Bearer $NEW_PF_WALLET_KEY"
Separate Read-Only vs Withdrawal Keys
Most agent operations — checking balance, fetching transaction history, polling rates — don't require withdrawal permissions. Create a read-only key for these operations. Only the withdrawal key needs withdrawal scope, and it should be stored more carefully than the read-only key.
import os from dotenv import load_dotenv load_dotenv() # Read-only key: safe to use in monitoring, logging, dashboards WALLET_READ_KEY = os.environ["PF_WALLET_READ_KEY"] # Withdrawal key: never log, never pass to sub-functions, never expose WALLET_WITHDRAW_KEY = os.environ["PF_WALLET_WITHDRAW_KEY"] def get_balance(): # Uses read-only key — safe to call anywhere r = requests.get( "https://wallet.purpleflea.com/api/v1/balance", headers={"Authorization": f"Bearer {WALLET_READ_KEY}"} ) return r.json()["balance_usdc"] def withdraw(amount: float, address: str): # Uses withdrawal key — only called from secure, audited paths return requests.post( "https://wallet.purpleflea.com/api/v1/withdraw", headers={"Authorization": f"Bearer {WALLET_WITHDRAW_KEY}"}, json={"amount_usdc": amount, "to_address": address} )
3. Self-Imposed Withdrawal Limits
Purple Flea supports configurable withdrawal limits at the API level. Even if an attacker obtains your withdrawal key, a hard daily limit caps their maximum extraction. Set limits low — you can always temporarily increase them through a verified action when you need a large withdrawal.
# Set withdrawal limits on your account curl -X POST https://wallet.purpleflea.com/api/v1/limits \ -H "Authorization: Bearer $PF_WALLET_WITHDRAW_KEY" \ -H "Content-Type: application/json" \ -d '{ "daily_withdrawal_limit_usdc": 500, "single_withdrawal_max_usdc": 200, "withdrawal_cooldown_minutes": 60, "require_confirmation_above_usdc": 100 }'
Recommended limits: Set your daily withdrawal limit to 2–3x your expected daily operational need. If your agent typically withdraws $50/day in profits, set the daily limit to $150. This caps attacker extraction while not interrupting normal operations.
4. Monitor for Anomalies
A 3× spike in daily withdrawal volume is the clearest possible signal of unauthorized access. Set up automated monitoring that alerts you when this threshold is crossed. The following script can run as a cron job every hour:
import requests, os, statistics from datetime import datetime, timedelta WALLET_READ_KEY = os.environ["PF_WALLET_READ_KEY"] ALERT_WEBHOOK = os.environ["ALERT_WEBHOOK_URL"] # Slack/Discord webhook HEADERS = {"Authorization": f"Bearer {WALLET_READ_KEY}"} def get_daily_withdrawal_amounts(days=30): "Return list of daily withdrawal totals for the past N days" since = (datetime.now() - timedelta(days=days)).isoformat() txns = requests.get( "https://wallet.purpleflea.com/api/v1/transactions", headers=HEADERS, params={"type": "withdrawal", "from": since} ).json()["items"] # Aggregate by day daily = {} for t in txns: day = t["created_at"][:10] daily[day] = daily.get(day, 0) + float(t["amount"]) return list(daily.values()) def check_anomaly(): amounts = get_daily_withdrawal_amounts(30) if len(amounts) < 7: return # Not enough history baseline = statistics.mean(amounts[:-1]) # all but today today = amounts[-1] if baseline > 0 and today > baseline * 3: send_alert( f"ANOMALY: Today's withdrawals ${today:.2f} are {today/baseline:.1f}x" f" the 30-day average (${baseline:.2f}). Check immediately." ) def send_alert(message: str): requests.post(ALERT_WEBHOOK, json={"text": f":rotating_light: PF Security Alert: {message}"}) print(f"ALERT SENT: {message}") check_anomaly()
Run this as a cron job or scheduled task every hour. The 3× threshold is a starting point — adjust based on your agent's typical withdrawal volatility. High-frequency trading agents may have more variable daily patterns; adjust to 5× or use standard deviation-based thresholds instead.
5. Multi-Sig for Large Balances
For wallets holding more than $1,000 USDC at any time, consider using Purple Flea's multi-sig withdrawal feature. Multi-sig requires that a withdrawal be approved by M-of-N keys before execution. For a 2-of-3 setup:
- Key 1: Your agent's hot key (automated, in environment)
- Key 2: Your personal key (on a hardware device you control)
- Key 3: Cold backup (written down, stored offline)
A single compromised key is no longer sufficient to withdraw. An attacker who obtains your agent's hot key cannot complete a withdrawal without Key 2 (which is in your personal hardware device). This changes the attack from "find one key" to "compromise two independent systems simultaneously" — a dramatically harder task.
# Enable 2-of-3 multi-sig on your wallet curl -X POST https://wallet.purpleflea.com/api/v1/multisig/setup \ -H "Authorization: Bearer $PF_WALLET_WITHDRAW_KEY" \ -H "Content-Type: application/json" \ -d '{ "threshold": 2, "signers": [ {"key_id": "agent-hot-key-id", "label": "Agent Hot Key"}, {"key_id": "personal-hw-key-id", "label": "Operator Hardware Key"}, {"key_id": "cold-backup-key-id", "label": "Cold Backup"} ], "apply_above_usdc": 500 }' # Multi-sig only applies to withdrawals above 500 USDC # Smaller operational withdrawals remain single-key for agent autonomy
Balance threshold guidance: Below $200 — single hot key is fine, limits are sufficient. $200–$1,000 — consider multi-sig for withdrawals above $500. Above $1,000 — multi-sig required for all large withdrawals; keep the agent's operational hot wallet below $200 at all times.
6. Cold Storage Strategy
The rule of thumb: keep no more than 10% of your total Purple Flea earnings in an agent's hot wallet at any time. The rest should be in cold storage — a wallet whose private key has never touched an internet-connected machine.
The operational workflow:
- Agent earns income via trading, casino, referrals, escrow.
- Daily or weekly, a scheduled job checks the hot wallet balance.
- If balance exceeds the working capital threshold (e.g., $100), the excess is swept to a cold address.
- The cold address is pre-configured; the sweep is automatic but requires the cold address to be allowlisted.
import requests, os WALLET_READ_KEY = os.environ["PF_WALLET_READ_KEY"] WALLET_WITHDRAW_KEY = os.environ["PF_WALLET_WITHDRAW_KEY"] COLD_ADDRESS = os.environ["PF_COLD_STORAGE_ADDRESS"] # never changes HOT_WALLET_CAP = float(os.environ.get("PF_HOT_WALLET_CAP", "100")) def sweep_to_cold(): balance = requests.get( "https://wallet.purpleflea.com/api/v1/balance", headers={"Authorization": f"Bearer {WALLET_READ_KEY}"} ).json()["balance_usdc"] excess = balance - HOT_WALLET_CAP if excess <= 0: print(f"Balance ${balance:.2f} — no sweep needed") return print(f"Sweeping ${excess:.2f} to cold storage...") result = requests.post( "https://wallet.purpleflea.com/api/v1/withdraw", headers={"Authorization": f"Bearer {WALLET_WITHDRAW_KEY}"}, json={ "amount_usdc": round(excess, 2), "to_address": COLD_ADDRESS, "memo": "scheduled-cold-sweep" } ) print(f"Sweep result: {result.json()['status']}") sweep_to_cold() # Schedule this daily via cron: 0 2 * * * python3 /opt/agent/sweep_to_cold.py
7. Incident Response
If you suspect your wallet has been breached — unusual transactions, unexpected balance changes, withdrawal confirmations you didn't initiate — act immediately. Speed is everything. Here are the steps in order:
-
1Revoke all API keys immediately
Log into the Purple Flea dashboard and revoke every active API key. Do not stop to investigate first — revoke first, investigate after. Every second a key remains active is a second it can be used to drain remaining funds.
-
2Freeze the account (contact support)
Email security@purpleflea.com with subject "URGENT: Account breach - [your username]". Purple Flea can place a temporary hold on all outgoing transactions while you investigate. Do this in parallel with key revocation.
-
3Download full transaction history
Using the read-only key (if still valid) or via the dashboard, export your complete transaction history for the past 90 days. This is your forensic record for determining the breach timeline and reporting losses.
-
4Identify the leak source
Check git logs for committed secrets. Search your codebase for the key string. Check whether it was logged. Review who had access to the environment where the key was stored. Common sources: public GitHub repo, unsanitized application logs, shared development environment, compromised developer machine.
-
5Generate new keys with a clean setup
Once the leak source is identified and remediated, generate a fresh set of API keys. Store them correctly from the start — environment variables, secrets manager, or vault. Do not reuse the same storage method that was compromised.
-
6Audit and harden before resuming
Before resuming agent operations, implement all the controls from this guide that weren't in place before the incident. Set withdrawal limits, enable anomaly monitoring, configure multi-sig if your balance warrants it, and schedule the first cold sweep.
8. Security Checklist
Use this checklist before deploying any agent with Purple Flea wallet access. Return to it every 30 days as part of your key rotation cycle.
-
1API keys stored in environment variables, not source code All PF_* keys loaded via os.environ[] or secrets manager. No keys in any .py, .js, .yaml, .json, or .toml file.
-
2.env file is in .gitignore and has never been committed Verify with: git log --all --full-history -- .env. If any result appears, treat the key as compromised.
-
3Read-only and withdrawal keys are separate Two distinct keys: PF_WALLET_READ_KEY (no withdrawal permission) and PF_WALLET_WITHDRAW_KEY. Monitoring code uses only the read key.
-
4Withdrawal limits are configured and set conservatively Daily limit ≤ 3x expected daily operational need. Single withdrawal limit ≤ $200 for typical agents.
-
5Anomaly monitoring is running and alerting Hourly cron job checks withdrawal volume against 30-day baseline. Alerts go to a monitored channel (not just email).
-
6Cold storage sweep is scheduled and tested Hot wallet capped at 10% of total balance. Sweep runs daily. Cold address is allowlisted and has been tested with a small transfer.
-
7Key rotation scheduled every 30 days Calendar event set. Rotation procedure documented and tested. Old keys are immediately invalidated after new keys are confirmed working.
-
8Incident response steps documented and accessible Support email (security@purpleflea.com) saved. Dashboard access is available from a device not running the agent. Key revocation can be done in under 2 minutes.
-
9Multi-sig enabled if balance exceeds $1,000 2-of-3 multi-sig configured for withdrawals above $500. Hardware key is accessible but not on the agent's machine.
Start secure, stay secure. The cost of implementing these controls before deployment is a few hours. The cost of a sweep attack on a funded agent wallet — plus the time to identify the breach, remediate, and rebuild trust — is orders of magnitude higher. Security is not a feature you add later. Build it in from the first line of code.
Build on Purple Flea
Start with the free $1 USDC faucet to test your agent's wallet integration with zero risk. All security features — limits, multi-sig, key rotation — are available from day one.
Claim Free $1 USDC →