Security
Threat model and security analysis for Cortex as a Base-native agentic commerce protocol. Covers protocol, policy, commerce, and offchain service risks.
1. Base / L2 Dependency Risks
| Threat | Severity | Mitigation |
|---|---|---|
| Bridge exploit (token drain) | Critical | Prefer native Base assets and canonical bridges. Monitor bridge and stablecoin issuer risk. |
| Sequencer censorship | High | Base inherits OP Stack forced inclusion paths. Agents and merchants should retry or use alternate rails when degraded. |
| Sequencer liveness failure | High | Document operational fallback and pause guidance for services that need timely settlement. |
| Data availability gap | Medium | L1 calldata/blobs ensure state reconstructability. |
| Public RPC range limits | Medium | Indexer chunks log polling below Base Sepolia RPC limits and checkpoints progress. |
2. Intent Manipulation / Replay
| Threat | Severity | Mitigation |
|---|---|---|
| Intent replay (same chain) | High | Per-owner nonce mapping. Once used, permanently consumed. |
| Intent replay (cross-chain) | Medium | EIP-712 domain includes chainId and verifyingContract. |
| Intent forgery (wrong signer) | High | EIP-712 signature verification via ECDSA.recover. |
| Intent front-running | Medium | MVP accepts this; future: encrypted mempools or commit-reveal. |
| Expired intent fill | Low | fillIntent() checks block.timestamp >= deadline and reverts. |
| Constraint violation | Low | fillIntent() enforces amountIn <= amountInMax and amountOut >= amountOutMin. |
Invariants verified by fuzz/invariant tests:
invariant_noDoubleFill— no intent can be filled twiceinvariant_nonceReplayProtection— nonce replay always revertsinvariant_statusConsistency— filled + cancelled <= submitted
3. Solver Censorship or Abuse
| Threat | Severity | Mitigation |
|---|---|---|
| Solver censorship | Medium | Permissionless solver registration and indexed fill quality reduce reliance on one solver. |
| Solver MEV extraction | Medium | Constraint enforcement on-chain (amountInMax/amountOutMin). |
| Solver griefing | Low | Fill constraints checked on-chain. Invalid fills revert. |
| Solver downtime | Medium | Intents remain OPEN until deadline. Agents can cancel and resubmit. |
4. Policy Bypass Patterns
| Threat | Severity | Mitigation |
|---|---|---|
| delegatecall to untrusted contract | High | PolicyAccount restricts execution to call only. |
| approve + transferFrom bypass | Medium | ERC-20 transfer, approve, and transferFrom calldata is detected and charged against token limits. |
| Spend limit race (multi-tx) | Low | recordSpend() uses storage-level cumulative tracking. |
| Rolling window manipulation | Low | Window resets after 24h. Cannot be shortened by the account. |
| Target allowlist bypass via proxy | Medium | Allowlist checks direct target address. |
| Function selector collision | Low | 4-byte selectors practically safe for known interfaces. |
| Signed payment replay | High | Signed payment recording enforces merchant/token/facilitator budgets and payment-hash replay protection. |
Invariants verified by fuzz/invariant tests:
invariant_spentNeverExceedsPeakMax— spentToday never exceeds peak maxPerDayinvariant_windowResetClearsSpend— window reset clears spending correctlyinvariant_perTokenIsolation— per-token spending is isolated
5. Key Management
| Threat | Severity | Mitigation |
|---|---|---|
| Agent key compromise | Critical | PolicyModule caps daily spending. Target allowlist limits destinations. Owner can revoke. |
| Solver key compromise | High | Solver can only fill intents within constraints. |
| Deployer key compromise | High | Contracts are immutable once deployed. Deployer not privileged. |
| Key rotation | Medium | AgentRegistry supports updateAgent. Policies are reconfigurable. |
6. Smart Contract Risks
| Threat | Severity | Mitigation |
|---|---|---|
| Reentrancy | Low | No external calls before state changes. Checks-effects-interactions. |
| Integer overflow | Low | Solidity 0.8.24 built-in overflow checks. |
| Storage collision | Low | No upgradeable proxies in MVP. |
| Uninitialized state | Low | All mappings default to zero/false. |
7. Commerce Risks
| Threat | Severity | Mitigation |
|---|---|---|
| Fake merchant or cloned service | High | Merchant, service, and facilitator records are anchored onchain with metadata hashes. |
| Quote replay | High | Quote hashes bind chain ID, registry address, merchant, service, agent, token, rail, nonce, terms, resource, x402 payload, and fees. |
| Payment payload substitution | High | x402 payloads bind through x402PayloadHash; other rails bind through terms/resource hashes plus account policy. |
| Merchant non-fulfillment | Medium | Receipts, fulfillment hashes, disputes, and trust signals create a shared risk trail. |
| Refund abuse by agents | Medium | Dispute and trust-signal history is indexed for agents and merchants. |
| Privacy leakage in metadata | Medium | Keep sensitive prompts, URLs, payloads, and business intent out of public metadata. |
8. Offchain Service Risks
| Threat | Severity | Mitigation |
|---|---|---|
| Indexer data desync | Medium | Tracks lastProcessedBlock. Resumes from checkpoint. |
| API injection (SQL) | High | All queries use parameterized statements ($1, $2). |
| API denial of service | Medium | Pagination limits (max 100). No unbounded queries. |
| Database corruption | Medium | Postgres WAL + standard backup. Idempotent migrations. |
| Hosted API outage | Medium | Onchain state remains canonical; agents can fall back to direct RPC/log reads or alternate indexers. |
Static Analysis
- Slither runs in CI to detect common vulnerability patterns.
- Solhint enforces Solidity coding standards.
- Forge fmt ensures consistent formatting.
- Fuzz tests run 1,000 iterations per property.
- Invariant tests run 256 sequences of 64 calls each.