Skip to content

Secure Headers: HTTP Security Headers for Hardening Your Backend

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about Secure Headers: HTTP Security Headers for Hardening Your Backend. We cover key concepts, practical examples, and best practices to help you master this topic.

HTTP security headers instruct browsers how to behave when interacting with your application. They enable critical security features: forcing HTTPS, preventing clickjacking, blocking MIME type sniffing, controlling referrer information, and restricting browser features.

flowchart LR
    Browser -->|Request| Server
    Server -->|Response + Security Headers| Browser
    Browser -->|Enforce Policies| User
    
    subgraph Headers
        HSTS[Strict-Transport-Security]
        XFO[X-Frame-Options]
        XCTO[X-Content-Type-Options]
        RP[Referrer-Policy]
        PP[Permissions-Policy]
        CSP[Content-Security-Policy]
    end
    
    HSTS -->|Force HTTPS| Browser
    XFO -->|Block iframe embedding| Browser
    XCTO -->|Prevent MIME sniffing| Browser
    RP -->|Control referrer| Browser
    PP -->|Restrict browser APIs| Browser
    CSP -->|Allowlisted sources| Browser

What You'll Learn

  • Every critical HTTP security header and its purpose
  • Configuring Helmet for Express-based applications
  • HSTS preloading and upgrade-insecure-requests
  • Permissions-Policy for granular API control

Why It Matters

Security headers are a high-impact, low-effort security improvement. Setting a few headers prevents entire categories of attacks: HSTS prevents SSL stripping, X-Frame-Options prevents clickjacking, and Permissions-Policy limits damage from XSS.

Real-World Use

A government services portal achieved an A+ security rating by implementing: HSTS with preload (max-age=31536000), X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, and Permissions-Policy: geolocation=().

Security Headers Implementation

Using Helmet for Express

const helmet = require('helmet');

app.use(helmet());

// Custom configuration
app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", "https://cdn.example.com"],
      styleSrc: ["'self'", "'unsafe-inline'"],
      imgSrc: ["'self'", "data:", "https://images.example.com"],
      connectSrc: ["'self'"],
      fontSrc: ["'self'"],
      objectSrc: ["'none'"],
      frameAncestors: ["'none'"],
      upgradeInsecureRequests: []
    }
  },
  hsts: {
    maxAge: 31536000,
    includeSubDomains: true,
    preload: true
  },
  referrerPolicy: {
    policy: 'strict-origin-when-cross-origin'
  }
}));

Expected output:

Response headers include: Strict-Transport-Security, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Content-Security-Policy, Permissions-Policy.

Manual Security Header Configuration

app.use((req, res, next) => {
  // HSTS: Force HTTPS for 1 year, include subdomains, preload
  res.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');

  // Prevent clickjacking
  res.set('X-Frame-Options', 'DENY');

  // Prevent MIME type sniffing
  res.set('X-Content-Type-Options', 'nosniff');

  // Control referrer information
  res.set('Referrer-Policy', 'strict-origin-when-cross-origin');

  // Restrict browser features
  res.set('Permissions-Policy', 'geolocation=(), microphone=(), camera=(), payment=()');

  // Disable caching for sensitive data
  res.set('Cache-Control', 'no-store, max-age=0');

  next();
});

Expected output:

All responses include these security headers. Browsers enforce the specified policies, blocking unsafe behaviors.

Cross-Origin Isolation Headers

// For enabling SharedArrayBuffer and high-resolution timers
app.use('/api/secure', (req, res, next) => {
  res.set('Cross-Origin-Opener-Policy', 'same-origin');
  res.set('Cross-Origin-Embedder-Policy', 'require-corp');
  res.set('Cross-Origin-Resource-Policy', 'same-origin');
  next();
});

// For embedding in specific origins
app.use('/api/embed', (req, res, next) => {
  res.set('Cross-Origin-Resource-Policy', 'cross-origin');
  res.set('Access-Control-Allow-Origin', 'https://trusted-partner.com');
  next();
});

Expected output:

Cross-Origin-Opener-Policy: same-origin isolates the browsing context group. Cross-Origin-Embedder-Policy: require-corp prevents loading cross-origin resources without explicit permission.

Common Mistakes

  • Setting HSTS with short max-age (e.g., 3600), which provides no meaningful protection.
  • Using X-Frame-Options: SAMEORIGIN when DENY is appropriate — only allow framing if explicitly needed.
  • Forgetting to set X-Content-Type-Options: nosniff, allowing browsers to MIME-sniff and potentially execute uploaded files as scripts.
  • Setting Permissions-Policy permissions too broadly (e.g., geolocation=(*)), allowing all origins to access sensitive APIs.
  • Not including upgrade-insecure-requests in CSP, allowing mixed content on HTTPS pages.

Practice Questions

  1. What does Strict-Transport-Security do?
  2. How does X-Frame-Options prevent clickjacking?
  3. What is MIME type sniffing and why should you disable it?
  4. How does Referrer-Policy protect user privacy?
  5. What is Permissions-Policy and when would you use it?

Challenge

Set up an Express server with comprehensive security headers. Use Helmet with custom configuration. Add middleware that sets HSTS with preload for production but disables it for localhost. Test all headers with curl and verify with securityheaders.com.

FAQ

What is HSTS?

HTTP Strict Transport Security (HSTS) tells browsers to always connect via HTTPS, never HTTP. It prevents SSL stripping attacks and protocol downgrade attacks.

Should I enable HSTS preload?

Yes, if your site will never serve HTTP. HSTS preload lists your domain in browser source code for hardcoded HTTPS enforcement. Submit at hstspreload.org.

What is the difference between X-Frame-Options and CSP frame-ancestors?

CSP frame-ancestors is the modern replacement for X-Frame-Options. It supports multiple origins and is more flexible. X-Frame-Options is still supported for older browsers.

What is Permissions-Policy?

Permissions-Policy (formerly Feature-Policy) controls which browser APIs and features your site can use. You can disable geolocation, camera, microphone, and other sensitive APIs.

How do I check if my security headers are correct?

Use online tools like securityheaders.com, observatory.mozilla.org, or the Security Headers Chrome extension. Also test with curl -I https://your-site.com.

Mini Project

Build a security headers configuration module that produces different header sets for development, staging, and production. Production should include HSTS preload, strict CSP, and all protections. Staging includes relaxed CSP for debugging. Development is permissive. Test each environment.

What's Next

Continue to Rate Limiting to learn how to protect your APIs from abuse and DDoS attacks.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro