BLOG
2026-04-11
18 min read

How to Secure a Website in 2026 — The Complete Guide

Complete guide to securing a website in 2026. TLS, headers, cookies, CORS, CSP, CVEs, WAF, pentesting. Code snippets for Next.js, Express, nginx.

web-securityguidecomplete-guidehardening

What "secure" actually means in 2026

Securing a website is not a single action — it is a layered defence where each layer catches what the previous missed. A modern, well-secured website has six layers: transport security, HTTP headers, cookie hygiene, CORS policy, dependency management, and active monitoring.

This guide walks through all six, in the order you should implement them, with code snippets for the stacks most developers actually use in 2026: Next.js 15, Express / Node, nginx, Cloudflare Workers, and plain static sites on Vercel / Netlify.

By the end you will have a concrete checklist, know exactly what to copy-paste, and have a plan to verify the whole thing with a free ScanMyVibe scan.

Layer 1 — Transport security (TLS)

Every modern website must be served over HTTPS. This is not negotiable. Browsers now actively warn or block mixed content, form submissions over HTTP, and insecure cookies. Let's Encrypt and Cloudflare make TLS free — there is no excuse.

The right TLS configuration in 2026:

->TLS 1.2 minimum, TLS 1.3 preferred. Disable TLS 1.0 and 1.1 at the load balancer.
->Strong cipher suites. Prefer AEAD ciphers like AES-GCM and ChaCha20-Poly1305.
->Certificate from a public CA. Let's Encrypt for free, paid CA for EV if you need it.
->Automated renewal. Use certbot, acme.sh, or your platform's built-in renewer.
->HSTS with preload. Submit to hstspreload.org once your subdomains are all HTTPS.

Verify with Qualys SSL Labs for deep grade, then with ScanMyVibe for the full picture.

Layer 2 — HTTP security headers

Headers are the most powerful and most underused security layer. Set these on every response:

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=(), interest-cohort=()
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-origin

In Next.js 15, set these in next.config.js:

async headers() {
  return [{
    source: '/(.*)',
    headers: [
      { key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubDomains; preload' },
      { key: 'X-Frame-Options', value: 'DENY' },
      { key: 'X-Content-Type-Options', value: 'nosniff' },
      { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
      { key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
    ],
  }]
}

In Express, use helmet:

import helmet from 'helmet'
app.use(helmet())

In nginx:

add_header Strict-Transport-Security "max-age=63072000; 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;

Layer 3 — Content-Security-Policy

CSP deserves its own section because it is the single most powerful header. A strict CSP stops most XSS at the browser level, even if your code is vulnerable.

Start with a permissive Report-Only policy, collect violations for a week, then tighten. The ideal 2026 CSP uses nonces with strict-dynamic:

Content-Security-Policy: default-src 'self'; script-src 'nonce-{RANDOM}' 'strict-dynamic'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; object-src 'none'; upgrade-insecure-requests

Generate nonces per request in Next.js middleware:

import { NextResponse } from 'next/server'
export function middleware(request) {
  const nonce = Buffer.from(crypto.randomUUID()).toString('base64')
  const csp = `script-src 'nonce-${nonce}' 'strict-dynamic';`
  const response = NextResponse.next()
  response.headers.set('Content-Security-Policy', csp)
  response.headers.set('x-nonce', nonce)
  return response
}

Don't want to write it by hand? Use our CSP header generator.

Layer 4 — Cookies

Session cookies are the #1 target of XSS, CSRF, and session hijacking. Get the flags right and most attacks fail:

->Secure — only sent over HTTPS.
->HttpOnly — inaccessible to JavaScript. Kills XSS-based session theft.
->SameSite=Lax (or Strict) — stops CSRF and cross-origin leaking.
->__Host- prefix — binds the cookie to the origin, prevents subdomain attacks.

In Express:

res.cookie('session', token, {
  httpOnly: true,
  secure: true,
  sameSite: 'lax',
  maxAge: 24 * 60 * 60 * 1000,
})

In Next.js with next-auth, set these in authOptions.cookies or rely on the secure defaults (next-auth v5 gets them right).

Layer 5 — CORS

CORS is where most production sites get it wrong. The rules:

1. Never use Access-Control-Allow-Origin: * with Access-Control-Allow-Credentials: true. This is explicitly forbidden by browsers and is a sign of a misconfigured server.

2. Echo a specific origin from an allowlist, not the Origin header blindly. Blind echo means any site can read your API.

3. Set Vary: Origin so CDNs cache the right variant.

4. Restrict Access-Control-Allow-Methods to what you actually use.

In Express:

const allowlist = ['https://yourapp.com', 'https://www.yourapp.com']
app.use(cors({
  origin: (origin, cb) => {
    if (!origin || allowlist.includes(origin)) cb(null, true)
    else cb(new Error('Not allowed'))
  },
  credentials: true,
}))

Layer 6 — Dependency and CVE management

Outdated libraries are the single most common source of real-world compromise. Every npm package, every WordPress plugin, every Python wheel is a supply chain risk. The 2026 baseline:

->Automated PRs for security updates. Use Dependabot or Renovate.
->Snyk or npm audit in CI. Fail builds that introduce known critical CVEs.
->Pin your versions. Use exact versions in production deployments.
->Remove unused dependencies. Every package is an attack surface.

ScanMyVibe fingerprints outdated client-side libraries (jQuery, Bootstrap, WordPress) and flags them automatically.

Authentication and authorization

If your site has user accounts, the auth layer is where most breaches happen. The 2026 standard:

->Use a library, not your own code. next-auth v5, Clerk, Auth0, Supabase Auth.
->Passwords: hash with Argon2id or bcrypt. Never store reversible.
->MFA: TOTP with backup codes. Passkeys if your library supports them.
->Rate limit login endpoints. 5 attempts per minute per IP.
->Session rotation on privilege change.

Never roll your own JWT verification. Use the library primitives.

Active monitoring and alerting

Security drifts. A new CDN rule, a framework upgrade, a misconfigured cache — any of these can regress your posture silently. The only defence is continuous monitoring.

->Scheduled scans. ScanMyVibe Pro runs a scan on every deploy and alerts on regression.
->Uptime and status. Use a status page so you know when something breaks.
->Error tracking. Sentry or similar catches exceptions that might reveal information.
->Log aggregation. Ship logs to Datadog, Loki, or Better Stack. Alert on suspicious patterns.

Pentesting and human review

Automated scanners catch configuration issues. Business-logic flaws — broken auth flows, IDOR, price manipulation — require humans. Budget for one pentest per year from a reputable vendor. Costs $5k–$25k for a typical SaaS engagement and usually finds issues no scanner could.

The complete checklist

1. HTTPS everywhere with Let's Encrypt or Cloudflare.

2. TLS 1.2 minimum, 1.3 preferred.

3. HSTS with preload submitted.

4. All security headers set.

5. Strict CSP with nonces.

6. Cookies with Secure, HttpOnly, SameSite.

7. CORS from an explicit allowlist.

8. Dependabot/Renovate configured.

9. Snyk or npm audit in CI.

10. Auth library, not custom code.

11. MFA enabled.

12. Scheduled security scans.

13. Error tracking.

14. Annual pentest.

If you check all 14, you are ahead of 99% of production sites. Verify the configuration side of this checklist with a free ScanMyVibe scan — it takes 30 seconds and tells you exactly which items are still outstanding.

For tool comparisons, see our best website security scanners of 2026 guide.