VOOZH about

URL: https://dev.to/joseph_anady_214bacedf939/web-security-headers-hsts-csp-1bn5

⇱ Web security headers + HSTS + CSP - DEV Community


Originally published at thatdevpro.com. Part of ThatDevPro's open SEO + AI framework library. ThatDevPro is an SDVOSB-certified veteran-owned web + AI engineering studio. Open-source AI citation toolkit: github.com/Janady13/aio-surfaces.


HTTPS, Headers, Authentication, WAF, Hardening, Incident Response, and the Security Posture Required to Maintain Search Trust

A comprehensive reference for web security across the sites Joseph manages. Security is a baseline expectation in 2026 — Google explicitly considers HTTPS a ranking factor (modest), security issues trigger manual actions, browser warnings destroy conversion rates, and breach incidents create permanent brand damage.


1. Document Purpose

Security is often treated as separate from SEO/marketing concerns, but the disciplines significantly overlap. Hacked sites lose rankings, get flagged in browsers as dangerous, drive away users, generate manual actions in GSC, and require months of recovery work. Sites with poor security signals lose trust both with users and with search engines.

For Joseph's specific situation managing 130+ production client sites on self-managed Linux infrastructure, security discipline is foundational. A single compromised client site affects the broader hosting environment. WordPress sites particularly attract attack attempts continuously.

This framework specifies security implementation across the full stack — server, application, content, and operational dimensions.

1.1 Required Tools

  • SSL Labsssllabs.com/ssltest/ — SSL/TLS configuration testing
  • Mozilla Observatoryobservatory.mozilla.org — security headers analysis
  • Security Headerssecurityheaders.com — header analysis
  • WPScan — WordPress vulnerability scanner
  • OWASP ZAP — application security scanner
  • Wordfence / Sucuri / Patchstack — WordPress security platforms
  • Cloudflare — WAF and DDoS protection
  • Let's Encrypt / acme.sh — free SSL certificates

2. HTTPS Implementation

2.1 SSL Certificate Management

ssl_certificate_management:

 certificate_options:

 lets_encrypt:
 cost: "Free"
 validity: "90days(auto-renew)"
 best_for: "Mostsites;commoditySSL"
 automation: "Certbot,acme.sh"

 paid_dv_certificates:
 cost: "$10-100/year"
 validity: "1-2years"
 best_for: "Sitespreferringlongervalidity"
 benefit: "Sometimesfasterissuance"

 extended_validation:
 cost: "$100-500+/year"
 validity: "1-2years"
 best_for: "Financial,e-commercewithhightrustrequirements"
 note: "Browseraddressbartreatmentreduced;lessdifferentiationthanyearspast"

 multi_domain_strategies:

 san_certificates:
 description: "Multipledomainsinsinglecertificate"
 use_case: "Multiplerelateddomains"

 wildcard_certificates:
 description: "Covers*.example.comsubdomains"
 use_case: "Manysubdomains"
 note: "Doesn'tcoverapex;needseparateorSANwithapex"

 multi_san:
 description: "Multipleunrelateddomainsinonecertificate"
 use_case: "Convenience;fewercertificatestomanage"

2.2 Let's Encrypt Implementation

For Joseph's Debian/Nginx setup managing 130+ sites:

# Install certbot
apt install certbot python3-certbot-nginx

# Get certificate for single site
certbot --nginx -d example.com -d www.example.com

# Auto-renewal (typically configured by certbot install)
systemctl status certbot.timer

# Manual renewal test
certbot renew --dry-run

For mass renewal management:

# Renew all certificates
certbot renew --quiet

# Should be in cron or systemd timer
# Default: twice daily check, renews when within 30 days of expiry

2.3 Nginx HTTPS Configuration

Strong default Nginx HTTPS configuration:

server {
 listen 443 ssl http2;
 listen [::]:443 ssl http2;
 server_name example.com www.example.com;

 # SSL Certificate
 ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

 # Modern SSL Configuration
 ssl_protocols TLSv1.2 TLSv1.3;
 ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
 ssl_prefer_server_ciphers off;
 ssl_session_cache shared:SSL:10m;
 ssl_session_timeout 10m;

 # OCSP Stapling
 ssl_stapling on;
 ssl_stapling_verify on;
 ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
 resolver 1.1.1.1 8.8.8.8 valid=300s;

 # Security Headers (see Section 3)
 add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

 # ... rest of configuration
}

# Redirect HTTP to HTTPS
server {
 listen 80;
 listen [::]:80;
 server_name example.com www.example.com;
 return 301 https://$host$request_uri;
}

2.4 SSL Testing

After implementation, verify with SSL Labs (ssllabs.com/ssltest/):

  • Target: A or A+ grade
  • Issues to fix: protocol weaknesses, weak ciphers, missing OCSP, certificate chain issues

3. Security Headers

Security headers add layers of browser-enforced protection.

3.1 Complete Security Headers

# Strict-Transport-Security (HSTS)
# Forces HTTPS, prevents downgrade attacks
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

# X-Frame-Options
# Prevents clickjacking via iframe embedding
add_header X-Frame-Options "SAMEORIGIN" always;

# X-Content-Type-Options
# Prevents MIME sniffing
add_header X-Content-Type-Options "nosniff" always;

# Referrer-Policy
# Controls referrer information sent
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

# Permissions-Policy (formerly Feature-Policy)
# Controls browser features
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

# Content-Security-Policy (most complex; see below)
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 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:; connect-src 'self' https://www.google-analytics.com; frame-ancestors 'self'; base-uri 'self'; form-action 'self';" always;

# Cross-Origin policies
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;

3.2 Content Security Policy (CSP)

CSP is the most complex but most powerful header. It defines what sources of scripts, styles, images, etc. are allowed:

csp_directives:

 default_src:
 purpose: "Fallbackforotherdirectives"
 typical: "'self'"

 script_src:
 purpose: "AllowedJavaScriptsources"
 common_additions:
 - "'self'"
 - "https://www.googletagmanager.com"
 - "https://www.google-analytics.com"
 - "'unsafe-inline'" # Often required; reduces protection
 avoid: "'unsafe-eval'unlessabsolutelyrequired"

 style_src:
 purpose: "AllowedCSSsources"
 common: "'self''unsafe-inline'https://fonts.googleapis.com"

 img_src:
 purpose: "Allowedimagesources"
 common: "'self'data:https:"

 font_src:
 purpose: "Allowedfontsources"
 common: "'self'https://fonts.gstatic.com"

 connect_src:
 purpose: "Allowedfetch/XHRdestinations"
 common: "'self'https://www.google-analytics.com"

 frame_ancestors:
 purpose: "Whocaniframethispage"
 typical: "'self'"
 note: "ReplacesX-Frame-Options"

 base_uri:
 purpose: "Restrict<base>element"
 typical: "'self'"

 form_action:
 purpose: "Whereformscansubmit"
 typical: "'self'"

3.3 CSP Implementation Approach

csp_implementation:

 step_1_audit:
 - Inventory all script sources
 - Inventory all style sources
 - Inventory all image, font, fetch sources

 step_2_report_only:
 header: "Content-Security-Policy-Report-Only"
 purpose: "Testpolicywithoutenforcement"
 duration: "Run1-2weeks;collectviolations"

 step_3_iterate:
 - Review violation reports
 - Adjust policy to allow legitimate sources
 - Block malicious or unnecessary

 step_4_enforce:
 header: "Content-Security-Policy"
 purpose: "Switchfromreport-onlytoenforcement"

 step_5_monitor:
 - Continued violation reporting via report-uri or report-to
 - Adjust as legitimate needs change

4. WordPress-Specific Security

For Joseph's significant WordPress portfolio:

4.1 WordPress Hardening Baseline

wordpress_hardening:

 core_updates:
 requirement: "WordPresscoreauto-updatesenabled"
 cadence: "Weeklyverificationacrossportfolio"
 automation: "Automaticforsecuritypatches;managedformajorversions"

 plugins:
 rule: "Onlyinstallreputablepluginsfromwordpress.orgortrustedsources"
 audit: "Quarterlypluginauditpersite"
 remove: "Inactiveplugins(securitysurface)"
 update: "Auto-updatesenabledforsecurity;managedformajorversions"

 themes:
 rule: "Reputablethemesonly"
 audit: "Inactivethemesremoved"
 custom_themes: "Maintainedandupdated"

 user_accounts:
 admin_username: "Never'admin'(default)"
 default_role: "Subscriberfornewusers"
 role_review: "Quarterlyreviewofadministrators"
 inactive_users: "Removedperiodically"

 password_security:
 requirement: "Strongpasswordsenforced"
 plugin: "ForceStrongPasswordsorsimilar"
 two_factor: "Enabledforadministrators"

 file_permissions:
 files: "644"
 directories: "755"
 wp_config: "600"

 wp_config_hardening:
 keys: "Salts/keysregenerated;neverdefault"
 db_prefix: "Non-default('wp_'isdefault;changetorandom)"
 debug: "Falseinproduction"

 xml_rpc:
 typical: "Disableunlessrequired(mobileapp,Jetpack)"
 method: ".htaccessblockorplugin"

 rest_api:
 public_endpoints: "Restrictwhereappropriate"
 plugin: "DisableWPRESTAPIorsimilarforrestriction"

 login_protection:
 rate_limiting: "LimitLoginAttemptsplugin"
 captcha: "Onloginform"
 two_factor: "Wordfence2FA,GoogleAuthenticator,etc."
 custom_login_url: "WPSHideLoginorsimilar"

4.2 WordPress Security Plugins

wordpress_security_plugin_options:

 wordfence:
 type: "Comprehensivesecuritysuite"
 features: ["Firewall", "Malwarescan", "Loginprotection", "2FA"]
 cost: "Free+Premium"
 recommended_for: "MostWordPresssites"

 sucuri:
 type: "Comprehensivesecuritysuite"
 features: ["Firewall", "Malwarescan", "Cleanupservice"]
 cost: "Freeplugin+paidservices"
 recommended_for: "Sitesneedingmanagedcleanup"

 patchstack:
 type: "Vulnerabilitypatching"
 features: ["Virtualpatching", "Vulnerabilitydatabase"]
 cost: "Paid"
 recommended_for: "Siteswithmanyplugins"

 ithemes_security:
 type: "Comprehensivesecuritysuite"
 features: ["Varioushardening", "2FA", "Logmonitoring"]
 cost: "Free+Pro"
 recommended_for: "AlternativetoWordfence"

For Joseph's hosting situation managing 130+ sites: standardizing on one security solution simplifies management. Wordfence Premium across portfolio with central monitoring is common pattern.

4.3 WordPress Backup

wordpress_backup_strategy:

 frequency:
 files: "Dailyforhigh-changesites;weeklyforstatic-content"
 database: "Dailyminimum"

 retention:
 daily: "Keep7-30days"
 weekly: "Keep4-12weeks"
 monthly: "Keep6-12months"

 storage:
 requirement: "Off-serverlocation"
 options:
 - S3 / Backblaze B2 / Wasabi
 - Other cloud storage
 - Different physical server
 avoid: "Backupsonlyonsameserver(lostincompromise)"

 testing:
 quarterly: "Testrestoreprocedure"
 purpose: "Verifybackupsareactuallyviable"

 plugins:
 options:
 - UpdraftPlus (most popular)
 - BackWPup
 - Duplicator Pro
 - WP Time Capsule
 server_side:
 - rsync to off-server location
 - Scripted backup to S3 or similar

5. Server-Level Security

For Joseph's self-managed Linux infrastructure:

5.1 SSH Hardening

# /etc/ssh/sshd_config

# Disable root login
PermitRootLogin no

# Use SSH keys only, no passwords
PasswordAuthentication no
ChallengeResponseAuthentication no

# Limit users who can SSH
AllowUsers joseph backupuser

# Change default port (security through obscurity, but reduces noise)
Port 22042 # Or any non-standard port

# Limit authentication attempts
MaxAuthTries 3
LoginGraceTime 30

# Modern protocol only
Protocol 2

# Strong key exchange
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256

# Modern ciphers only
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com

After changes:

sshd -t # Test config
systemctl restart sshd

5.2 Firewall (UFW or iptables)

# Basic UFW configuration
ufw default deny incoming
ufw default allow outgoing

# Allow SSH (on custom port if changed)
ufw allow 22042/tcp

# Allow web traffic
ufw allow 80/tcp
ufw allow 443/tcp

# Enable firewall
ufw enable

# Status
ufw status verbose

5.3 Fail2ban

Prevents brute force attacks:

apt install fail2ban

# /etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3

[sshd]
enabled = true
port = 22042

[nginx-http-auth]
enabled = true

[wordpress]
enabled = true
filter = wordpress
logpath = /var/log/nginx/access.log

5.4 Automatic Security Updates

# Debian/Ubuntu unattended-upgrades
apt install unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades

# Configure /etc/apt/apt.conf.d/50unattended-upgrades
# Enable security updates
# Configure email notifications

5.5 Log Monitoring

log_monitoring:

 what_to_monitor:
 - Failed login attempts (auth.log)
 - Web server errors (nginx error log)
 - Suspicious request patterns (nginx access log)
 - Application errors (varies)

 tools:
 - logwatch (daily summary email)
 - GoAccess (real-time web log analysis)
 - Centralized logging (ELK stack, Graylog, etc.) for larger setups

 alerts:
 - Unusual login patterns
 - High error rates
 - Suspicious traffic patterns
 - Disk space warnings

6. Cloudflare WAF

For sites where Joseph manages or recommends:

cloudflare_security_layer:

 free_tier_features:
 - Free SSL/TLS
 - Basic DDoS protection
 - Bot fight mode
 - Browser integrity check

 pro_tier_additions:
 - WAF rules (managed rulesets)
 - Image optimization
 - Mobile redirect

 business_tier_additions:
 - Custom WAF rules
 - Rate limiting
 - Page rules with more options

 setup_steps:
 - Add domain to Cloudflare
 - Update nameservers
 - Verify proxying enabled (orange cloud)
 - Configure SSL mode (Full Strict recommended)
 - Enable security features
 - Test thoroughly

 custom_rules_examples:
 block_xmlrpc: "Block/xmlrpc.phptoall(WordPress)"
 rate_limit_login: "Ratelimit/wp-login.php"
 block_known_bad_ips: "BlockIPsfromthreatintelligence"
 challenge_high_risk_countries: "Wherebusinessdoesn'toperate"

7. Application Security

7.1 Common Vulnerabilities (OWASP Top 10)

owasp_top_10_2021:

 A01_broken_access_control:
 examples: "Pathtraversal,IDOR,missingauthorization"
 prevention: "Server-sideauthorizationchecks;leastprivilege"

 A02_cryptographic_failures:
 examples: "Weakencryption,plaintextpasswords"
 prevention: "Moderncrypto;passwordhashing(bcrypt,argon2)"

 A03_injection:
 examples: "SQLinjection,XSS,commandinjection"
 prevention: "Parameterizedqueries;inputsanitization;outputencoding"

 A04_insecure_design:
 examples: "Missingsecurityindesign"
 prevention: "Threatmodeling;securedesignpatterns"

 A05_security_misconfiguration:
 examples: "Defaultcredentials,verboseerrors,missingheaders"
 prevention: "Securitybaselines;configurationaudits"

 A06_vulnerable_components:
 examples: "Outdatedlibraries,dependencies"
 prevention: "Dependencyscanning;regularupdates"

 A07_authentication_failures:
 examples: "Weakpasswords,sessionmanagementissues"
 prevention: "Strongauth,MFA,sessionsecurity"

 A08_software_data_integrity_failures:
 examples: "Unsignedupdates,deserializationvulns"
 prevention: "Signedupdates;safedeserialization"

 A09_logging_monitoring_failures:
 examples: "Nologging,nomonitoring"
 prevention: "Comprehensivelogging;alerting"

 A10_ssrf:
 examples: "Server-siderequestforgery"
 prevention: "URLvalidation;allowlists"

7.2 Input Validation & Output Encoding

// PHP example — parameterized query (prevents SQL injection)
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);

// JavaScript — output encoding (prevents XSS)
element.textContent = userInput; // Safe
element.innerHTML = userInput; // DANGEROUS

// React — automatic encoding
{userInput} // Safe
dangerouslySetInnerHTML={{__html: userInput}} // DANGEROUS

8. Incident Response

8.1 Incident Response Plan

incident_response_phases:

 preparation:
 - Documented response plan
 - Contact list (hosting, registrar, security firm)
 - Backup access verified
 - Logging in place to support investigation

 detection:
 - Monitoring alerts
 - User reports
 - Security tools detection
 - Search engine warnings

 containment:
 immediate:
 - Take site offline if active attack
 - Change all credentials
 - Block attacker IP if identified
 short_term:
 - Isolate affected systems
 - Preserve evidence
 - Engage security team or service if needed

 eradication:
 - Identify root cause
 - Remove malicious content
 - Patch vulnerability
 - Verify thorough cleanup

 recovery:
 - Restore from clean backup if needed
 - Bring systems back online
 - Verify normal operation
 - Monitor closely for return

 post_incident:
 - Root cause analysis
 - Documentation
 - Process improvements
 - Affected user notification (if applicable)

8.2 Common Incidents

common_incident_types:

 malware_injection:
 detection: "Malwarescan,GSCsecuritywarning"
 response: "Identifyentrypoint;cleanfiles;patchvulnerability"

 defacement:
 detection: "Visualinspection;userreports"
 response: "Restorefrombackup;identifyentrypoint"

 data_breach:
 detection: "Databaseaccesspatterns;userreports"
 response: "Majorincident;legalcounsel;usernotification"

 ddos:
 detection: "Trafficspike;servicedegradation"
 response: "Cloudflareorsimilar;ratelimiting"

 account_compromise:
 detection: "Unusualadminactivity;userreports"
 response: "Lockaccount;forcepasswordreset;auditlogs"

8.3 Manual Action from Hacked Content

If GSC reports manual action for hacked content:

  • Address issue per Section 8.1
  • Verify thorough cleanup
  • Submit reconsideration request via GSC
  • Document remediation work

9. Privacy and Compliance

9.1 Privacy Considerations

privacy_baseline:

 privacy_policy:
 requirement: "Comprehensivepolicyoneverysite"
 contents:
 - Data collected
 - How used
 - Third parties
 - User rights
 - Contact information

 cookie_consent:
 requirement: "EEAtraffic;goodpracticeelsewhere"
 implementation: "CMPperframework-ga4.md"

 user_data_handling:
 minimum_collection: "Onlycollectwhat'sneeded"
 secure_storage: "Encryptatrest"
 secure_transmission: "AlwaysHTTPS"
 retention_limits: "Don'tkeepindefinitely"
 deletion_rights: "Processuserdeletionrequests"

9.2 Regulatory Compliance

relevant_regulations:

 gdpr: "EUandUK;comprehensiveprivacylaw"
 ccpa_cpra: "California;consumerprivacy"
 hipaa: "HealthcaredatainUS"
 pci_dss: "Paymentcarddata"
 ferpa: "Educationalrecords"
 coppa: "Childrenunder13"

For client sites, compliance is the client's legal responsibility but Joseph's implementation should support compliance (HTTPS, consent, secure handling, etc.).


10. Audit Mode

# Criterion Pass/Fail
SEC1 HTTPS enforced sitewide
SEC2 SSL Labs grade A or A+
SEC3 All security headers configured
SEC4 CSP implemented (at least basic)
SEC5 WordPress hardening baseline applied (if WP)
SEC6 Security plugin active (if WP)
SEC7 Backup strategy implemented and tested
SEC8 SSH hardened (key auth, no root)
SEC9 Firewall configured
SEC10 Fail2ban or equivalent active
SEC11 Automatic security updates enabled
SEC12 Cloudflare or equivalent WAF (where appropriate)
SEC13 Log monitoring established
SEC14 Vulnerability scanning periodic
SEC15 Incident response plan documented
SEC16 Privacy policy current

Score: 16. World-class security baseline: 14+/16.


11. Common Mistakes

  1. HTTP still allowed — must redirect or fail
  2. Missing security headers — easy wins skipped
  3. Default WordPress credentialsadmin username, weak password
  4. Outdated plugins/themes — primary WordPress attack vector
  5. No backup off-server — backup destroyed in compromise
  6. No vulnerability scanning — issues unknown until exploited
  7. No 2FA — account compromise risk
  8. Verbose error messages — leak information to attackers
  9. Default ports and configurations — easier to attack
  10. No incident response plan — paralysis when incident occurs

End of Framework Document

Companion documents:

  • framework-https.md — HTTPS implementation specifics (overlap)
  • framework-hosting.md — Hosting environment security
  • framework-spampolicies.md — Manual actions from hacked content
  • framework-wordpress.md — WordPress-specific implementation
  • framework-serverconfig.md — Server configuration

About this framework library

Dev.to republish of a framework from ThatDevPro's SEO + AI engineering library. Canonical source: https://www.thatdevpro.com/insights/framework-security/

ThatDevPro is an SDVOSB-certified veteran-owned web + AI engineering studio. Need this framework implemented? See the Engine Optimization service or hire via contact.