DraftThis post is not published yet. Change status: "draft" to status: "published" in frontmatter to publish.

The Most Common Security Vulnerabilities We Find When Pentesting SaaS Applications

Based on hundreds of real penetration tests, here are the security vulnerabilities we find most often in SaaS applications, with practical remediation guidance for each.

13 min read·

At Bastion, we conduct penetration tests for SaaS companies preparing for SOC 2, ISO 27001, and security-conscious enterprise customers. After reviewing hundreds of applications, clear patterns have emerged. The same vulnerabilities appear repeatedly, regardless of the tech stack, team size, or funding stage.

This isn't a theoretical list pulled from OWASP documentation. These are real issues we find in production applications, anonymized from actual assessments. Understanding these patterns can help you identify and fix vulnerabilities before an attacker, or a pentester, finds them first.

Why SaaS Applications Are Attractive Targets

SaaS applications are prime targets for supply chain attacks. Compromising a single SaaS vendor can give attackers access to hundreds or thousands of downstream customers, their data, and their credentials. Instead of breaching companies one by one, attackers focus on the software those companies depend on. A vulnerability in your application isn't just your problem, it's a potential entry point into every organization that trusts you with their data.

The rapid development pace at most SaaS companies compounds the risk. Features ship quickly, security reviews happen inconsistently, and technical debt accumulates. By the time a company reaches Series A or starts pursuing enterprise customers, years of security shortcuts have become embedded in the codebase.

Here's what we find most often.

Authentication and Session Management

Authentication vulnerabilities remain the most common category we encounter. The issues range from missing controls to subtle implementation flaws that bypass existing protections.

Rate Limiting Gaps

Most applications implement rate limiting on authentication endpoints, but stop there. We regularly find applications where the login endpoint is rate-limited, but the password reset endpoint isn't. Or the primary API is protected, but internal endpoints used by the frontend have no limits at all.

Rate limiting needs to be comprehensive. Every endpoint that accepts user input, processes data, or could be used for enumeration needs appropriate limits.

What we find:

  • Rate limiting only on /login, not on /api/* endpoints
  • Password reset endpoints with no rate limits
  • Account enumeration through unprotected email lookup endpoints

Remediation: Implement rate limiting at the API gateway or reverse proxy level to ensure consistent coverage. Set appropriate limits based on legitimate usage patterns, typically 100-1000 requests per minute for authenticated endpoints, lower for authentication flows.

Weak Password Policies

We still encounter applications with password minimums of 8 characters and no other requirements. While password complexity rules have fallen out of favor (NIST no longer recommends them), password length remains important. An 8-character password can be cracked relatively quickly with modern hardware.

What we find:

  • Minimum password length of 8 characters with no other requirements
  • No password strength estimation or feedback
  • No checks against common password lists

Remediation: Require a minimum of 12 characters. Consider implementing password strength estimation using libraries like zxcvbn. Check new passwords against breach databases using the HaveIBeenPwned API (which supports k-anonymity, so you're not sending actual passwords).

Account Enumeration

Account enumeration allows attackers to determine which email addresses have accounts in your system. This information enables targeted phishing attacks and credential stuffing with known-valid usernames.

What we find:

  • Login page returns "Invalid password" vs "User not found" (reveals if email exists)
  • Password reset says "Instructions sent" only for valid emails
  • Registration immediately rejects existing email addresses with a distinct error

Remediation: Return identical responses regardless of whether an account exists. For login: "Invalid email or password." For password reset: "If an account exists, instructions have been sent." For registration, either delay the duplicate check until email verification, or implement a consistent delay to prevent timing-based enumeration.

Session Management Issues

Long-lived tokens, missing security flags on cookies, and improper session handling create opportunities for session hijacking.

What we find:

  • Access tokens valid for 10+ hours instead of 15-60 minutes
  • Session cookies missing SameSite, Secure, or HttpOnly flags
  • No session invalidation when user changes password or email
  • OTPs (one-time passwords) that remain valid after failed verification attempts
  • Password reset that clears account lockout state

Remediation: Use short-lived access tokens (15-60 minutes) with refresh token rotation. Set session cookies with SameSite=Strict for maximum protection, or SameSite=Lax if your application requires cookies to be sent on top-level navigations from external sites. Always include Secure and HttpOnly flags. Invalidate all sessions when security-relevant account changes occur.

MFA Bypass

Multi-factor authentication provides strong protection when implemented correctly. When implemented incorrectly, it provides false confidence.

What we find:

  • MFA can be bypassed by calling the API directly, skipping the frontend MFA prompt
  • MFA enrollment not enforced at the API level
  • Recovery codes that work indefinitely without MFA re-enrollment
  • MFA check only on web login, not on API token generation

Remediation: Enforce MFA at the API layer, not just the frontend. After initial authentication, require MFA verification before issuing a full-privilege token. Include MFA status in the session token and verify it for sensitive operations.

Authorization and Access Control

Authorization flaws are the second most common category and often the most severe. A single IDOR (Insecure Direct Object Reference) vulnerability can expose your entire database.

Broken Object-Level Authorization (BOLA/IDOR)

This vulnerability allows users to access resources belonging to other users or organizations by manipulating identifiers in API requests. The Moltbook data breach is a recent example of how broken access control can expose millions of records.

What we find:

  • GET /api/organizations/{id} returns data for any organization ID
  • Users can access any document by guessing sequential IDs
  • API endpoints check authentication but not authorization
  • Export functionality includes data from all users, not just the requesting user

Remediation: Every API endpoint that accesses resources must verify the requesting user has permission to access that specific resource. Implement this at the data layer (e.g., adding WHERE organization_id = :user_org_id to queries) or through a consistent authorization middleware. Use UUIDs instead of sequential integers to make ID guessing harder (but don't rely on this as your only protection).

Missing Function-Level Access Control

Different users have different permission levels, but the backend doesn't always enforce this properly.

What we find:

  • Standard users can call admin API endpoints
  • Permission checks exist in the frontend but not the backend
  • Role changes can be self-assigned through the API
  • Soft-deleted users can still authenticate and access resources

Remediation: Implement role-based access control (RBAC) at the API layer. Define which roles can access which endpoints and enforce this in middleware that runs before any handler code. Never trust frontend-only permission checks.

Multi-Tenancy Failures

SaaS applications serve multiple customers from shared infrastructure. When tenant isolation fails, one customer can access another's data.

What we find:

  • Missing tenant context in database queries
  • Tenant ID pulled from user-supplied input rather than the authenticated session
  • Shared resources (like file storage) without proper access controls
  • AI chat history accessible across tenants via predictable identifiers

Remediation: Include tenant context automatically in all database queries through ORM middleware or query builders. Never accept tenant ID from request parameters, always derive it from the authenticated session. Audit all data access patterns for cross-tenant leakage.

CORS Misconfiguration

Cross-Origin Resource Sharing misconfigurations can allow malicious websites to make authenticated requests to your API.

What we find:

  • Access-Control-Allow-Origin: * on authenticated endpoints
  • Origin reflected back without validation
  • Credentials allowed with wildcard origin

Remediation: Maintain an explicit allowlist of permitted origins. Never reflect the Origin header back without validation. Don't use Access-Control-Allow-Credentials: true with wildcard origins (browsers block this, but your configuration shouldn't rely on it).

Input Validation and XSS

Cross-site scripting remains prevalent despite years of framework improvements. The vulnerability has evolved, but it hasn't disappeared.

Stored XSS

Stored XSS occurs when malicious input is saved to the database and rendered to other users without proper encoding.

What we find:

  • User-generated content (notes, comments, profile fields) rendered without encoding
  • Rich text editors that allow arbitrary HTML
  • Organization names and other "internal" fields that end up in admin interfaces
  • SVG uploads that execute JavaScript when viewed

Remediation: Encode all user-supplied content before rendering. Use your framework's built-in encoding (React's JSX, Vue's double-brace syntax, etc.) and be cautious with "dangerouslySetInnerHTML" or equivalent features. For rich text, use a sanitization library like DOMPurify with a strict allowlist of tags and attributes.

Email Template Injection

Email templates are a common XSS vector that security teams often overlook.

What we find:

  • User-supplied data included in emails without HTML encoding
  • Template injection allowing arbitrary content in transactional emails
  • Phishing opportunities through manipulated email content

Remediation: HTML-encode all user-supplied data in email templates. Use your email service provider's templating features rather than string concatenation. Review email templates as carefully as you review web pages.

File Upload Vulnerabilities

File upload functionality requires careful security consideration. The attack surface includes the upload process, storage, and retrieval.

What we find:

  • No file type restrictions, allowing executable uploads
  • File type validation only on the client side
  • No antivirus or malware scanning of uploaded content
  • Files served inline rather than as downloads, enabling XSS through uploaded HTML/SVG
  • Unsigned or non-expiring URLs for sensitive file access
  • Storage buckets with overly permissive access policies

Remediation: Validate file types on the server using content inspection, not just file extensions. Scan uploaded files for malware before making them available. Serve user-uploaded files with Content-Disposition: attachment to prevent browser execution. Use signed URLs with short expiration times for sensitive files. Store uploads in separate storage buckets with appropriate access controls.

AI and LLM Security

As SaaS applications increasingly integrate AI features, a new category of vulnerabilities has emerged.

What we find:

  • AI assistants that can be manipulated to reveal system prompts and internal configuration
  • LLM agents that disclose available tools and capabilities when prompted creatively
  • Prompt injection that bypasses safety controls
  • AI-generated content rendered without sanitization
  • Chat histories shared across tenant boundaries

Remediation: Treat AI-generated content as untrusted input that requires sanitization. Implement robust prompt filtering, though recognize its limitations. Don't rely on the AI to enforce access controls; verify permissions before providing data to the model. Log and monitor AI interactions for abuse patterns. Consider rate limiting AI features more aggressively than traditional endpoints.

Infrastructure and Configuration

Even well-coded applications can be compromised through infrastructure misconfigurations. We cover the most common cloud-specific issues in our guide on AWS security misconfigurations.

Network Exposure

Services that should be internal get exposed to the internet.

What we find:

  • SSH (port 22) exposed to 0.0.0.0/0
  • Database ports (PostgreSQL, Redis) publicly accessible
  • Internal services on non-standard ports accessible from the internet
  • Kubernetes API servers exposed without IP restrictions

Remediation: Default to private networking. Use security groups/firewall rules that explicitly allow only necessary traffic. Access internal services through bastion hosts, VPNs, or tools like AWS Systems Manager Session Manager. Regularly audit exposed ports using tools like Shodan or your cloud provider's security findings.

Information Disclosure

Detailed error messages and exposed internal endpoints help attackers understand your system.

What we find:

  • Verbose error messages including function names, file paths, and stack traces
  • Server technology disclosed in HTTP headers (X-Powered-By, Server)
  • API documentation (Swagger/OpenAPI) publicly accessible
  • Internal endpoints exposed (/metrics, /health, /debug)
  • Source maps included in production JavaScript builds
  • JWT tokens containing sensitive data (PII, internal IDs) in payloads
  • Auth tokens passed as URL query parameters (visible in logs and browser history)

Remediation: Return generic error messages to users while logging detailed errors server-side. Remove or customize server headers. Protect API documentation behind authentication. Remove or restrict internal endpoints in production. Don't include source maps in production builds. Keep JWT payloads minimal, store sensitive data server-side.

Missing Security Headers

HTTP security headers provide defense-in-depth against various attacks.

What we find:

  • Missing Strict-Transport-Security (allows SSL stripping attacks)
  • Missing X-Content-Type-Options (allows MIME sniffing attacks)
  • Missing X-Frame-Options or Content-Security-Policy frame-ancestors (allows clickjacking)
  • Missing Content-Security-Policy (allows various injection attacks)

Remediation: Implement all standard security headers. At minimum:

Text
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'

Tune Content-Security-Policy based on your application's needs, starting restrictive and relaxing as necessary.

Outdated TLS Configuration

Legacy TLS configurations leave connections vulnerable to known attacks.

What we find:

  • TLS 1.0 and 1.1 still enabled
  • Weak cipher suites supported
  • HTTP connections allowed without redirect to HTTPS

Remediation: Support only TLS 1.2 and 1.3. Disable weak cipher suites. Redirect all HTTP traffic to HTTPS. Use tools like SSL Labs' SSL Test to verify your configuration.

Hardcoded Credentials

Secrets embedded in code eventually leak through repositories, logs, or client-side bundles. For a deeper dive into this topic, see our guide on secrets management best practices.

What we find:

  • API keys in frontend JavaScript bundles
  • Database credentials in configuration files committed to repositories
  • Service account credentials in Docker images
  • Secrets visible in CI/CD logs

Remediation: Use environment variables or secret management services for all credentials. Scan repositories for secrets using tools like gitleaks or truffleHog. Review what gets included in client-side bundles. Mask secrets in CI/CD output.

Building Security Into Your Development Process

Finding these vulnerabilities in a pentest means they've likely been present in production for months or years. A more effective approach builds security into the development process.

Shift security left: Include security requirements in user stories. Train developers on common vulnerabilities. Use static analysis tools in CI/CD pipelines.

Conduct regular code reviews with security focus: Not every code review needs a full security audit, but reviewers should flag obvious issues like missing authorization checks or unsanitized output.

Implement security testing: Include authentication and authorization tests in your test suite. Test that users cannot access resources they shouldn't.

Schedule regular penetration tests: Annual pentests catch vulnerabilities that slip through other processes. More frequent testing is better, especially after major feature releases. If you're pursuing compliance certifications, learn about the differences between SOC 2 and ISO 27001 to understand which framework fits your needs.

Conclusion

The vulnerabilities described here aren't exotic or sophisticated. They're the same issues the security industry has discussed for decades, appearing in new contexts and with new technologies. Broken authentication, broken access control, injection, and misconfiguration account for the vast majority of what we find.

The good news is that these patterns are well-understood and preventable. Consistent application of security fundamentals, authentication, authorization, input validation, secure configuration, will eliminate most of what makes it onto a pentest report.

If you're reading this and recognizing patterns from your own application, you're not alone. Most SaaS applications have some subset of these issues. The important thing is to find and fix them proactively, before they become a breach notification.


Bastion provides penetration testing and compliance services for SaaS companies. If you're preparing for SOC 2, responding to enterprise security questionnaires, or simply want to understand your security posture, contact us to discuss how we can help. You can also learn more about how a Virtual CISO can streamline your compliance journey.

Share this article

Other platforms check the box

We secure the box

Get in touch and learn why hundreds of companies trust Bastion to manage their security and fast-track their compliance.

Get Started