Security with Nuxt Headers: Complete Guide to Hardening Your Application

Complete guide to configuring security headers in Nuxt 4 applications. Learn how to implement CSP, HSTS, X-Frame-Options, and other essential security headers using modern Nuxt 4 routeRules API. Includes real-world examples and best practices.

Michal Szajnecki
Michal Szajnecki
Jan 15, 202520 min read
Security with Nuxt Headers: Complete Guide to Hardening Your Application

Security headers are your first line of defense against common web vulnerabilities. Properly configured headers help protect your Nuxt application from XSS attacks, clickjacking, MIME type sniffing, and other security threats. This guide walks you through implementing security headers using Nuxt's modern APIs, with practical examples you can use right away. Whether you're preparing your application for a penetration test or simply want to follow security best practices, the techniques described here are essential steps in hardening your application's security posture.

Understanding Security Headers: Complete Overview

What Are Security Headers?

Security headers are HTTP response headers that instruct browsers how to behave when handling your site's content. They help prevent attacks like XSS, clickjacking, and protocol downgrades.

Expert Resources:

  • OWASP Secure Headers Project 1
  • Security Headers Scanner 2 - Test your site's headers
  • MDN HTTP Headers Reference 3

Essential Security Headers for Nuxt 4

1. Content Security Policy (CSP)

CSP helps prevent XSS attacks by controlling which resources can be loaded. In Nuxt 4, use routeRules for declarative header configuration.

Modern Nuxt 4 Configuration:

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    "/**": {
      headers: {
        "Content-Security-Policy": [
          "default-src 'self'",
          "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net",
          "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
          "font-src 'self' https://fonts.gstatic.com",
          "img-src 'self' data: https:",
          "connect-src 'self' https://api.example.com",
          "frame-ancestors 'none'",
        ].join("; "),
      },
    },
  },
});

References:

  • CSP Evaluator by Google 4 - Validate your CSP
  • CSP Cheat Sheet 5
  • YouTube: CSP Explained 6

2. X-Frame-Options

Prevents clickjacking attacks by controlling if your site can be embedded in frames. Note: Modern approach uses CSP frame-ancestors directive, but X-Frame-Options provides backward compatibility.

Nuxt 4 Example:

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    "/**": {
      headers: {
        "X-Frame-Options": "DENY", // or 'SAMEORIGIN' for same-origin embedding
      },
    },
  },
});

Expert Insights:

  • MDN X-Frame-Options 7
  • OWASP Clickjacking Defense 8

3. X-Content-Type-Options

Prevents MIME type sniffing attacks by instructing browsers not to guess content types.

Nuxt 4 Example:

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    "/**": {
      headers: {
        "X-Content-Type-Options": "nosniff",
      },
    },
  },
});

4. Strict-Transport-Security (HSTS)

Forces browsers to use HTTPS connections. Only enable in production environments.

Nuxt 4 Example:

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    "/**": {
      headers:
        process.env.NODE_ENV === "production"
          ? {
              "Strict-Transport-Security":
                "max-age=31536000; includeSubDomains; preload",
            }
          : {},
    },
  },
});

References:

  • HSTS Preload List 9 - Submit your domain
  • MDN HSTS 10

5. Referrer-Policy

Controls how much referrer information is sent with requests, helping protect user privacy.

Nuxt 4 Example:

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    "/**": {
      headers: {
        "Referrer-Policy": "strict-origin-when-cross-origin",
      },
    },
  },
});

6. Permissions-Policy (formerly Feature-Policy)

Controls browser features and APIs, restricting access to sensitive functionality like geolocation, camera, and microphone.

Nuxt 4 Example:

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    "/**": {
      headers: {
        "Permissions-Policy": [
          "geolocation=()",
          "microphone=()",
          "camera=()",
          "payment=(self)",
        ].join(", "),
      },
    },
  },
});

Complete Nuxt 4 Configuration: Modern Approach

Nuxt 4's routeRules API is the recommended modern approach for configuring security headers. It's declarative, type-safe, and works seamlessly with Nuxt's routing system.

Complete Nuxt 4 Security Headers Configuration:

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    // Global headers for all routes
    "/**": {
      headers: {
        "X-Content-Type-Options": "nosniff",
        "X-Frame-Options": "DENY",
        "Referrer-Policy": "strict-origin-when-cross-origin",
        "Permissions-Policy":
          "geolocation=(), microphone=(), camera=(), payment=(self)",
        "Content-Security-Policy": [
          "default-src 'self'",
          "script-src 'self'",
          "style-src 'self' 'unsafe-inline'",
          "img-src 'self' data: https:",
          "font-src 'self' https://fonts.gstatic.com",
          "connect-src 'self'",
          "frame-ancestors 'none'",
        ].join("; "),
        // Only in production
        ...(process.env.NODE_ENV === "production" && {
          "Strict-Transport-Security":
            "max-age=31536000; includeSubDomains; preload",
        }),
      },
    },
    // Specific headers for sensitive routes
    "/checkout/**": {
      headers: {
        "Content-Security-Policy": [
          "default-src 'self'",
          "script-src 'self' https://js.stripe.com",
          "connect-src 'self' https://api.stripe.com",
          "frame-ancestors 'none'",
        ].join("; "),
      },
    },
  },
});

Alternative: Server Middleware (For Dynamic Headers)

Use server middleware only when you need dynamic header generation based on request context.

// server/middleware/security-headers.ts
export default defineEventHandler((event) => {
  const headers: Record<string, string> = {
    "X-Content-Type-Options": "nosniff",
    "X-Frame-Options": "DENY",
    "Referrer-Policy": "strict-origin-when-cross-origin",
    "Permissions-Policy": "geolocation=(), microphone=(), camera=()",
    "Content-Security-Policy": "default-src 'self'; frame-ancestors 'none'",
  };

  // Only add HSTS in production
  if (process.env.NODE_ENV === "production") {
    headers["Strict-Transport-Security"] =
      "max-age=31536000; includeSubDomains; preload";
  }

  // Set headers
  Object.entries(headers).forEach(([key, value]) => {
    setHeader(event, key, value);
  });
});

Note: Prefer routeRules over middleware for static header configuration. Middleware is better for dynamic scenarios.

Testing Your Security Headers

Tools for Testing

  1. Security Headers Scanner
  2. Mozilla Observatory
  3. Google Lighthouse
    • Built into Chrome DevTools
    • Tests security headers in audits
  4. OWASP ZAP

Video Tutorials:

  • Security Headers Testing with Lighthouse 13
  • OWASP ZAP Tutorial 14

Common Pitfalls and Solutions

Problem: CSP Breaking Third-Party Scripts

Solution (Nuxt 4):

// nuxt.config.ts - Use routeRules with specific domains
export default defineNuxtConfig({
  routeRules: {
    "/**": {
      headers: {
        "Content-Security-Policy": [
          "default-src 'self'",
          "script-src 'self' https://trusted-cdn.com",
          "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
          "connect-src 'self' https://api.example.com",
        ].join("; "),
      },
    },
  },
});

Problem: HSTS Breaking Development

Solution (Nuxt 4):

// nuxt.config.ts - Conditionally add HSTS
export default defineNuxtConfig({
  routeRules: {
    "/**": {
      headers: {
        ...(process.env.NODE_ENV === "production" && {
          "Strict-Transport-Security":
            "max-age=31536000; includeSubDomains; preload",
        }),
      },
    },
  },
});

Real-World Examples: Nuxt 4 Implementations

Example 1: E-commerce Site with Payment Processing

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    // Global security headers
    "/**": {
      headers: {
        "X-Content-Type-Options": "nosniff",
        "X-Frame-Options": "DENY",
        "Referrer-Policy": "strict-origin-when-cross-origin",
      },
    },
    // Enhanced security for checkout
    "/checkout/**": {
      headers: {
        "Content-Security-Policy": [
          "default-src 'self'",
          "script-src 'self' https://js.stripe.com",
          "style-src 'self' 'unsafe-inline'",
          "img-src 'self' data: https:",
          "connect-src 'self' https://api.stripe.com https://api.stripe.com",
          "frame-src https://js.stripe.com",
          "frame-ancestors 'none'",
        ].join("; "),
        "Strict-Transport-Security":
          "max-age=31536000; includeSubDomains; preload",
      },
    },
  },
});

Example 2: Content-Heavy Site with External Resources

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    "/**": {
      headers: {
        "Content-Security-Policy": [
          "default-src 'self'",
          "script-src 'self' 'unsafe-inline' https://cdn.example.com https://www.googletagmanager.com",
          "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
          "font-src 'self' https://fonts.gstatic.com",
          "img-src 'self' data: https:",
          "media-src 'self' https:",
          "connect-src 'self' https://api.example.com https://www.google-analytics.com",
          "frame-ancestors 'none'",
        ].join("; "),
        "X-Content-Type-Options": "nosniff",
        "X-Frame-Options": "DENY",
        "Referrer-Policy": "strict-origin-when-cross-origin",
      },
    },
  },
});

Performance Considerations

Security headers have minimal performance impact, but consider:

  • CSP Evaluation: Browser must parse CSP on every request
  • HSTS Preload: Reduces redirect overhead
  • Header Size: Keep headers concise to avoid HTTP/2 header compression issues

Benchmarks:

  • HTTP/2 Header Compression 15
  • Security Headers Performance Impact 16

Nuxt 4 Security Headers Best Practices

  1. Use routeRules for Static Headers: Prefer Nuxt 4's routeRules API over middleware for static header configuration
  2. Start Strict, Relax as Needed: Begin with restrictive CSP, then add exceptions based on actual needs
  3. Test in Staging: Always test security headers in staging before production deployment
  4. Monitor Violations: Use CSP reporting endpoints to catch issues early
  5. Keep Updated: Security headers evolve; stay current with Nuxt 4 and browser best practices
  6. Use Tools: Leverage automated testing tools like securityheaders.com regularly
  7. Conditional Headers: Only enable HSTS and other production-only headers in production environments
  8. Route-Specific Rules: Use different security policies for different route patterns (e.g., stricter for /checkout/**)

Expert Resources:

  • Scott Helme's Security Headers Blog 17 - Security expert's insights
  • Troy Hunt's Security Headers Guide 18 - Detailed explanations
  • OWASP Security Headers Cheat Sheet 19

Frequently Asked Questions (FAQ)

What are security headers in Nuxt 4?

Security headers are HTTP response headers that instruct browsers how to handle your site's content, helping prevent attacks like XSS, clickjacking, and MIME type sniffing. In Nuxt 4, you configure them using the routeRules API in nuxt.config.ts.

How do I configure security headers in Nuxt 4?

Use Nuxt 4's routeRules API in nuxt.config.ts to declaratively set headers per route pattern. This is the recommended modern approach over server middleware for static configurations.

What is Content Security Policy (CSP)?

CSP is a security header that helps prevent XSS attacks by controlling which resources (scripts, styles, images, etc.) can be loaded by your application. It's one of the most important security headers.

Should I use X-Frame-Options or CSP frame-ancestors?

Modern best practice is to use CSP's frame-ancestors directive, but you can include both for backward compatibility. CSP frame-ancestors 'none' is more flexible and powerful.

Do I need HSTS in development?

No, HSTS should only be enabled in production. In development, it can cause issues with local HTTP connections. Use conditional configuration based on NODE_ENV.

How do I test my security headers?

Use tools like securityheaders.com, Mozilla Observatory, or Google Lighthouse to test and grade your security headers configuration.

Can I have different security headers for different routes?

Yes, Nuxt 4's routeRules allows you to define different headers for different route patterns. For example, you can have stricter CSP for /checkout/** routes.

What's the difference between routeRules and server middleware?

routeRules is declarative, type-safe, and better for static header configurations. Server middleware is better for dynamic headers that depend on request context or runtime conditions.


References

  1. OWASP. "Secure Headers Project." https://owasp.org/www-project-secure-headers/
  2. Security Headers. "Security Headers Scanner." https://securityheaders.com/
  3. MDN. "HTTP Headers Reference." https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
  4. Google. "CSP Evaluator." https://csp-evaluator.withgoogle.com/
  5. OWASP. "CSP Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html
  6. YouTube. "CSP Explained." https://www.youtube.com/results?search_query=content+security+policy+explained
  7. MDN. "X-Frame-Options." https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
  8. OWASP. "Clickjacking Defense." https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html
  9. HSTS Preload. "HSTS Preload List." https://hstspreload.org/
  10. MDN. "Strict-Transport-Security." https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
  11. MDN. "Permissions Policy." https://developer.mozilla.org/en-US/docs/Web/HTTP/Permissions_Policy
  12. MDN. "Feature Policy Guide." https://developer.mozilla.org/en-US/docs/Web/HTTP/Feature_Policy
  13. YouTube. "Lighthouse Security Headers." https://www.youtube.com/results?search_query=lighthouse+security+headers
  14. YouTube. "OWASP ZAP Tutorial." https://www.youtube.com/results?search_query=owasp+zap+tutorial
  15. HTTP/2 Working Group. "Header Compression." https://http2.github.io/http2-spec/compression.html
  16. Google. "Security Headers Performance." https://web.dev/security-headers/
  17. Scott Helme. "Security Headers Blog." https://scotthelme.co.uk/
  18. Troy Hunt. "Understanding HSTS." https://www.troyhunt.com/understanding-http-strict-transport/
  19. OWASP. "HTTP Headers Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html
Michal Szajnecki

Michal Szajnecki

Share Article: