Security

Security isn't a feature. It's the product.

Arden holds your transactions, balances, and bank connections. That's an enormous amount of trust to ask for. This page tells you exactly how we protect it — and where we're still improving. No marketing fluff. Updated April 2026.

Five principles. Held to in code.

How we think about protecting your data.

  1. 01

    Collect the minimum. Keep it the shortest time.

    We can't leak data we don't have. Plaid is optional. Logs are scrubbed of emails, currency, and tokens. Retention windows are written down — and enforced by code, not policy.

  2. 02

    Encrypt everything in motion. Encrypt everything at rest.

    TLS 1.3 (1.2 fallback) on every connection. AES-256 on the database, on backups, on Vercel build artifacts. Bcrypt on every password. No plaintext secrets in logs, exports, or repos.

  3. 03

    Authorize every row, every time.

    Multi-tenant data is the #1 risk for an app like ours. Every database mutation passes through an ownership predicate before it touches a row by ID. Schema enforcement is separate from permission enforcement — both must pass.

  4. 04

    Rate-limit every authentication surface.

    Signup, login, login-per-email, email verification, two-factor verification, Plaid token exchange, data export. Sliding-window limits in Postgres, generous for humans, brutal for bots.

  5. 05

    Be honest about gaps.

    Real security means writing down what you don't do yet. The "What we don't do yet" section below is the part we expect you to read most carefully.

On the security roadmap

What we're working toward next.

A short list, kept honest. If something here matters to you, tell us — it'll move up the priority list. The full SECURITY.md has the longer technical follow-ups.

  • Application-layer encryption of TOTP secrets

    Planned

    Two-factor secrets are encrypted at rest by Neon. We're adding a second layer — KMS-backed envelope encryption inside the application — so a database-only exfiltration scenario can't bypass 2FA. The current posture is already strong; this raises the floor further.

  • WebAuthn / hardware key support

    Planned

    TOTP via authenticator app is supported today. We're adding WebAuthn (YubiKey, Touch ID, Face ID, Windows Hello) as an alternative second factor — phishing-resistant by design, no shared secret to lose.

  • Third-party penetration test

    Longer term

    External adversarial testing is the gold standard for catching what internal review misses. We'll commission one once the user base and budget justify it. In the meantime, we run a bug bounty via the disclosure address below.

  • SOC 2 Type II audit

    Longer term

    Formal compliance attestation is a multi-month, multi-thousand-dollar undertaking that primarily serves enterprise procurement teams. We'll pursue it when there's a customer who needs it. Until then, this page and our public SECURITY.md are the substantive answer.

What's actually in place

Ten layers. Each one specific.

The exact controls running in production right now. Updated each time the underlying code changes — not annually for compliance.

  1. 01

    Transport

    Every byte you exchange with Arden is over TLS.

    TLS
    TLS 1.3 with 1.2 fallback. HTTP auto-redirects to HTTPS via Vercel.
    CSP
    Content-Security-Policy with default-src 'self' and an explicit Plaid allowlist. Frame-ancestors 'none' (Arden cannot be iframed).
    Other headers
    X-Frame-Options DENY, X-Content-Type-Options nosniff, Referrer-Policy strict-origin-when-cross-origin, Cross-Origin-Opener-Policy same-origin, Permissions-Policy denying camera/mic/geolocation/payment APIs.
  2. 02

    Storage

    Your data is encrypted on disk by everyone who touches it.

    Database
    Neon Postgres. AES-256 encryption at rest. US region. Pooled connections over TLS.
    Application
    Hosted on Vercel (us-west-2). Build artifacts and environment variables encrypted at rest.
    Plaid tokens
    Stored server-side only. Never returned to the client. Explicitly redacted from data exports. Deleted immediately when you disconnect a bank.
    Backups
    Neon point-in-time restore retains 7 days by default. Backups inherit the same encryption-at-rest as the live database.
  3. 03

    Authentication

    Passwords, sessions, and the optional second factor.

    Passwords
    Bcrypt with cost 10 (industry standard). Plaintext passwords never written to disk or logs.
    Sessions
    Stateless JWT, signed with HS256, 30-day expiry. HttpOnly + Secure + SameSite=Lax cookies. Server-side AUTH_SECRET validated at boot — must be ≥32 characters or the process refuses to start.
    Email verification
    Required before any write actions. Verification tokens are short-lived (24 hours) and rate-limited (10 attempts per 15 min per IP).
    Two-factor (TOTP)
    Optional, opt-in from Settings. RFC 6238 standard. Compatible with Authy, Google Authenticator, 1Password, Bitwarden. 10 single-use recovery codes generated at enrollment, stored as bcrypt hashes. Login verification rate-limited to 5 attempts per 15 min per (IP × user).
    CSRF
    Next.js Server Actions enforce same-origin checks on every mutation. SameSite=Lax cookies as a second layer.
  4. 04

    Authorization

    Every database mutation checks ownership before touching a row.

    Pattern
    Multi-tenant data is the #1 risk for an app like Arden. Every server action calls an ownership predicate (userOwnsAccount, userOwnsCategory, userOwnsTrackingAccount, userOwnsCategoryGroup) before SQL runs.
    Validation
    Every server action runs Zod input validation at entry. Shape enforcement (Zod) and permission enforcement (ownership) are separate; both must pass.
    SQL
    Tagged-template queries via the postgres library. Every value auto-parameterized. Zero string concatenation into SQL anywhere in the codebase.
  5. 05

    Plaid

    Connecting a bank is optional. The token never leaves the server.

    Optional by design
    Every feature works without Plaid. CSV import is a first-class flow. We never require a bank login to use Arden.
    Credentials
    Plaid receives your bank login directly via Plaid Link. We never see your bank password. Plaid sends us a long-lived access token in exchange.
    Access tokens
    Stored server-side in plaid_items.access_token. Never returned to the client. Never logged. Explicitly redacted from GDPR data exports.
    Disconnect
    Removing a Plaid item issues an itemRemove call to Plaid AND hard-deletes the row in the same transaction. No 30-day "grace period" — gone immediately.
    Webhook auth
    Plaid webhooks verify a JWT signature against Plaid's rotating public keys before any sync logic runs.
  6. 06

    Retention

    How long we keep what we keep.

    Your data
    Until you delete your account. Cascading delete via ON DELETE CASCADE through every owned table — user record, transactions, budgets, accounts, holdings, milestones, recovery codes — in one transaction.
    Plaid tokens
    Deleted immediately on disconnect.
    Server logs
    30 days (Vercel default). Scrubbed of emails, currency, JWTs, and Plaid tokens before write.
    Rate-limit attempts
    Cleaned daily. Anything older than 24 hours is dropped.
    Email-verification tokens
    Cleared 24 hours after issue or on use, whichever first.
    Import sessions
    Deleted after 90 days (filenames may contain PII).
    Used recovery codes
    Deleted 90 days after consumption (ops audit window). Unused codes kept until the user regenerates them.
  7. 07

    Your rights

    Your data is yours. We make it easy to leave.

    Full export
    One click from Settings → Privacy & Data Export. Downloads a complete JSON snapshot of every account, transaction, budget assignment, goal, investment holding, scheduled transaction, and metadata row scoped to your user.
    Transactions CSV
    Spreadsheet-friendly export with date, payee, amount, category, account. Opens in Excel, Numbers, or Google Sheets. No paywall, no email gate.
    Account deletion
    One button in Settings → Danger Zone. Cascades through every owned table in a single transaction (transactions, budgets, accounts, holdings, milestones, recovery codes), revokes all Plaid connections, and deletes the user record. No 30-day soft-delete; no recovery window.
    Excluded from exports
    Passwords (bcrypt hashes) and Plaid access tokens are deliberately excluded. They never leave the server in any form.
  8. 08

    Privacy & telemetry

    No third-party analytics on the pages where your money lives.

    In the app (app.ardenmoney.com)
    No Google Analytics, no Mixpanel, no Segment, no behavioral tracking pixels. Period. Sentry runs only on uncaught exceptions, with PII scrubbed before send.
    On the marketing site
    Plausible Analytics — cookieless, no personal identifiers, no cross-site tracking, country-level geolocation only. Aggregate pageview counts so we know which pages get traffic.
    Sentry scrubbing
    Before any error report leaves our servers, a scrubber strips email addresses, currency amounts, JWTs, and Plaid tokens from the payload. See instrumentation.ts.
  9. 09

    Monitoring & response

    How we keep the posture current — and what happens if something goes wrong.

    Patch SLA
    Critical CVEs in 7 days. High in 30. Medium in 90. Low at next dependency bump. Tracked via GitHub Dependabot; pnpm.overrides used to pin security-critical packages.
    MFA on admin tools
    Multi-factor authentication enforced on every SaaS that touches user data: Vercel, Neon, GitHub, Plaid, Resend, the domain registrar.
    Incident response
    In the event of a confirmed security incident affecting user data, we will notify affected users within 72 hours with a clear description of what happened, what data was involved, and what we are doing about it. No legalese; no spin.
    Vulnerability reports
    Email security@ardenmoney.com. 72-hour acknowledgement target, 90-day coordinated disclosure window. Public credit on resolution unless you prefer anonymity.

Found something? Tell us.

We follow coordinated disclosure: 72-hour acknowledgement target, 90-day fix window, public credit when the fix ships (unless you want anonymity). Please don't run automated scanners against production — email first and we'll set you up with a sandbox.