Skip to main content

Overview

Security rules protect your website and users from common attacks, data breaches, and vulnerabilities. Proper security also builds trust and is a ranking factor for search engines.
Security issues should be treated as high priority. A single vulnerability can compromise your entire site and user data.

HTTPS Enforcement

Rule: security/https

What it checks:
  • Site served over HTTPS (not HTTP)
  • Valid SSL/TLS certificate
  • No mixed content (HTTP resources on HTTPS pages)
  • HTTPS redirect from HTTP
Why it matters: HTTPS encrypts data between users and your server, preventing eavesdropping and man-in-the-middle attacks. Google requires HTTPS for ranking.
Steps:
  1. Get an SSL certificate:
    • Free: Let’s Encrypt
    • Paid: DigiCert, Sectigo, GlobalSign
    • Automatic: Cloudflare, Netlify, Vercel (free)
  2. Install certificate on server:
# Nginx configuration
server {
  listen 443 ssl http2;
  server_name example.com;
  
  ssl_certificate /path/to/fullchain.pem;
  ssl_certificate_key /path/to/privkey.pem;
  
  # Modern TLS configuration
  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ciphers HIGH:!aNULL:!MD5;
  ssl_prefer_server_ciphers on;
}

# Redirect HTTP to HTTPS
server {
  listen 80;
  server_name example.com;
  return 301 https://$server_name$request_uri;
}
  1. Fix mixed content:
<!-- ❌ Bad: HTTP resource on HTTPS page -->
<img src="http://example.com/image.jpg">
<script src="http://cdn.example.com/script.js"></script>

<!-- ✅ Good: HTTPS or protocol-relative URLs -->
<img src="https://example.com/image.jpg">
<script src="https://cdn.example.com/script.js"></script>

Security Headers

Rule: security/headers

What it checks:
  • Content-Security-Policy (CSP)
  • Strict-Transport-Security (HSTS)
  • X-Frame-Options
  • X-Content-Type-Options
  • Referrer-Policy
  • Permissions-Policy
Why it matters: Security headers provide defense-in-depth against XSS, clickjacking, and other attacks.

Content-Security-Policy (CSP)

What it prevents:
  • Cross-Site Scripting (XSS) attacks
  • Data injection attacks
  • Unauthorized script execution
Missing CSP = Critical vulnerabilityBasic CSP:
# Nginx
add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://trusted-cdn.com; style-src 'self' 'unsafe-inline'; img-src 'self' https: data:; font-src 'self'; connect-src 'self' https://api.example.com;" always;
<!-- HTML meta tag -->
<meta http-equiv="Content-Security-Policy" 
      content="default-src 'self'; script-src 'self' https://trusted-cdn.com; style-src 'self' 'unsafe-inline';">
CSP Directives:
DirectivePurposeExample
default-srcFallback for all resources'self'
script-srcJavaScript sources'self' https://cdn.com
style-srcCSS sources'self' 'unsafe-inline'
img-srcImage sources'self' https: data:
font-srcFont sources'self' https://fonts.gstatic.com
connect-srcAJAX/fetch/WebSocket'self' https://api.example.com
frame-ancestorsWho can embed page'none' or 'self'
Testing CSP:Start with report-only mode:
add_header Content-Security-Policy-Report-Only "default-src 'self'; report-uri https://example.com/csp-report;";
Monitor reports, fix violations, then enforce.

Strict-Transport-Security (HSTS)

What it prevents:
  • Downgrade attacks (forcing HTTP)
  • SSL stripping
  • Cookie hijacking
Missing HSTS = Downgrade attack riskConfiguration:
# Nginx
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# Apache
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Parameters:
  • max-age=31536000: 1 year (in seconds)
  • includeSubDomains: Apply to all subdomains
  • preload: Submit to HSTS preload list
HSTS Preload List:Submit your domain to hstspreload.org to be included in browsers’ built-in HSTS lists.
HSTS preload is difficult to undo. Ensure all subdomains support HTTPS before submitting.

X-Frame-Options

What it prevents:
  • Clickjacking attacks
  • UI redressing
  • Iframe embedding attacks
Missing X-Frame-Options = Clickjacking riskConfiguration:
# Nginx - Deny all framing
add_header X-Frame-Options "DENY" always;

# Or allow same-origin framing only
add_header X-Frame-Options "SAMEORIGIN" always;
Options:
  • DENY: Cannot be framed by anyone
  • SAMEORIGIN: Can only be framed by same domain
  • ALLOW-FROM uri: Deprecated, use CSP frame-ancestors instead
Modern alternative (CSP):
# Use CSP frame-ancestors instead
add_header Content-Security-Policy "frame-ancestors 'none';" always;
# Or
add_header Content-Security-Policy "frame-ancestors 'self';" always;

X-Content-Type-Options

What it prevents:
  • MIME type sniffing attacks
  • Script execution from non-script files
Configuration:
# Nginx
add_header X-Content-Type-Options "nosniff" always;
This forces browsers to respect the Content-Type header and prevents executing scripts from files with incorrect MIME types.

Referrer-Policy

What it controls:
  • How much referrer information is sent with requests
  • Privacy and security of outbound links
Configuration:
# Nginx - Recommended policy
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
Options:
  • no-referrer: Never send referrer
  • same-origin: Send referrer to same origin only
  • strict-origin: Send origin only on HTTPS → HTTPS
  • strict-origin-when-cross-origin: Full URL for same-origin, origin only for cross-origin (recommended)

Complete Security Headers Example

# Nginx - Complete security headers
server {
  listen 443 ssl http2;
  server_name example.com;
  
  # SSL configuration
  ssl_certificate /path/to/fullchain.pem;
  ssl_certificate_key /path/to/privkey.pem;
  ssl_protocols TLSv1.2 TLSv1.3;
  
  # Security headers
  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
  add_header X-Frame-Options "DENY" always;
  add_header X-Content-Type-Options "nosniff" always;
  add_header Referrer-Policy "strict-origin-when-cross-origin" always;
  add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
  add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://trusted-cdn.com; style-src 'self' 'unsafe-inline'; img-src 'self' https: data:; font-src 'self'; connect-src 'self' https://api.example.com; frame-ancestors 'none';" always;
  
  # ... rest of configuration
}

Rule: security/cookies

What it checks:
  • Secure flag on cookies (HTTPS only)
  • HttpOnly flag (prevents JavaScript access)
  • SameSite attribute (CSRF protection)

Sensitive Data Exposure

Rule: security/secrets

What it checks:
  • No API keys in HTML/JavaScript
  • No credentials in source code
  • No leaked secrets in error messages
Common leaks:
// ❌ Bad: API key exposed in frontend
const API_KEY = 'sk_live_abc123xyz';
fetch(`https://api.stripe.com/v1/charges?api_key=${API_KEY}`);

// ✅ Good: API key on backend only
// Backend (Node.js)
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

// Frontend
fetch('/api/create-charge', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ amount: 1000 })
});
Use environment variables:
# .env (never commit to git)
DATABASE_URL=postgresql://user:pass@localhost/db
API_SECRET_KEY=your-secret-key
STRIPE_SECRET_KEY=sk_live_abc123xyz
// Load from environment
require('dotenv').config();
const apiKey = process.env.API_SECRET_KEY;
Add to .gitignore:
# .gitignore
.env
.env.local
.env.*.local
secrets/

Testing Security

Security Headers

Test your site’s security headers and get a grade

Mozilla Observatory

Comprehensive security scan including TLS, headers, and more

SSL Labs

Deep analysis of SSL/TLS configuration

CSP Evaluator

Test and validate your Content Security Policy

Security Checklist

1

Enable HTTPS

  • Get SSL certificate (Let’s Encrypt is free)
  • Redirect HTTP → HTTPS
  • Fix mixed content warnings
2

Add Security Headers

  • Strict-Transport-Security (HSTS)
  • Content-Security-Policy (CSP)
  • X-Frame-Options
  • X-Content-Type-Options
  • Referrer-Policy
3

Secure Cookies

  • Set Secure flag (HTTPS only)
  • Set HttpOnly flag (prevent XSS)
  • Set SameSite attribute (prevent CSRF)
4

Protect Secrets

  • Never commit secrets to git
  • Use environment variables
  • Keep API keys on backend only
  • Rotate credentials regularly
5

Test & Monitor

  • Run security audits regularly
  • Monitor for vulnerabilities
  • Keep dependencies updated
  • Set up security alerts

Performance Rules

Page speed, compression, and optimization

Accessibility Rules

WCAG compliance and inclusive design

Running Audits

Learn how to run security audits

Interpreting Results

Understand security scores and fix vulnerabilities

Build docs developers (and LLMs) love