skills/igbuend/grimbard/missing-security-headers-anti-pattern

missing-security-headers-anti-pattern

SKILL.md

Missing Security Headers Anti-Pattern

Severity: Medium

Summary

HTTP security headers defend against XSS, clickjacking, and man-in-the-middle attacks at the browser level. Applications failing to send these headers rely on insecure browser defaults, missing a powerful declarative security layer.

The Anti-Pattern

The anti-pattern is omitting security headers from HTTP responses. Browsers default to permissive policies; servers must instruct stricter controls.

BAD Code Example

# VULNERABLE: A Flask application that does not set any security headers.
from flask import Flask, make_response

app = Flask(__name__)

@app.route("/")
def index():
    # Response sent with insecure default headers.
    # - No CSP: scripts from any origin can execute
    # - No X-Frame-Options: any site can iframe for clickjacking
    # - No HSTS: connection can downgrade to HTTP
    response = make_response("<h1>Welcome to the site!</h1>")
    return response

# The HTTP response would look something like this:
#
# HTTP/1.1 200 OK
# Content-Type: text/html; charset=utf-8
# Content-Length: 29
#
# <h1>Welcome to the site!</h1>

GOOD Code Example

# SECURE: The application sets a strong baseline of security headers for all responses.
from flask import Flask, make_response

app = Flask(__name__)

@app.after_request
def add_security_headers(response):
    # CSP: Prevents XSS. Allows resources only from same origin ('self').
    response.headers['Content-Security-Policy'] = "default-src 'self'"

    # X-Frame-Options: Prevents iframe embedding, mitigates clickjacking.
    response.headers['X-Frame-Options'] = 'DENY'

    # HSTS: Instructs browser to use only HTTPS.
    response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'

    # X-Content-Type-Options: Prevents MIME-sniffing.
    response.headers['X-Content-Type-Options'] = 'nosniff'

    # Referrer-Policy: Controls referrer information sent with requests.
    response.headers['Referrer-Policy'] = 'strict-origin-when-cross-origin'
    return response

@app.route("/")
def index_secure():
    return make_response("<h1>Welcome to the secure site!</h1>")

# The HTTP response now includes critical security controls:
#
# HTTP/1.1 200 OK
# Content-Type: text/html; charset=utf-8
# Content-Length: 36
# Content-Security-Policy: default-src 'self'
# X-Frame-Options: DENY
# Strict-Transport-Security: max-age=31536000; includeSubDomains
# X-Content-Type-Options: nosniff
# Referrer-Policy: strict-origin-when-cross-origin
#
# <h1>Welcome to the secure site!</h1>

Detection

  • Use browser developer tools: Open the "Network" tab, inspect a request to your site, and look at the "Response Headers" section. Check for the presence of the headers listed below.
  • Use an online scanner: Tools like SecurityHeaders.com can quickly scan a public website and report on its missing headers.
  • Review framework configurations: Check your web server or framework's configuration files to see if security headers are being set globally. Many frameworks have dedicated middleware (like Helmet for Express.js) to handle this.

Prevention

Implement a middleware or a global response filter in your application that adds the following headers to all outgoing responses.

  • Content-Security-Policy (CSP): Most important XSS defense. Defines strict allowlist for content sources (scripts, styles, images). Start with default-src 'self'.
  • Strict-Transport-Security (HSTS): Browser uses only HTTPS. Prevents downgrade attacks.
  • X-Frame-Options: Primary clickjacking defense. Prevents iframe embedding. Set to DENY or SAMEORIGIN.
  • X-Content-Type-Options: Set to nosniff. Prevents MIME-sniffing abuse for script execution.
  • Referrer-Policy: Controls referrer information sent on navigation. Default: strict-origin-when-cross-origin.
  • Permissions-Policy: Selectively enable/disable browser features (microphone, camera, geolocation).

Related Security Patterns & Anti-Patterns

References

Weekly Installs
4
GitHub Stars
4
First Seen
Jan 20, 2026
Installed on
claude-code4
codex4
cursor4
opencode4
trae-cn3
antigravity3