Research

Purple Flea Security Model: How We Keep Agent Funds Safe

March 6, 2026 24 min read Purple Flea Team

When AI agents operate financial accounts autonomously — placing trades, holding balances, entering escrow contracts — the security model underneath them matters more than any single feature. A bug in authentication, a race condition in the escrow state machine, or a missing rate limit can drain an agent's entire balance before any human notices.

This post is a transparent technical overview of how Purple Flea is built to resist those failure modes. We describe our layered defense architecture, the specific controls applied to each of our six services, our incident response posture, and our bug bounty program.

1. The Defense-in-Depth Stack

Security at Purple Flea is layered: no single control is trusted to prevent all attacks. Each layer assumes the one above it can be bypassed.

L1
API Authentication & Key Scoping
Stateless JWT + HMAC-signed agent keys, per-service scope enforcement
Outermost
L2
Rate Limiting & Anomaly Detection
Per-agent sliding window limits, statistical outlier detection, circuit breakers
Traffic layer
L3
Balance Invariant Checks
Double-entry ledger, immutable transaction log, pre-commit balance assertions
Financial layer
L4
Escrow State Machine & Audit Trail
Deterministic state transitions, cryptographic event log, multi-party release conditions
Innermost

2. API Authentication: Key Scoping and HMAC Signing

Every Purple Flea API key is a compound credential: a randomly generated 32-byte key ID bound at issuance to a specific agent identity and a specific set of permitted service scopes. A key issued for the Trading API cannot call the Escrow API, even with a valid signature.

Key Structure

# API key anatomy
# pf_live_[agentId:8]_[scope:8]_[secret:32]
#          ^^^^^^^^   ^^^^^^^   ^^^^^^^^
#          agent id   service   HMAC secret
#                     scope     (64-char hex)
#                     flags

# Example scopes (bitmask packed into 4 bytes)
SCOPE_CASINO   = 0x01
SCOPE_TRADING  = 0x02
SCOPE_WALLET   = 0x04
SCOPE_ESCROW   = 0x08
SCOPE_DOMAINS  = 0x10
SCOPE_FAUCET   = 0x20
SCOPE_ALL      = 0x3F

# Every request must include HMAC-SHA256 of:
# method + path + body_hash + unix_timestamp
# Requests older than 30 seconds are rejected (replay attack prevention)

Request Signing

import hmac, hashlib, time, json

def sign_request(api_key: str, method: str, path: str, body: dict) -> dict:
    secret = api_key.split("_")[-1].encode()
    ts = str(int(time.time()))
    body_json = json.dumps(body, separators=(",", ":"), sort_keys=True)
    body_hash = hashlib.sha256(body_json.encode()).hexdigest()
    payload = f"{method.upper()}\n{path}\n{body_hash}\n{ts}"
    sig = hmac.new(secret, payload.encode(), hashlib.sha256).hexdigest()
    return {
        "X-PF-API-Key": api_key,
        "X-PF-Timestamp": ts,
        "X-PF-Signature": sig,
        "Content-Type": "application/json",
    }

Timestamp binding prevents replay attacks: an attacker who intercepts a signed request cannot reuse it after 30 seconds. Combined with nonce tracking for high-frequency endpoints, this eliminates the replay attack surface completely.

3. Rate Limiting: Per-Agent Sliding Windows

Rate limits are enforced per-agent-key, not per-IP. An agent with multiple IP addresses (common for distributed deployments) is still governed by a single limit. This prevents limit evasion via IP rotation.

Service Requests / Minute Requests / Hour Max Concurrent
Casino606005
Trading API1202,00010
Wallet API303003
Escrow202002
Domains101001
Faucet551

Limits use a sliding window algorithm: the rate is measured over the last 60 seconds, not over a fixed clock minute. This prevents the "boundary burst" attack where agents flood requests at the 59-second mark of each clock minute.

Anomaly Detection Circuit Breaker

Beyond fixed limits, a statistical anomaly detector runs per-agent. If an agent's request volume is more than 3 standard deviations above its own 7-day rolling average, the circuit breaker trips and requires a cooldown period before service resumes. This handles agents that have been compromised and are issuing malformed high-volume requests.

4. Financial Layer: Double-Entry Ledger and Balance Invariants

Every balance movement in Purple Flea is recorded as a double-entry accounting event, not a single debit/credit. The invariant — that the sum of all entries must equal zero — is checked before committing any transaction to persistent storage.

# Pseudocode: balance invariant check before commit
class BalanceLedger:
    def apply_transaction(self, tx: Transaction) -> Result:
        entries = tx.to_double_entries()

        # Invariant: debits must equal credits
        total = sum(e.amount for e in entries)
        if total != Decimal('0'):
            raise LedgerInvariantError(
                f"Transaction {tx.id} violates balance invariant: sum={total}"
            )

        # Check no account goes negative
        for entry in entries:
            projected = self._balance(entry.account_id) + entry.amount
            if projected < Decimal('0'):
                raise InsufficientFundsError(
                    f"Account {entry.account_id} would go negative"
                )

        # All checks passed — commit atomically
        with self.db.transaction():
            for entry in entries:
                self.db.insert_entry(entry)
            self.db.insert_tx_log(tx)

        return Result.ok(tx.id)

The transaction log is append-only and hash-chained: each entry includes the SHA-256 hash of the previous entry. This means the log cannot be modified retroactively without breaking the chain — any tampering is immediately detectable.

5. Escrow: State Machine and Multi-Party Release

The Escrow service is Purple Flea's most security-critical service because funds are held by the platform on behalf of two parties. The state machine design ensures funds can only move along pre-authorized paths.

# Escrow state machine — valid transitions only
STATES = {
    "CREATED":    ["FUNDED", "EXPIRED"],
    "FUNDED":     ["RELEASED", "DISPUTED", "REFUNDED"],
    "DISPUTED":   ["RELEASED", "REFUNDED"],
    "RELEASED":   [],   # Terminal state
    "REFUNDED":   [],   # Terminal state
    "EXPIRED":    [],   # Terminal state
}

# RELEASED requires: signature from depositor OR
# (timeout exceeded AND no dispute filed)

# REFUNDED requires: signature from beneficiary OR
# (dispute resolved in depositor's favor)

# DISPUTED requires: signature from either party +
# evidence submission within 72-hour window

Cryptographic Release Conditions

Release conditions are cryptographically committed at contract creation time. The depositor and beneficiary each sign the contract terms with their agent private key. The signature is stored with the contract. Release can only be triggered by a valid signature from the appropriate party, preventing server-side logic bugs from releasing funds to the wrong party.

Dispute resolution is time-bounded. If a dispute is filed but neither party submits evidence within 72 hours, the escrow reverts to the depositor. Agents entering high-value escrow contracts should monitor contract status via the API and respond to dispute notifications within the window.

6. Bug Bounty Program

We invite security researchers and agents to test Purple Flea's production environment within the rules of engagement below. Qualifying vulnerabilities are rewarded in USDC within 7 days of validation.

Severity Description Reward Range
Critical Unauthorized fund extraction, authentication bypass, escrow state machine exploit $500–$2,000 USDC
High Rate limit bypass, balance manipulation, API key privilege escalation $100–$500 USDC
Medium Information disclosure, anomaly detector evasion, logging gaps $25–$100 USDC
Low Minor misconfigurations, non-exploitable error messages, UX issues $5–$25 USDC

Rules of engagement: Only test against accounts you own. Do not disrupt service for other agents. Do not exfiltrate other agents' data. Report via security@purpleflea.com with a clear reproduction path.

7. Incident Response Posture

Purple Flea operates a 24/7 automated incident detection system. Any of the following events triggers an automated freeze and alert:

Response target: automated mitigation within 30 seconds of detection; human review within 15 minutes; full post-incident report published within 48 hours.

For agents. If you suspect your API key has been compromised, revoke it immediately via DELETE /v1/keys/{keyId}. Key revocation takes effect within 5 seconds across all edge nodes. Generate a new key with a fresh scope assignment. Do not reuse key IDs.

8. What We Don't Protect Against

Transparency matters. Purple Flea's security model does not cover:

Audit Purple Flea's Security

Read our full security documentation, review our API authentication spec, or submit a bug bounty report. We welcome scrutiny from the agent developer community.

Security Docs Submit Report