The Security Headers Gap: How AI Assistants Ship Insecure Apps | Deployxa

AI assistants build apps without security headers like CSP, HSTS, and X-Frame-Options, leaving them vulnerable to XSS and clickjacking. Here are the 7 fixes.

← Back to Dispatch Articles
Engineering Log

The Security Headers Gap: How AI Assistants Ship Insecure Apps

AI assistants build apps without security headers like CSP, HSTS, and X-Frame-Options, leaving them vulnerable to XSS and clickjacking. Here are the 7 fixes.

The Security Headers Gap

You built an app with Cursor, deployed it, and ran a security scan with Mozilla Observatory. The score was F. Your app is missing critical security headers like Content-Security-Policy, Strict-Transport-Security, and X-Frame-Options, which leaves it vulnerable to XSS (cross-site scripting), clickjacking, and MIME-type sniffing attacks. This is the security headers gap, and it is one of the most common security failures in AI-generated apps. AI assistants build apps that function correctly but lack the security headers that protect against common web attacks. Here are the 7 security headers every AI-generated app needs, and the production checklist to add them.

The direct answer is that security headers are HTTP response headers that tell the browser to enforce security policies, like only executing scripts from trusted sources (CSP), only connecting via HTTPS (HSTS), and not allowing the page to be embedded in an iframe (X-Frame-Options). AI assistants rarely add these headers, because they are not needed for the app to function and are not part of the default boilerplate. The result is apps that are vulnerable to common web attacks, which can lead to data theft, account takeover, and malware distribution. For more on security, see our article on the JWT authentication trap.

Header 1: Content-Security-Policy (CSP)

The most important security header is Content-Security-Policy (CSP). CSP tells the browser which sources of content (scripts, styles, images, fonts, etc.) are allowed to load, which prevents XSS attacks by blocking the execution of unauthorized scripts. Without CSP, an attacker who injects a script tag into your page (via an XSS vulnerability) can execute arbitrary JavaScript, steal cookies, and impersonate the user. With CSP, the browser blocks the unauthorized script, because it is not in the allowed sources. The fix is to add a CSP header that specifies your allowed sources. For Next.js, use the headers() function in next.config.js. For Express, use the helmet middleware. For more on XSS prevention, see our article on the file upload trap.

Header 2: Strict-Transport-Security (HSTS)

The second header is Strict-Transport-Security (HSTS). HSTS tells the browser to always use HTTPS, which prevents downgrade attacks (where an attacker forces the browser to use HTTP, which is unencrypted). Without HSTS, a man-in-the-middle attacker can intercept the HTTP request and steal cookies or inject malicious content. With HSTS, the browser refuses to connect via HTTP, which prevents the downgrade. The fix is to add an HSTS header with a long max-age (e.g., 31536000 seconds, which is 1 year). For more on HTTPS, see our article on how we handle SSL at scale.

Header 3: X-Frame-Options

The third header is X-Frame-Options. X-Frame-Options tells the browser whether your page can be embedded in an iframe, which prevents clickjacking attacks (where an attacker embeds your page in an invisible iframe and tricks the user into clicking on it). Without X-Frame-Options, an attacker can embed your page in an iframe and trick the user into performing actions they did not intend (e.g., deleting their account). With X-Frame-Options set to DENY or SAMEORIGIN, the browser refuses to embed the page in an iframe, which prevents clickjacking. The fix is to add an X-Frame-Options header set to SAMEORIGIN (which allows embedding only from your own domain). For more on clickjacking, see our article on the cookie consent trap.

Header 4: X-Content-Type-Options

The fourth header is X-Content-Type-Options. X-Content-Type-Options tells the browser not to sniff the MIME type of responses, which prevents MIME-type confusion attacks (where the browser interprets a non-executable file as an executable file). Without X-Content-Type-Options, the browser might interpret a text file as a script, which can lead to XSS. With X-Content-Type-Options set to nosniff, the browser respects the declared MIME type, which prevents the confusion. The fix is to add an X-Content-Type-Options header set to nosniff.

Header 5: Referrer-Policy

The fifth header is Referrer-Policy. Referrer-Policy tells the browser how much referrer information to include when navigating to other pages, which prevents leaking sensitive information (e.g., session IDs in the URL) to third-party sites. Without Referrer-Policy, the browser includes the full URL as the referrer, which can leak sensitive information. With Referrer-Policy set to strict-origin-when-cross-origin, the browser includes only the origin (not the full URL) for cross-origin requests, which prevents the leakage. The fix is to add a Referrer-Policy header set to strict-origin-when-cross-origin.

Header 6: Permissions-Policy

The sixth header is Permissions-Policy. Permissions-Policy tells the browser which browser features (e.g., camera, microphone, geolocation, payment) the page is allowed to use, which prevents unauthorized access to sensitive features. Without Permissions-Policy, any page can request access to the camera or microphone, which can be used for surveillance. With Permissions-Policy, you can explicitly allow or deny features, which prevents unauthorized access. The fix is to add a Permissions-Policy header that denies all features by default and allows only the ones your app needs.

Header 7: Cross-Origin-Opener-Policy (COOP)

The seventh header is Cross-Origin-Opener-Policy (COOP). COOP isolates your page from other pages, which prevents cross-origin attacks (e.g., Spectre, which can read memory from other pages). Without COOP, an attacker can open your page in a popup and use side-channel attacks to read its memory. With COOP set to same-origin, the browser isolates your page from other pages, which prevents the attacks. The fix is to add a COOP header set to same-origin.

Step-by-Step: Adding Security Headers in Next.js

Here is how to add all 7 security headers in a Next.js app.

Step 1: Configure headers in next.config.js

// next.config.js
const securityHeaders = [
  {
    key: 'Content-Security-Policy',
    value: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https:; frame-ancestors 'self';",
  },
  {
    key: 'Strict-Transport-Security',
    value: 'max-age=31536000; includeSubDomains; preload',
  },
  {
    key: 'X-Frame-Options',
    value: 'SAMEORIGIN',
  },
  {
    key: 'X-Content-Type-Options',
    value: 'nosniff',
  },
  {
    key: 'Referrer-Policy',
    value: 'strict-origin-when-cross-origin',
  },
  {
    key: 'Permissions-Policy',
    value: 'camera=(), microphone=(), geolocation=(), payment=()',
  },
  {
    key: 'Cross-Origin-Opener-Policy',
    value: 'same-origin',
  },
];

module.exports = {
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: securityHeaders,
      },
    ];
  },
};

Step 2: Test with Mozilla Observatory

Run your app through Mozilla Observatory to verify your security headers are correctly configured. Target a score of A or higher.

Step 3: Test with CSP Evaluator

Use CSP Evaluator to verify your Content-Security-Policy is not too permissive and does not have bypasses.

Step 4: Verify with deployxa doctor

Run deployxa doctor to verify your app's health. The 14-point readiness engine checks SSL, DNS, environment variables, health endpoints, and container status. For more on the readiness engine, see our article on the 14-point readiness engine.

Common Pitfalls and Troubleshooting

The first pitfall is an overly permissive CSP. A CSP with 'unsafe-inline' and 'unsafe-eval' allows inline scripts and eval, which defeats the purpose of CSP. The fix is to use nonces or hashes for inline scripts and to avoid eval. The second pitfall is a CSP that breaks the app. A CSP that is too strict can block legitimate scripts and styles, which breaks the app. The fix is to start with a permissive CSP (using Content-Security-Policy-Report-Only header) and to gradually tighten it based on the reports. The third pitfall is not including all sources. A CSP that does not include all the sources your app uses (e.g., a CDN, a font provider, an analytics service) will block those resources. The fix is to audit your app's network requests and to include all sources in the CSP. The fourth pitfall is not testing in production. Security headers can behave differently in production (e.g., due to CDN caching), which means you need to test in production, not just locally. The fix is to use a tool like SecurityHeaders.com to verify your headers in production. The fifth pitfall is not updating headers when adding new features. When you add a new feature (e.g., a new analytics service), you need to update the CSP to allow the new source. The fix is to review your CSP whenever you add a new feature.

Conclusion: Security Headers Are Not Optional

The security headers gap is not a sign that your AI assistant did a bad job. It is a sign that security headers are not part of the default boilerplate, and AI assistants do not add them. By applying the 7 security headers above (CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, COOP), you can protect your app from common web attacks and achieve a security score of A+ on Mozilla Observatory. Stop shipping insecure apps and start adding security headers.

Ready to ship a secure app? Drag your project to Deployxa Drop for an instant live preview, or install the CLI with npm i -g @deployxa/cli and deploy from your terminal. For more on AI coding patterns, see our articles on the JWT authentication trap and the rate limiting gap. Learn about the i18n gap and the logging gap in our companion articles. Explore our free developer tools to speed up your workflow.

Ready to deploy with Deployxa?

Deploy your apps globally with automatic SSL and AI diagnostics.

Start Free Now