We Audited 50 Popular Web Applications: The Top 4 Security Mistakes We Found

Vergate Team5 min read

We ran our automated audit engine against 50 production web applications — SaaS tools, developer platforms, indie projects, and marketing sites. The goal was empirical: what are the most common security configuration failures on real sites, not theoretical OWASP lists?

The results were clear. Four issues appeared across the majority of the sample, and every one of them is fixable in under an hour.

#Finding 1: Missing or misconfigured security headers (68%)

The most common finding by far. 34 out of 50 sites were missing at least one critical security header.

What we checked:

HeaderSites missingImpact
Content-Security-Policy41 (82%)XSS attacks load unrestricted scripts
Strict-Transport-Security29 (58%)Protocol downgrade attacks
Permissions-Policy38 (76%)Browser features (camera, mic) accessible
X-Content-Type-Options22 (44%)MIME sniffing attacks
Cross-Origin-Opener-Policy45 (90%)Cross-origin information leaks

The pattern: most sites had Server: nginx or X-Powered-By: Express but no CSP, no HSTS, and no Permissions-Policy. The sites that had CSP often had Content-Security-Policy: * — which is equivalent to no CSP at all.

The fix (one code block):

javascript
// next.config.js — covers all routes
headers: async () => [{
  source: "/(.*)",
  headers: [
    { key: "Strict-Transport-Security", value: "max-age=63072000; includeSubDomains; preload" },
    { key: "X-Content-Type-Options", value: "nosniff" },
    { key: "X-Frame-Options", value: "SAMEORIGIN" },
    { key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=()" },
    { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
  ],
}],

For FastAPI, add the same headers via middleware. The exact mechanism varies by framework — the headers themselves don't.

#Finding 2: Verbose error logs leaked to clients (30%)

15 out of 50 sites returned raw stack traces, database connection strings, or internal file paths when fed malformed input. We tested with:

  • Invalid JSON in POST bodies
  • Overly long URL parameters
  • Special characters in path segments
  • Missing required fields in form data

What leaked:

  • Full Python/Node.js tracebacks with file paths and line numbers
  • Database connection strings (postgresql://user:password@host/db)
  • Internal API structure (/api/v1/internal/admin/users)
  • Library versions (django==4.2.1, express@4.18.2)

Why it matters: stack traces tell attackers exactly what framework and version you're running, what your directory structure looks like, and in some cases your database credentials. A single leaked traceback can be the reconnaissance that leads to a targeted exploit.

The fix: register a global exception handler that returns a generic error response while logging the full traceback server-side. Never run your API with DEBUG=true in production.

#Finding 3: Public staging endpoints (25%)

12 out of 50 sites had publicly reachable staging or development subdomains without any authentication:

  • staging.example.com — full application, no auth
  • dev.example.com — older version with known CVEs
  • admin-staging.example.com — admin panel, no password

The pattern: these aren't forgotten servers. They're active staging environments that were set up during development, deployed to, and never decommissioned. The DNS records are permanent. The applications are running. And because they're on different subdomains, they're not covered by the production site's security headers, CSP, or monitoring.

Why it matters: staging environments often have weaker security than production — relaxed CORS, debug mode enabled, test credentials hardcoded, older dependency versions. An attacker who finds staging.example.com has a lower-bar target with the same data access.

The fix:

  1. Audit your DNS records for subdomains you don't recognize
  2. Add authentication to every staging endpoint (basic auth at minimum)
  3. Set up automated subdomain discovery to catch drift
bash
# Quick subdomain audit
dig +short example.com ANY | grep -v "^$"
# Or use a tool like subfinder for comprehensive discovery

#Finding 4: Broken TLS certificate chains (17%)

8 out of 50 sites had TLS issues that caused intermittent failures on mobile devices and older browsers:

  • Missing intermediate certificates (chain incomplete)
  • Expired certificates on subdomains
  • TLS 1.0/1.1 still enabled alongside 1.2/1.3
  • Weak cipher suites (RC4, DES)

The pattern: the main domain (example.com) had a perfect TLS setup, but subdomains (api.example.com, cdn.example.com) had stale certificates or incomplete chains. This causes intermittent failures — the site works on Chrome desktop (which tolerates incomplete chains) but fails on mobile Safari and older Android browsers.

Why it matters: mobile traffic is 60%+ of web traffic. A broken TLS chain on a subdomain means a significant portion of your users see connection errors intermittently — and they blame your site, not their browser.

The fix:

bash
# Check your TLS chain
openssl s_client -connect example.com:443 -showcerts < /dev/null 2>&1 | grep -E "Verify|depth"

# Check for weak protocols
nmap --script ssl-enum-ciphers -p 443 example.com

Use Let's Encrypt with certbot (auto-renewal handles intermediate certificates) or a CDN that manages certificates for you (Cloudflare, Vercel, Fastly).

#The common thread

Every one of these findings is a configuration problem, not a code problem. None of them require rewriting application logic. They require someone to check the configuration, fix the gap, and set up monitoring to catch regressions.

That's the operational gap most teams have: the code works, the deploy succeeds, the tests pass — but the configuration drifts, and no one checks until something breaks.

#Test your own site

We compiled this data using Vergate's automated audit engine. Every finding in this post — headers, error leakage, exposed endpoints, TLS chain — is checked by a free passive scan in about 10 seconds.

Run it on your site at vergate.dev/free-scan. No account, no credit card, results immediately. See if your site has any of these 4 issues — and fix them before an automated scanner finds them for you.

Frequently asked questions

How were these 50 websites selected?

We scanned a cross-section of production web applications: SaaS products, developer tools, indie hacker projects, e-commerce sites, and marketing pages. The selection was non-random — we chose sites that represent the typical modern web stack (Next.js, React, Rails, Django, FastAPI) rather than large enterprises with dedicated security teams.

Are these findings specific to certain frameworks?

No. The top 4 issues are framework-agnostic. Missing security headers affect Next.js, Rails, Django, and static sites equally. Stack trace leakage happens in FastAPI, Express, and Rails when debug mode is enabled. Staging endpoints exist regardless of framework. TLS chain issues are a server configuration problem, not an application problem.

What's the most surprising finding?

The staging endpoint exposure (25%) was the highest surprise. These aren't forgotten test servers — they're full production applications on staging subdomains (staging.example.com, dev.example.com) with no authentication, no rate limiting, and often older versions with known CVEs. They're publicly reachable because DNS records are permanent and no one deletes them after the project launches.

Can I test my own site for these issues?

Yes. Run a free passive scan at vergate.dev/free-scan — it checks all 4 categories (headers, error leakage, exposed endpoints, TLS chain) in about 10 seconds with no account required.

Keep reading