← Back to Worth Flow
Security
Worth Flow is a personal hobby project. Here is how your data is protected.
All financial calculations run in your browser. Worth Flow has no application server, and no third party ever sees the contents of your financial plan.
Security properties at a glance
Client-side compute
All projections run locally in your browser - nothing is sent to a server.
Per-user data isolation
Cloud saves are stored in a private S3 prefix scoped exclusively to your account via IAM policy.
Encryption at rest
S3 storage uses AES-256 server-side encryption (SSE-S3) for all saved plans.
Encryption in transit
All connections use TLS. Non-TLS requests to S3 are denied by bucket policy.
No static credentials
The app uses short-lived IAM credentials from Cognito Identity Pool - no long-lived AWS keys anywhere.
No secrets in source
Only public identifiers (region, pool IDs) ship in the client bundle. No passwords, keys, or secrets.
Zero-knowledge AI key vault
The optional AI assistant encrypts your provider API key and chat in your browser (PBKDF2 + AES-GCM) with a passphrase only you know. We store only ciphertext.
Authentication
Accounts use email + password via Amazon Cognito. Worth Flow never handles or stores
your password directly - Cognito manages credentials with the Secure Remote Password (SRP) protocol,
so your password is never sent over the wire. Creating an account requires verifying your email with a
6-digit code (valid for 24 hours).
Password Policy
- At least 8 characters
- With an uppercase letter
- A lowercase letter
- And a number
Both account verification and password reset use codes emailed from noreply@worthflow.in,
delivered through Amazon SES with DKIM and SPF authentication.
Per-user data isolation
When you sign in, the Cognito Identity Pool exchanges your JWT for temporary IAM credentials.
These credentials are restricted by policy to your own S3 prefix:
arn:aws:s3:::worth-flow-saves/users/<your-identity-id>/*
Attempting to read or write another user's prefix is denied by AWS at the IAM level -
the application layer cannot override this.
AI assistant (optional, bring-your-own-key)
The AI assistant is optional and uses your own Google Gemini API key. Its security model:
- Zero-knowledge at rest. Your API key and chat are encrypted in your browser with a
passphrase only you know (PBKDF2-derived AES-GCM key). We store only ciphertext and can never read
either; forgetting the passphrase wipes both.
- No server in the path. Requests go browser-direct to Google Gemini
with your key - Worth Flow runs no proxy and never sees your key or your prompts.
- Tight egress. The Content-Security-Policy allows the assistant to connect only to
generativelanguage.googleapis.com (alongside AWS and
Cognito) - nothing else.
- Least data. Only forecast figures and plan summaries are sent; credentials and
internal IDs are never included.
Browser security headers
The app is served with the following security headers on every response:
- Strict-Transport-Security - HSTS with preload, 2-year max-age.
- Content-Security-Policy - restricts script, style, and connection sources; outbound connections are allow-listed to AWS, Cognito, and the Gemini API only.
- X-Frame-Options: DENY - prevents clickjacking.
- X-Content-Type-Options: nosniff - prevents MIME sniffing.
- Referrer-Policy: strict-origin-when-cross-origin.
- Permissions-Policy - camera, microphone, geolocation all disabled.
Source code
Worth Flow is open source. You can review the code, infrastructure definitions (Terraform), and
security model on GitHub.
Responsible disclosure
Found a security issue? Please report it privately - do not open a public issue for
vulnerabilities. Use GitHub's private vulnerability reporting at
Security → Report a vulnerability.
I'll acknowledge within 48 hours and work on a fix promptly.
Worth Flow is a one-person hobby project. There is no bug bounty programme. Reports are appreciated
and will be credited (with your permission) once fixed.