Security

Security at FinTrakker

FinTrakker handles sensitive licensing data — NMLS IDs, state license numbers, renewal dates — on behalf of fintech compliance teams. Here's how we protect it.

Data Encryption

All data at rest is encrypted using AES-256. This includes license records, user account data, alert histories, and webhook configurations stored in our PostgreSQL database.

All data in transit is encrypted using TLS 1.2 or higher. Connections to the API, dashboard, and webhook endpoints are HTTPS-only. HTTP requests are redirected to HTTPS at the network edge.

Authentication

User sessions are authenticated with JSON Web Tokens (JWT) with configurable expiry. Passwords are hashed using bcrypt before storage. We do not store plaintext credentials at any layer.

  • JWT tokens are signed with a secret stored only in the server environment, never committed to source or logged.
  • bcrypt hash rounds are set to a work factor that keeps brute-force cost high on current hardware.
  • Session management tracks active tokens server-side, allowing revocation on logout or account change.
  • Login attempts are rate-limited to 10 per minute per IP. Signup is rate-limited to 5 per hour per IP.

Webhook Security

Every webhook delivery is signed with HMAC-SHA256 using a per-endpoint secret key. The signature is included in the X-FT-Signature request header.

Replay protection is enforced by including a UTC timestamp in every payload. Webhook receivers should reject events with a timestamp older than 5 minutes.

// Verify webhook signature (Node.js example) const crypto = require('crypto'); const secret = process.env.FT_WEBHOOK_SECRET; const signature = req.headers['x-ft-signature']; const body = JSON.stringify(req.body); const expected = crypto .createHmac('sha256', secret) .update(body) .digest('hex'); if (signature !== expected) return res.status(401).end();

Webhook endpoints must use HTTPS. Private IP addresses and localhost destinations are blocked at registration time to prevent SSRF attacks.

Access Control

Access within FinTrakker is governed by role-based access control. Users can only access data belonging to their own account. There are no shared credentials between accounts, and no cross-account data access paths exist in the API.

  • Each account's license records, alert histories, and webhook configurations are scoped by account ID at the query layer.
  • Internal API endpoints (scraping, admin stats, digest delivery) require a separate internal key, distinct from user-facing JWTs.
  • Database roles follow least privilege: the application role has no DDL permissions in production.

Data Retention

Alert history is retained for 13 months, which covers a full annual compliance review cycle for license renewals that occur once per year. Scrape run logs are retained for 90 days.

All account data, including license records, alert history, and webhook configurations, is deleted within 30 days of account cancellation upon written request to [email protected].

Infrastructure

FinTrakker is hosted on Hetzner Cloud in the Ashburn, Virginia data center. This is a single-region deployment. No license data is replicated to additional regions.

  • Server-level firewall restricts inbound access to HTTPS (443), SSH (key-only, no password auth), and internal service ports.
  • No third-party analytics scripts have access to license data or API responses. Analytics (PostHog) are limited to marketing pages only.
  • Database backups are encrypted and retained for 7 days.

Compliance Posture

FinTrakker is not currently SOC 2 Type II certified. A SOC 2 Type II audit is in planning. Annual penetration testing is scheduled. FinTrakker does not process card data and is not in scope for PCI DSS.

  • Stripe handles all payment card processing. FinTrakker never receives or stores raw card numbers.
  • Stripe webhook signatures are verified on every inbound billing event before any action is taken.

GAUNTLET Audit

FinTrakker passed a 3-round adversarial security audit (GAUNTLET) before launch, covering SQL injection, IDOR, authentication gaps, XSS, and hardcoded secrets. All findings were resolved before the platform opened to subscribers.

GAUNTLET audit passed — 3 rounds, all findings resolved

Responsible Disclosure

Report security issues to [email protected]. We respond within 24 hours and will work with you to resolve valid vulnerabilities before public disclosure. We do not take legal action against good-faith security researchers who follow responsible disclosure practices.