# Server version headers are suppressed

- **Pattern:** `ab-000014` (`security-headers.info-exposure.no-server-version`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-17
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000014
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000014)

## Why it matters

Server `X-Powered-By: Next.js` and `Server: nginx/1.24.0` headers hand attackers a pre-filled target list: they know your exact framework and server version without running a single probe, and can immediately cross-reference known CVEs. This is reconnaissance that costs the attacker nothing and costs you nothing to prevent. CWE-200 (Exposure of Sensitive Information) and CWE-497 (Exposure of System Data to Unauthorized Control Sphere) both apply. OWASP A05 (Security Misconfiguration) lists version disclosure as a baseline misconfiguration. Suppressing these headers doesn't fix vulnerabilities, but it eliminates passive fingerprinting and forces attackers to do active work.

## Severity rationale

Low because version disclosure is reconnaissance-only — it enables faster targeted attacks but does not directly enable exploitation on its own.

## Remediation

Set `poweredByHeader: false` in `next.config.js` to suppress the `X-Powered-By` header. On Vercel this is stripped by default, but the explicit config ensures it doesn't reappear if you self-host.

```js
// next.config.js
const nextConfig = {
  poweredByHeader: false,
}
export default nextConfig
```

For Express: `app.disable('x-powered-by')` or `helmet()`, which disables it automatically. The `Server` header is usually controlled by your reverse proxy (nginx, Caddy) — set `server_tokens off;` in your nginx config to suppress the version number.

## Detection

- **ID:** `no-server-version`
- **Severity:** `low`
- **What to look for:** Count the version-revealing headers that need suppression: `X-Powered-By` and `Server`. For each, check whether configuration removes or suppresses them. In Next.js, check `next.config.*` for `poweredByHeader: false`. In Express, check for `app.disable('x-powered-by')` or helmet usage.
- **Pass criteria:** No more than 0 version-revealing headers are exposed. `X-Powered-By` header is suppressed via explicit config (e.g., `poweredByHeader: false` in Next.js, `app.disable('x-powered-by')` in Express, or `helmet()` middleware). Framework-default suppression by the hosting platform also counts (e.g., Vercel strips `X-Powered-By` by default for Next.js apps). The `Server` header should also not reveal specific version numbers (e.g., `nginx/1.24.0`).
- **Fail criteria:** `X-Powered-By` header is being sent with the framework/version information, and no configuration to suppress it is found. Or `Server` header explicitly reveals the server software version number.
- **Skip (N/A) when:** Never.
- **Detail on fail:** `"next.config.js does not set poweredByHeader: false — X-Powered-By: Next.js header will be sent"` or `"Express app does not disable x-powered-by header"`
- **Remediation:** Version headers help attackers identify your technology stack and target known vulnerabilities. Suppress them:

  ```js
  // next.config.js
  const nextConfig = {
    poweredByHeader: false,
  }
  ```

  For Express: `app.disable('x-powered-by')` or use `helmet()` which does this automatically.

## External references

- cwe CWE-200
- cwe CWE-497
- owasp A05

Taxons: operational-readiness

HTML version: https://auditbuffet.com/patterns/ab-000014
