Security model

AXON layers defences so that no single failure is catastrophic. From the edge inward:

AXON security architecture

1 — Edge

  • Cloudflare fronts the domain (DNS, CDN, WAF, TLS).
  • Caddy terminates TLS inside the host and reverse‑proxies to the gateway. Backend services publish no ports — they're reachable only on the private Docker network.

2 — Gateway authentication

  • A global JWT guard verifies an HS256 bearer token (verifyBearer, timing‑safe, HS256‑only) on every request.
  • A small public‑route allowlist (anchored‑prefix matched, so no substring bypass) exempts only what must be unauthenticated: /auth/nonce, /auth/login, /auth/refresh, /kyc/webhook, /admin/login, /health*.
  • Rate limiting is applied per client IP by path class (auth ~20/min, AI ~40/min, default ~300/min) to blunt brute‑force and abuse.
  • Sensitive internal headers (x-axon-service-token, x-axon-admin-user) are stripped on ingress so a client can't forge them.

3 — Service authorisation & data scoping

  • Defence in depth: each service re‑verifies the JWT in its @CurrentUser() decorator — it never trusts the gateway blindly.
  • Profile scoping: business‑scoped endpoints require an X-AXON-Profile-Id header, and the service checks that the token's user actually owns that profile (mismatch → 403). This is why a personal account can't read another business's data.
  • No commingling: personal and business wallets are distinct addresses (different HD indexes); operations are stamped with the acting profile so the two contexts never mix on‑chain or in the ledger.
  • Session hardening: access tokens are short‑lived (~2h); refresh tokens are single‑use and rotated, with reuse detection that revokes the whole token family if an old token is replayed.

4 — On-chain custody

  • Users sign their own transactions with their Privy wallet — AXON never holds user keys for custody actions.
  • The backend uses prepare → confirm: it prepares the call, the user signs, and the service verifies the resulting transaction on‑chain before mutating state. The chain is the source of truth.
  • The escrow contract enforces its own access control (initiator/counterparty modifiers, acceptance gating, the 5‑day permissionless‑release timeout, and the fee snapshot).

5 — Integrity & audit

  • Webhooks (e.g. Sumsub, MoonPay) are authenticated by HMAC signature over the raw body, and de‑duplicated via WebhookEvent so replays are harmless.
  • Money movements are written to the append‑only, hash‑chained settlement ledger, whose head is periodically anchored to Base — tampering is detectable and provable.
  • Admin and auth actions are written to an append‑only AuditLog (e.g. user.signin, auth.refresh_reuse_detected, settlement.recorded, policy changes).

Secrets

  • Configuration is loaded through a fail‑closed getSecret() — in production a missing required secret stops the service rather than starting in an insecure default.
  • NEXT_PUBLIC_* values are baked into the web bundle at build time (notably NEXT_PUBLIC_PRIVY_APP_ID, which the auth/wagmi provider stack requires).

Remediation history

The codebase went through structured security hardening (P0/P1/P2). Highlights now in place: real JWT verification everywhere, gateway rate‑limiting, DB‑backed single‑use nonces, rotating refresh tokens with reuse detection, webhook signature + dedupe, exact on‑chain transaction verification on the custody path, and an escrow fee‑snapshot. See docs/REMEDIATION_PLAN_2026-06-10.md and docs/TECHNICAL_REVIEW_2026-06-10.md in the repo for the full record.

results matching ""

    No results matching ""