CardWise handles sensitive financial data. This document outlines the security measures in place.
- Never stored in database, files, logs, or cookies
- Passed in HTTP request body (POST
/api/scrape) over HTTPS - Exist only in Node.js process memory during the scrape operation
- Discarded immediately after
israeli-bank-scraperscompletes - Frontend clears input fields after successful scrape
autoComplete="off"on credential input fields
- Hashed with bcrypt (12 salt rounds) before comparison
- Original password stored only as environment variable
- Never logged or exposed in API responses
- Session-based auth with
express-session - HTTP-only cookies (not accessible via JavaScript)
- Secure flag in production (HTTPS only)
- SameSite=Lax (CSRF protection)
- 1-hour session TTL
- Session destroyed on logout
| Endpoint | Limit | Window |
|---|---|---|
| General API | 100 requests | 15 minutes |
| Scrape | 5 requests | 1 hour |
| AI endpoints | 30 requests | 15 minutes |
- CORS: Restricted to configured
FRONTEND_URLorigin - Helmet: Sets security headers (X-Frame-Options, CSP, etc.)
- HTTPS: Enforced in production via PaaS (Azure/AWS)
- Database: Encrypted at rest (PaaS-managed)
The sanitizeForLog() utility strips sensitive fields (password, username, token, secret, apiKey) from objects before logging. All request logging must use this utility.
All secrets are managed via environment variables, never committed to source:
APP_PASSWORD— App login passwordSESSION_SECRET— Session signing keyDATABASE_URL— PostgreSQL connection stringAZURE_OPENAI_API_KEY— Azure OpenAI key
In production, use Azure Key Vault or AWS Secrets Manager.
- Dependencies are pinned in
package-lock.json - GitHub Dependabot enabled for security updates
- No credential-containing packages in the dependency tree