Security Model

MarrowStack blocks make specific, testable security guarantees. This page documents what those guarantees are, what is explicitly outside their scope, and what you must implement on your side.

What the blocks guarantee

Passwords are never stored in plaintext

The Auth block hashes passwords with bcrypt before writing to the database. The plaintext value is never logged, returned, or stored. The work factor defaults to 12 rounds (configurable up, not down below 10).

Cryptographic verification is server-side only

For SIWS (Solana Auth), Ed25519 signature verification runs on the server using tweetnacl. The block never trusts a client claim that verification succeeded. For payments, on-chain verification runs via your RPC before any value-delivery path is reached.

Nonces and tokens are single-use

Auth nonces are consumed atomically with a conditional UPDATE (WHERE consumed_at IS NULL). A second verify attempt with the same nonce returns 409. Invite tokens work identically.

Idempotency on payments

The payment signature is stored in an idempotency_key UNIQUE column. A duplicate verify attempt for the same on-chain transaction returns 409 ALREADY_CREDITED rather than double-crediting.

Row-Level Security on all tables

Every SQL migration enables RLS and sets policies. Service role operations (server-side) bypass RLS intentionally. Client-side Supabase access (if you add it) is constrained by RLS policies.

Domain binding in SIWS

The Solana Auth block checks the domain field in every SIWS message against SOLANA_AUTH_DOMAIN. A mismatch rejects the request. This prevents cross-origin replay attacks.

Brute-force lockout

The Auth block tracks failed login attempts per IP. After MAX_LOGIN_ATTEMPTS failures within LOCKOUT_WINDOW_MINUTES, that IP is blocked until the window expires.

Verify before delivering value

This is the most important rule for Solana payments.

The usePaymentStatus hook fires onConfirmed only after the status API returns confirmed, which itself only fires after server-side verifyPayment() passes all 6 checks. Despite this, your product delivery logic must independently call verifyPayment()or check the DB status before writing the order. Defense in depth: if the client call is intercepted or replayed, your server is the last line of defense.

What is your responsibility

  • HTTPS everywhere. The blocks do not enforce transport security — your infrastructure must serve over TLS. SIWS signatures over plain HTTP are trivially interceptable.
  • Secret management. Never expose SUPABASE_SERVICE_ROLE_KEY, NEXTAUTH_SECRET, or SMTP_PASS to the client. Use Next.js server-only env vars (no NEXT_PUBLIC_ prefix) for all secrets.
  • RPC reliability. For Solana payments in production, use a private RPC (Helius, QuickNode, Alchemy). Public devnet and mainnet RPCs have aggressive rate limits that will cause confirmation polling to fail under load.
  • USDC mint address verification. Before going to mainnet, verify the USDC mint addresses against Circle's official documentation. The block ships with the correct addresses at time of writing, but you must confirm them for your deployment.
  • Nonce TTL lower bound. Do not set SOLANA_AUTH_NONCE_TTL_SECONDS below 60. Very short windows cause legitimate users to fail the timestamp check on slow connections.
  • Admin route authorization. The Admin block's requireAdmin() must be called at the top of every admin route handler and server component. The block does not apply middleware-level protection.
  • Dependency updates. You own the block file. Monitor @solana/web3.js, tweetnacl, next-auth, and bcryptjs for security advisories.

Out of scope

The following are not covered by any block and must be implemented at the infrastructure or application layer:

  • DDoS protection (use Cloudflare or your CDN's WAF)
  • Rate limiting at the network edge (beyond the per-IP lockout in the Auth block)
  • Content Security Policy headers
  • CORS policy enforcement
  • Database backups and point-in-time recovery
  • Solana validator-level MEV resistance (private RPC helps at the RPC layer)

Reporting issues

The two Solana blocks are MIT-licensed and open source. Report security issues by email to security@marrowstack.dev. For the web2 blocks, use the same address. Please do not file public GitHub issues for security vulnerabilities.