← All posts
vite react security headerssecurity headersvite reactreact securityheaders fix

How to Fix Missing Security Headers in a Vite React App

O

OverMCP Team

Quick answer

Missing security headers in a Vite React app leave your users vulnerable to attacks like XSS, clickjacking, and MIME sniffing. To fix them, you need to add security headers at the server or hosting level, and for local development, configure Vite's server headers. Use a tool like OverMCP's security headers checker to audit your site and verify the fix.

Why your Vite React app is missing security headers

When you build a React app with Vite, the output is a static bundle. Security headers are HTTP response headers that tell the browser how to behave. They are not part of your JavaScript or HTML by default; they are set by the server that serves your files. If you're deploying to a simple static host or a custom server, you might not have configured them.

AI coding tools like Cursor or v0 can scaffold a Vite React app quickly, but they often skip server configuration. That's why many AI-built apps go live without essential headers like Content-Security-Policy, X-Content-Type-Options, Referrer-Policy, and Strict-Transport-Security.

What to check first

Before you start adding headers, audit your current setup. Here's a quick checklist:

  • Visit your deployed site and check the response headers using your browser's DevTools (Network tab) or an online tool.
  • Look for these headers: Content-Security-Policy, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy, and Strict-Transport-Security.
  • If any are missing, you need to add them.
  • Determine your hosting platform: Vercel, Netlify, AWS S3, Nginx, or a custom Node server.
  • Check if you're using a service worker or a router that might affect headers.
  • If you're using Vercel, you can use OverMCP's Vercel security scanner to get a quick overview of your app's security posture.

    Step-by-step fix

    For local development (Vite dev server)

    During development, you can add headers to the Vite dev server by modifying your vite.config.ts file. Here's an example:

    // vite.config.ts
    import { defineConfig } from 'vite';
    import react from '@vitejs/plugin-react';
    
    export default defineConfig({
      plugins: [react()],
      server: {
        headers: {
          'Content-Security-Policy': "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';",
          'X-Content-Type-Options': 'nosniff',
          'X-Frame-Options': 'DENY',
          'Referrer-Policy': 'strict-origin-when-cross-origin',
          'Permissions-Policy': 'geolocation=(), microphone=(), camera=()',
        },
      },
    });

    This ensures that when you test locally, you see the headers in action.

    For production (hosting-specific)

    #### Vercel

    Create a vercel.json file in your project root:

    {
      "headers": [
        {
          "source": "/(.*)",
          "headers": [
            { "key": "Content-Security-Policy", "value": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';" },
            { "key": "X-Content-Type-Options", "value": "nosniff" },
            { "key": "X-Frame-Options", "value": "DENY" },
            { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
            { "key": "Permissions-Policy", "value": "geolocation=(), microphone=(), camera=()" }
          ]
        }
      ]
    }

    #### Netlify

    Create a netlify.toml file:

    [[headers]]
      for = "/*"
      [headers.values]
        Content-Security-Policy = "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';"
        X-Content-Type-Options = "nosniff"
        X-Frame-Options = "DENY"
        Referrer-Policy = "strict-origin-when-cross-origin"
        Permissions-Policy = "geolocation=(), microphone=(), camera=()"

    #### Nginx

    If you're serving your build from Nginx, add these lines to your server block:

    add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';";
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "DENY" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "geolocation=(), microphone=(), camera=()";

    #### Custom Node server

    If you're using Express, you can set headers in middleware:

    app.use((req, res, next) => {
      res.setHeader('Content-Security-Policy', "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';");
      res.setHeader('X-Content-Type-Options', 'nosniff');
      res.setHeader('X-Frame-Options', 'DENY');
      res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
      res.setHeader('Permissions-Policy', 'geolocation=(), microphone=(), camera=()');
      next();
    });

    After adding headers, deploy your app and re-check with the security headers checker. Also, test your app thoroughly, especially if you use inline styles or external scripts, as a strict CSP might break functionality.

    Common mistakes

    AI-built apps often get these wrong:

  • Forgetting the `always` directive in Nginx – Without it, headers might not be sent for error pages.
  • Copying a CSP that's too strict – A CSP like default-src 'self' can block inline scripts or styles that React apps often use. Use 'unsafe-inline' for styles if needed, or refactor to external styles.
  • Not testing after adding headers – A misconfigured CSP can break your app's functionality. Always test.
  • Ignoring local development – If you don't set headers in dev, you might not notice issues until production, where debugging is harder.
  • Assuming the host automatically adds headers – Many static hosts don't; you must configure them.
  • Why this matters for vibe-coded apps

    When you use AI tools to build your app, security is often an afterthought. The AI generates code that works, but it doesn't know your deployment environment. By fixing security headers, you protect your users from common attacks. OverMCP's free AI app security scanner can help you catch other issues like exposed secrets or misconfigurations.

    FAQ

    What are the most important security headers for a Vite React app?

    Content-Security-Policy (CSP), X-Content-Type-Options, X-Frame-Options, Referrer-Policy, and Permissions-Policy are crucial. CSP helps prevent XSS, X-Content-Type-Options prevents MIME sniffing, X-Frame-Options prevents clickjacking, and Referrer-Policy controls information leakage.

    How do I check if my Vite React app has security headers?

    Use your browser's DevTools (Network tab) to inspect response headers of your deployed site. Alternatively, use an online tool like OverMCP's security headers checker for a quick audit.

    Can I set security headers in the index.html file?

    No, security headers are HTTP response headers set by the server. You cannot set them in HTML. You must configure them at the server or hosting level. For local development, you can use Vite's server.headers option.

    Is your app secure?

    Free scan in 30 seconds. No signup needed.

    Scan My App Free