Skip to main content
Engineering7 min readMarch 3, 2026

SaaS Security: The Non-Negotiables Before You Launch

Security shortcuts in early SaaS products create liabilities that are expensive to fix and fatal if exploited. Here's the security baseline every SaaS product needs before launch.

James Ross Jr.

James Ross Jr.

Strategic Systems Architect & Enterprise Software Developer

Security Debt Is Different From Technical Debt

Technical debt is the accumulated cost of shortcuts taken during development. You can carry a lot of technical debt and still ship a product that works. Security debt is different — it's a liability that sits dormant until someone decides to exploit it, and then it's not a gradual cost. It's an incident.

A data breach in a SaaS product doesn't just cost the remediation expense. It costs customer trust, regulatory exposure (GDPR fines can reach 4% of annual global revenue), legal liability, and often the company itself. In markets where customers are choosing between you and a competitor, a publicized breach can be the decision that sends them somewhere else.

The security baseline in this guide is not a complete security program. It's the minimum that every SaaS product needs before it handles real customer data.


Authentication Security

Password hashing. Passwords must be stored as hashes using bcrypt, Argon2, or scrypt. Never MD5, SHA-1, or plain SHA-256 — these are too fast to brute-force. Argon2id is my current recommendation: it's memory-hard (resistant to GPU-based attacks) and has an excellent TypeScript library. The cost factor should be set so hashing takes 100-300ms on your server hardware.

Password policies. Enforce a minimum of 12 characters. Allow passphrases. Don't impose arbitrary complexity requirements (capital + number + symbol) — NIST 800-63B retired this guidance in 2017. Do check passwords against known breach lists using an API like HaveIBeenPwned or the k-anonymity endpoint.

Multi-factor authentication. Implement TOTP (authenticator app) as a minimum. This should be mandatory for admin roles and optional (strongly encouraged) for regular users. Libraries like otpauth handle the TOTP implementation. Do not implement SMS-only 2FA — SS7 vulnerabilities make SMS TOTP a weaker signal than TOTP apps.

Session management. Sessions should expire after a period of inactivity (15-30 minutes for sensitive applications, longer for low-risk tools). Provide explicit session listing and revocation ("these are all devices logged in, click to revoke"). On password reset, revoke all existing sessions.

Rate limiting on auth endpoints. Login, password reset, and OTP validation endpoints must be rate-limited. A login endpoint that allows unlimited guesses is an invitation to credential stuffing. Use exponential backoff (5 failed attempts triggers a 15-minute lockout, with increasing delays), and consider adding CAPTCHA after 3 failures.


Data Security

Encryption at rest. Use your cloud provider's encrypted volumes (AWS EBS, GCP Persistent Disk with CMEK). For databases, enable encryption at rest in the database configuration. For particularly sensitive fields (SSNs, payment data, PII beyond contact information), consider column-level encryption using a symmetric key stored in a secrets manager (AWS Secrets Manager, HashiCorp Vault), not in your application config.

Encryption in transit. TLS 1.2 minimum, TLS 1.3 preferred, everywhere. No HTTP endpoints that handle data. HSTS header with a long max-age. No mixed content.

Secrets management. API keys, database passwords, JWT secrets — none of these should appear in your application code, source control, or .env files that get committed. Use a secrets manager or environment variable injection at deployment time. Rotate secrets on schedule (every 90 days for long-lived keys, more frequently for high-risk credentials).

SQL injection prevention. Use parameterized queries. If you're using an ORM (Prisma, Sequelize, TypeORM), the query builder generates parameterized queries by default for standard operations. Be extremely careful with any code that builds SQL strings dynamically — validate and sanitize every input, and prefer the ORM's query API over raw string interpolation.


Authorization: The Vulnerability Most Developers Underestimate

The OWASP Top 10 consistently puts broken access control at the top of the list, and with good reason. Authentication confirms who you are. Authorization determines what you can do. Authorization bugs are the most common category of serious vulnerability in SaaS applications.

Enforce authorization at the server, not the client. Hiding a button in the UI is not access control. Every API endpoint must verify that the authenticated user has permission to perform the requested action on the requested resource.

Tenant isolation is mandatory. Every database query that returns resources must filter by the authenticated user's organization. A query for /api/projects that returns all projects in the database is a multi-tenancy breach waiting to happen. Use a middleware layer or query helper that automatically applies the tenant scope.

Test authorization explicitly. Write tests that verify: user A cannot access user B's resources, a member cannot perform admin actions, an unauthenticated request is rejected. These are not edge cases — they're the primary test cases for your authorization layer.


HTTP Security Headers

These headers should be present on every response from your application:

Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{random}'
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

The Content-Security-Policy header is the most impactful and the most complex. It restricts what scripts can run on your pages, preventing XSS attacks even if an attacker manages to inject script content. A properly configured CSP is one of the most effective defenses against a large class of browser-based attacks.


Dependency Vulnerabilities

Your application's dependencies are part of your attack surface. Libraries you installed and never updated may have known vulnerabilities that are publicly documented and actively exploited.

Run npm audit (or the equivalent for your package manager) in CI. Fail the build if any high or critical vulnerabilities are present. Use Dependabot or Renovate to automate pull requests for dependency updates. Review the changelog when upgrading major versions.

This is a maintenance discipline, not a one-time fix. Vulnerabilities are discovered continuously.


The Pre-Launch Security Checklist

Before handling real customer data:

  • All passwords hashed with bcrypt or Argon2id
  • MFA implemented for admin accounts
  • Auth endpoints rate-limited
  • All API endpoints enforce authorization
  • Tenant isolation tested: user A cannot access user B's data
  • TLS everywhere, HSTS enabled
  • Security headers configured (CSP, X-Frame-Options, etc.)
  • No secrets in source control
  • SQL injection: ORM used or parameterized queries throughout
  • Dependency audit clean (no high/critical vulnerabilities)
  • Error messages don't expose stack traces or internal paths in production
  • Logging captures security events (login, permission denied, API key usage) without logging passwords or tokens

Security in SaaS is not a feature you add later. It's a set of engineering practices that need to be standard from day one. If you're preparing to launch a SaaS product and want a security review of your application, book a call at calendly.com/jamesrossjr — catching these issues before launch is significantly less painful than after.


Keep Reading