CentralCSP
Security headers

Information disclosure

Server, X-Powered-By, and the other headers that leak your stack and versions to attackers, the full list and how to remove them.

Last update:

Some response headers exist only to advertise what software you run. Server names the web server, often with its exact version and operating system. X-Powered-By names the backend language or framework. Behind those two sits a long tail of vendor headers that name the CMS, the cache, the monitoring agent, or an internal machine. None of them change how the browser renders the page.

What they do is hand an attacker a free fingerprint of your stack, ready to grep against CVE databases for known exploits. The fix costs one config line per header: remove it, or where the server refuses to drop it, cut it down to a generic value with no version.

What a leaky response looks like
HTTP/1.1 200 OK
Server: Apache/2.4.41 (Unix)
X-Powered-By: PHP/8.2.1
Content-Type: text/html; charset=utf-8
After cleanup
HTTP/1.1 200 OK
Server: Apache
Content-Type: text/html; charset=utf-8

Why banners matter

Fingerprinting the web server is a formal first step of a penetration test. The OWASP testing guide (WSTG-INFO-02, Fingerprint Web Server) calls the technique banner grabbing: send a request, read the response headers. A header like Server: Apache/2.4.41 (Unix) answers most of the recon in one line, and as the guide puts it, servers running older versions of software without up-to-date security patches can be susceptible to known version-specific exploits.

The workflow is mechanical. An exact version banner, say X-Powered-By: PHP/5.3.7, goes straight into a CVE database search, which returns the list of vulnerabilities that version is known to have. Some disclosure headers give away more than a version. Microsoft Exchange responses can carry the names of internal front-end and back-end servers (X-FEServer, X-BEServer, X-CalculatedBETarget), mapping the same front-end to back-end routing surface that the ProxyLogon exploit chain (CVE-2021-26855, analyzed by Google Project Zero) abused.

Be honest about the weight of this finding, though. MDN calls obscuring the Server header a measure of debatable benefit, because attackers can fingerprint a stack by other means, and says the more reliable approach is to keep the software updated and patched. The Express security best practices say the same about disabling X-Powered-By: it does not prevent a sophisticated attacker from identifying the framework. Removing banners cuts off the cheapest recon vector and clears the findings every scanner and pentest report raises; the defense that actually matters is patching.

The headers to remove

Every header in the tables below gets the same advice, remove it, so there is no status column. The canonical inventory is the OWASP Secure Headers Project removal list, 81 headers as of its June 30, 2026 update, which scanners and pentest reports key off. The tables group the most common entries by what they leak; where a header is community-reported rather than officially documented, the description says so.

Server, language, and framework banners

HeaderWhat it leaks
ServerThe server software, usually its version, sometimes the OS (Apache/2.4.41 (Unix))
X-Powered-ByThe backend technology, often with a version. PHP sends it when expose_php is on; Express and Next.js send it by default
X-AspNet-VersionThe exact ASP.NET version
X-AspNetMvc-VersionThe ASP.NET MVC version
X-Php-VersionReported as a PHP version banner; on the OWASP removal list
X-Framework, X-Server-Powered-By, X-Content-Encoded-ByFurther stack banners on the OWASP removal list, widely reported on Joomla sites

CMS and platform versions

HeaderWhat it leaks
X-GeneratorThe CMS behind the page; Drupal emits Drupal N
X-OWA-VersionThe exact Exchange Outlook Web Access build number
X-Umbraco-Version, X-Joomla-Version, X-Powered-CMS, X-CF-Powered-ByReported as CMS version banners; on the OWASP removal list
X-Cocoon-VersionReported as an Apache Cocoon version banner
Liferay-PortalReported as leaking the Liferay edition and version
OracleCommerceCloud-VersionAn Oracle Commerce Cloud banner on the OWASP removal list
Pega-HostReported as leaking an internal Pega node name

Infrastructure and cache fingerprints

HeaderWhat it leaks
X-VarnishVarnish transaction IDs, one on a cache miss and two on a hit, fingerprinting the cache layer
X-Turbo-Charged-ByA LiteSpeed family server
X-Backside-TransportAn IBM DataPower gateway and the status of its backend connection
K-Proxy-RequestA Knative activator marker, revealing a Kubernetes serverless platform
Host-HeaderReported as exposing managed-hosting routing information
ProductOn the OWASP removal list

Internal hostnames

Exchange front-end servers add routing headers to Outlook Web Access and autodiscover responses. These leak internal machine names, which is topology disclosure rather than a version banner, and they sit on the same front-end to back-end routing surface ProxyLogon abused.

HeaderWhat it leaks
X-FEServerThe front-end Client Access Server name
X-BEServerThe back-end server name
X-CalculatedBETargetThe internal name of the target mailbox server
X-DiagInfoThe name of the responding mailbox server

Monitoring agents

The Dynatrace OneAgent family marks responses it has touched, telling an attacker exactly which monitoring stack watches the site.

HeaderWhat it leaks
X-OneAgent-JS-InjectionThe Dynatrace OneAgent injects its monitoring JavaScript here
X-ruxit-JS-AgentThe legacy name for the same injection marker
X-DTAgentIdThe Dynatrace agent ID, seen on health-check responses
X-DTHealthCheckA Dynatrace health-check marker

Development and debug artifacts

These go beyond fingerprinting: each one means something from development reached production.

HeaderWhat it leaks
SourceMap / X-SourcemapThe URL of a source map; if the .map file is public, anyone can reconstruct your original unminified client source
X-SourceFilesAn ASP.NET / IIS Express debug header carrying a base64-encoded local disk path of the source file. It is meant for localhost only, so seeing it in production means a debug configuration leaked
X-NextJS-Matched-PathThe internal Next.js route pattern that matched, such as /news/[slug]
X-NextJS-PageA related Next.js internal header on the OWASP removal list
X-GitLab-MetaA JSON blob with a correlation ID and version, observed on GitLab Pages responses

How to remove them

Each stack has a switch for its own banners. Anything your application or framework adds on top can be stripped by whatever sits in front of it, a reverse proxy or a CDN.

nginx

nginx.conf
server_tokens off;
proxy_hide_header X-Powered-By;

In nginx, server_tokens off hides the version in both the Server header and the built-in error pages, but the header still reads Server: nginx. Removing it entirely requires the third-party headers-more module (more_clear_headers Server;). When proxying, nginx already replaces the upstream Server header with its own; proxy_hide_header drops application headers such as X-Powered-By on the way through.

Apache

httpd.conf
ServerTokens Prod
ServerSignature Off
Header always unset X-Powered-By

In Apache, ServerTokens Prod trims the banner to Server: Apache and ServerSignature Off removes the version footer from error pages. Note that Header unset Server does not remove Apache's own Server header (Apache Bug 40026); mod_headers can only unset headers the application added, such as X-Powered-By.

IIS and ASP.NET

web.config
<configuration>
  <system.web>
    <httpRuntime enableVersionHeader="false" />
  </system.web>
  <system.webServer>
    <security>
      <requestFiltering removeServerHeader="true" />
    </security>
    <httpProtocol>
      <customHeaders>
        <remove name="X-Powered-By" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>
</configuration>

On IIS 10 and later, removeServerHeader removes the Server header completely (Windows Server version 1709 and later). enableVersionHeader="false" drops X-AspNet-Version, and the customHeaders block removes X-Powered-By. The MVC version banner has its own switch, set at application start:

Global.asax.cs
MvcHandler.DisableMvcResponseHeader = true;

Express

app.js
app.disable('x-powered-by');

The Express security best practices recommend this line, or using Helmet, which removes the header along with its other header changes.

PHP

php.ini
expose_php = Off

expose_php can only be set in php.ini, not at runtime.

Next.js

next.config.js
module.exports = {
  poweredByHeader: false,
};

The poweredByHeader option stops Next.js from sending X-Powered-By.

At the CDN or proxy edge

The edge can strip what the origin cannot. On Cloudflare, a response header transform rule with the remove operation deletes any of these headers before the response reaches the visitor, with one caveat: it cannot remove cf- or x-cf- prefixed headers, nor Cloudflare's own server header. A reverse proxy or cache you run yourself, such as Varnish, can likewise unset response headers in its delivery logic. This is often the fastest fix for vendor headers that a managed platform gives you no switch for.

Can you remove the Server header entirely

It depends on the server. IIS 10 and later can, with removeServerHeader. Stock nginx cannot: server_tokens off still sends Server: nginx, and full removal needs the headers-more module. Apache cannot either; ServerTokens Prod and its Server: Apache floor is as far as the core config goes. Behind a CDN the question often disappears, because the edge substitutes its own banner (Cloudflare sends server: cloudflare, which you cannot remove). A bare product name with no version is a fine end state; the version is what feeds the CVE lookup.

Recommendation

Remove or genericize every header in the tables above. The OWASP HTTP Headers cheat sheet says it plainly: for Server, "Remove this header or set non-informative values", and "Remove all X-Powered-By headers". Use the OWASP Secure Headers Project removal list as the checklist when you sweep your responses.

Keep the finding in perspective. Deleting a banner patches nothing; if the software behind it is outdated, it is exactly as exploitable afterwards. Do this cleanup as hygiene alongside patching, not instead of it. To see which of these headers your site sends today, run it through the security headers scanner.

FAQ

How do I remove X-Powered-By?

It depends on what emits it. In PHP set expose_php = Off; in Express call app.disable('x-powered-by'); in Next.js set poweredByHeader: false; in IIS remove it through customHeaders. When you cannot change the origin, strip it at the reverse proxy or CDN, for example proxy_hide_header X-Powered-By in nginx.

Is the Server header a vulnerability?

Not by itself. It is an information-disclosure finding: the version banner tells an attacker which software and version to look up in a CVE database, cutting the cheapest recon step. The real risk is running unpatched software behind the banner. Removing it quiets scanners but patches nothing.

Does hiding version banners make my site secure?

No. Stripping Server, X-Powered-By, and the other banners is noise reduction: it removes the easiest fingerprinting vector and clears scanner findings. It does not fix a single underlying flaw. As OWASP and MDN both note, keeping the software patched is the actual defense; banner removal is hygiene alongside it.

See also

Sources

On this page