Missing Security Headers: The #1 Issue in Vibe-Coded Web Apps - VibeDoctor 
← All Articles 🛡️ Security Headers High

Missing Security Headers: The #1 Issue in Vibe-Coded Web Apps

Most AI-generated apps ship with zero security headers. Learn about HSTS, CSP, X-Frame-Options and how to add them in one config change.

HDR-001 HDR-002 HDR-003 HDR-004 HDR-005 HDR-006

Quick Answer

Security headers are HTTP response headers that instruct browsers on how to handle your site's content. Without them, your app is vulnerable to clickjacking, cross-site scripting, protocol downgrade attacks, and information leakage. AI-generated apps built with Bolt, Lovable, v0, and Cursor almost universally ship with zero security headers - they are the single most common finding in vibe-coded web applications.

Why Vibe-Coded Apps Have No Security Headers

Security headers live in HTTP responses, not in application logic. They're set in server configuration, middleware, or framework config files - layers that AI tools either skip or treat as optional boilerplate. When Bolt scaffolds a Next.js app or Lovable generates a React frontend, it produces components and API routes. It does not produce a next.config.js with a complete security headers block.

The OWASP Foundation consistently lists missing security headers in its Web Security Testing Guide as low-effort, high-impact findings. According to the Mozilla Observatory, less than 30% of websites on the internet implement a Content Security Policy - and among newly deployed vibe-coded apps, the number is far lower. The 2024 Qualys Web Application Security Report found that missing Strict-Transport-Security headers affected 54% of scanned applications.

These headers cost almost nothing to add. A single configuration block can harden your entire application against multiple attack classes in under 10 minutes.

Before: A Typical Vibe-Coded App Response

Here is what an HTTP response from an AI-generated Next.js app deployed to Vercel looks like without any security header configuration:

$ curl -I https://your-vibe-app.vercel.app

HTTP/2 200
content-type: text/html; charset=utf-8
x-vercel-id: iad1::abc123
cache-control: private, no-cache, no-store, max-age=0, must-revalidate

# Missing headers:
# - Strict-Transport-Security (HSTS)
# - Content-Security-Policy
# - X-Frame-Options
# - X-Content-Type-Options
# - Referrer-Policy
# - Permissions-Policy

After: A Properly Configured Response

$ curl -I https://your-vibe-app.vercel.app

HTTP/2 200
content-type: text/html; charset=utf-8
strict-transport-security: max-age=63072000; includeSubDomains; preload
content-security-policy: default-src 'self'; script-src 'self' 'nonce-{nonce}'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://your-api.supabase.co
x-frame-options: DENY
x-content-type-options: nosniff
referrer-policy: strict-origin-when-cross-origin
permissions-policy: camera=(), microphone=(), geolocation=()

What Each Header Does

Header Check ID What It Prevents Recommended Value
Strict-Transport-Security HDR-001 Protocol downgrade attacks, forces HTTPS max-age=63072000; includeSubDomains; preload
Content-Security-Policy HDR-002 XSS, data injection, script hijacking Start with default-src 'self' and expand
X-Frame-Options HDR-003 Clickjacking attacks via iframes DENY or SAMEORIGIN
X-Content-Type-Options HDR-004 MIME-sniffing attacks nosniff
Referrer-Policy HDR-005 Leaking URL paths to third parties strict-origin-when-cross-origin
Permissions-Policy HDR-006 Unauthorized access to camera, mic, location camera=(), microphone=(), geolocation=()

Adding Security Headers in Next.js

For Next.js apps - the most common target for Bolt, v0, and Cursor - security headers are added in next.config.js. This applies them to every response from your application:

// ✅ GOOD - next.config.js with security headers
const securityHeaders = [
  {
    key: 'Strict-Transport-Security',
    value: 'max-age=63072000; includeSubDomains; preload',
  },
  {
    key: 'X-Frame-Options',
    value: 'DENY',
  },
  {
    key: 'X-Content-Type-Options',
    value: 'nosniff',
  },
  {
    key: 'Referrer-Policy',
    value: 'strict-origin-when-cross-origin',
  },
  {
    key: 'Permissions-Policy',
    value: 'camera=(), microphone=(), geolocation=()',
  },
  {
    key: 'Content-Security-Policy',
    value: [
      "default-src 'self'",
      "script-src 'self' 'unsafe-eval' 'unsafe-inline'", // tighten after testing
      "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
      "img-src 'self' data: https:",
      "font-src 'self' https://fonts.gstatic.com",
      "connect-src 'self'",
    ].join('; '),
  },
];

/** @type {import('next').NextConfig} */
const nextConfig = {
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: securityHeaders,
      },
    ];
  },
};

module.exports = nextConfig;

Content Security Policy: Start Simple, Tighten Over Time

CSP is the most powerful header on the list, and also the most complex. A misconfigured CSP can break your application by blocking legitimate scripts, stylesheets, or API calls. The safe approach is to start permissive and tighten iteratively.

Use CSP report-only mode first: set Content-Security-Policy-Report-Only instead of Content-Security-Policy. This logs violations without enforcing them. Review the violation reports in your browser DevTools console or a reporting endpoint, then tighten the policy until violations stop.

For apps using Google Fonts (common in Lovable-generated designs), Supabase API calls, and Vercel Analytics, your CSP connect-src and font-src directives will need to explicitly allow those domains. The table above shows which sources are commonly needed.

How to Find Missing Headers in Your App

Tools like VibeDoctor (vibedoctor.io) automatically scan your deployed web app for missing security headers and flag which of HDR-001 through HDR-006 are absent from your HTTP responses. Free to sign up.

You can also check manually using the Mozilla Observatory at observatory.mozilla.org, SecurityHeaders.com, or by running curl -I your-domain.com and reviewing the response headers. Any production app scoring below B on the Mozilla Observatory has fixable issues that can be resolved in under an hour.

FAQ

Will adding a strict CSP break my Bolt or Lovable app?

Possibly, initially. Vibe-coded apps often use inline styles and scripts that CSP blocks by default. Start with Content-Security-Policy-Report-Only to identify violations, then either refactor inline code or add specific allowances. The unsafe-inline allowance for styles is a common concession for AI-generated apps using component libraries.

Does Vercel add any security headers automatically?

Vercel adds a few headers by default (like X-Vercel-ID) but does not automatically add security-critical headers like HSTS, CSP, or X-Frame-Options. You must configure them explicitly in next.config.js or vercel.json. Vercel's documentation recommends the next.config.js headers() approach for Next.js apps.

What is clickjacking and how does X-Frame-Options prevent it?

Clickjacking embeds your site in an invisible iframe on an attacker's page, tricking users into clicking buttons they cannot see. X-Frame-Options: DENY prevents any site from embedding your pages in a frame. The modern equivalent is CSP frame-ancestors 'none', which overrides X-Frame-Options when both are present.

Is HSTS safe to add immediately?

Only if your site is already fully on HTTPS. HSTS tells browsers to never connect over HTTP again for the specified duration. If you add it while any part of your site is still accessible over HTTP, you may lock out users. Start with a short max-age (e.g., 300 seconds) and increase it to 63072000 (2 years) once you are confident.

Do these headers need to be set on API routes too?

For API responses, HSTS and X-Content-Type-Options are valuable. CSP and X-Frame-Options are less relevant for JSON API endpoints but harmless to include. The Next.js headers() configuration applies to all routes matching the source pattern, so using source: '/(.*))' covers both pages and API routes uniformly.

Scan your codebase for this issue - free

VibeDoctor checks for HDR-001, HDR-002, HDR-003, HDR-004, HDR-005, HDR-006 and 128 other issues across 15 diagnostic areas.

SCAN MY APP →
← Back to all articles View all 129+ checks →