Security Model¶
This document outlines the security measures implemented in WasiAI to protect users, builders, and the platform.
Smart Contract Security¶
Access Control¶
All WasiAI contracts implement strict access control:
| Pattern | Description | Used In |
|---|---|---|
| Ownable2Step | Two-step ownership transfer prevents accidental transfers | All contracts |
| onlyOwner | Restricts admin functions to contract owner | MarketplaceV3, SplitterFactory |
| onlyMarketplace | Restricts minting to Marketplace contract | LicenseNFTV2, AgentRegistryV2 |
| onlyAuthorized | Whitelist for splitter creation | SplitterFactory |
Reentrancy Protection¶
All payment functions use OpenZeppelin's ReentrancyGuard:
Pausability¶
All main contracts can be paused in emergencies:
function pause() external onlyOwner {
_pause();
}
function unpause() external onlyOwner {
_unpause();
}
When paused: - No new models can be published - No licenses can be purchased - No agents can be registered - Existing data remains accessible
Timelocks¶
Critical operations require a 24-hour delay:
| Operation | Timelock | Contract |
|---|---|---|
| Inference wallet change | 24 hours | MarketplaceV3 |
| Agent wallet change | 24 hours | AgentRegistryV2 |
This prevents instant theft if a private key is compromised.
function requestWalletChange(uint256 agentId, address newWallet) external {
pendingWalletChanges[agentId] = PendingWalletChange({
newWallet: newWallet,
effectiveAt: block.timestamp + TIMELOCK_DELAY
});
}
function executeWalletChange(uint256 agentId) external {
require(block.timestamp >= pendingWalletChanges[agentId].effectiveAt);
// Execute change
}
Payment Security¶
x402 Protections¶
Replay Protection¶
Each payment has a unique 32-byte nonce:
Used nonces are tracked to prevent replay attacks:
if (usedNonces.has(nonce)) {
return { valid: false, error: 'Nonce already used' }
}
usedNonces.add(nonce)
Note: Currently stored in memory. Production should persist to database.
Time Windows¶
Payments are only valid within a short window:
const validAfter = now - 60 // Valid from 1 minute ago
const validBefore = now + 60 // Expires in 1 minute
Server validates:
if (now < validAfter) return { error: 'Payment not yet valid' }
if (now > validBefore) return { error: 'Payment expired' }
Amount Validation¶
Exact payment amount is required:
Recipient Validation¶
Payment must go to the correct address:
if (paymentTo.toLowerCase() !== requirement.payTo.toLowerCase()) {
return { error: 'Wrong recipient' }
}
EIP-3009 Security¶
USDC's transferWithAuthorization is secure because:
- Signature verification: USDC contract verifies EIP-712 signature
- Nonce uniqueness: Each authorization can only be used once
- Time bounds: Authorization has explicit validity window
- Specific recipient: Cannot redirect to different address
API Security¶
Rate Limiting¶
All endpoints have rate limits:
| Endpoint | Limit | Window |
|---|---|---|
/api/inference/* | 10 requests | 1 minute |
/api/models/* | 30 requests | 1 minute |
/api/ipfs/* | 10 requests | 1 minute |
Implementation:
const hits = new Map<string, { count: number; resetAt: number }>()
function rateLimit(key: string, max: number, windowMs: number) {
const now = Date.now()
const cur = hits.get(key)
if (!cur || now > cur.resetAt) {
hits.set(key, { count: 1, resetAt: now + windowMs })
return { ok: true }
}
if (cur.count >= max) {
return { ok: false }
}
cur.count++
return { ok: true }
}
Input Validation¶
All inputs are validated:
// URL validation for endpoints
const url = new URL(endpoint)
if (!['http:', 'https:'].includes(url.protocol)) {
throw new Error('Invalid endpoint protocol')
}
// Length limits
if (endpoint.length > MAX_ENDPOINT_LENGTH) {
throw new Error('Endpoint too long')
}
CORS¶
API routes have restricted CORS: - Only allowed origins can make requests - Credentials are handled securely
Data Security¶
IPFS Storage¶
Model metadata is stored on IPFS: - Content-addressed: Data cannot be modified without changing the hash - Decentralized: No single point of failure - Immutable: Once published, metadata cannot be altered
Database¶
Neon Postgres is used for indexed data: - Encrypted at rest: All data encrypted - Encrypted in transit: TLS connections only - Access control: Restricted to application
Sensitive Data¶
- Private keys: Never stored, only in environment variables
- API keys: Stored in environment, not in code
- User data: Minimal collection, no PII stored
Wallet Security¶
Social Login (Thirdweb)¶
Thirdweb In-App Wallets are: - Non-custodial: User controls the key - Recoverable: Via social account - Secure: Keys generated client-side
Traditional Wallets¶
Users connecting with MetaMask/WalletConnect: - Sign transactions locally - Never share private keys - Can verify all transactions
Known Limitations¶
Current (Testnet)¶
| Limitation | Risk | Mitigation |
|---|---|---|
| Nonces in memory | Replay after restart | Persist to DB for mainnet |
| Rate limits in memory | Reset on restart | Use Redis for mainnet |
| No signature verification | Trust facilitator | Add local verification |
| Unaudited contracts | Potential vulnerabilities | Audit before mainnet |
Planned Improvements¶
- Persist nonces to database: Prevent replay attacks across restarts
- Redis rate limiting: Consistent limits across serverless instances
- Local signature verification: Verify before calling facilitator
- Security audit: Professional audit before mainnet
- Bug bounty program: Incentivize responsible disclosure
Incident Response¶
If You Discover a Vulnerability¶
- Do NOT disclose publicly
- Email security@wasiai.com with details
- Include steps to reproduce
- We'll respond within 24 hours
If Your Wallet is Compromised¶
- For agents: Request wallet change (24-hour timelock gives you time)
- For models: Transfer ownership to a new wallet
- Contact support: We can help with emergency measures
Audit Status¶
| Component | Status | Date |
|---|---|---|
| MarketplaceV3 | 🔜 Pending | Q2 2025 |
| LicenseNFTV2 | 🔜 Pending | Q2 2025 |
| AgentRegistryV2 | 🔜 Pending | Q2 2025 |
| SplitterFactory | 🔜 Pending | Q2 2025 |
| ModelSplitter | 🔜 Pending | Q2 2025 |
All contracts will be audited before mainnet deployment.
Security Checklist for Builders¶
When publishing models:
- [ ] Use a dedicated wallet for receiving payments
- [ ] Set up wallet monitoring for unusual activity
- [ ] Keep your inference endpoint secure
- [ ] Don't expose API keys in metadata
- [ ] Test thoroughly on testnet first
- [ ] Monitor your model's reputation for issues