Skip to content

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:

function buyLicense(...) external nonReentrant whenNotPaused {
    // Safe from reentrancy attacks
}

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:

const nonce = generateNonce() // crypto.getRandomValues(new Uint8Array(32))

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:

if (paymentAmount < requiredAmount) {
  return { error: 'Insufficient payment' }
}

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:

  1. Signature verification: USDC contract verifies EIP-712 signature
  2. Nonce uniqueness: Each authorization can only be used once
  3. Time bounds: Authorization has explicit validity window
  4. 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

  1. Persist nonces to database: Prevent replay attacks across restarts
  2. Redis rate limiting: Consistent limits across serverless instances
  3. Local signature verification: Verify before calling facilitator
  4. Security audit: Professional audit before mainnet
  5. Bug bounty program: Incentivize responsible disclosure

Incident Response

If You Discover a Vulnerability

  1. Do NOT disclose publicly
  2. Email security@wasiai.com with details
  3. Include steps to reproduce
  4. We'll respond within 24 hours

If Your Wallet is Compromised

  1. For agents: Request wallet change (24-hour timelock gives you time)
  2. For models: Transfer ownership to a new wallet
  3. 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