Hiding Software Versions in Headers and Markup
Many servers, frameworks and content management systems announce themselves by default. A response
header such as Server: Apache/2.4.41 (Ubuntu) or X-Powered-By: PHP/7.4.3, or a tag like
<meta name="generator" content="WordPress 6.2">, tells every visitor exactly which software and
version you run.
Why it matters
Attackers and automated bots look for sites running versions with published vulnerabilities. A version string lets them skip straight to a matching exploit instead of probing. Hiding versions does not fix an outdated component, and it will not stop a determined attacker who can fingerprint software in other ways. It does take you off the cheapest, broadest target lists, and it costs nothing.
The real fix for a vulnerable version is to update it. Treat this check as a reminder to do both.
What we check
| Check | Passes when |
|---|---|
| No software version disclosure | none of the signals below are found in the page response |
We report “needs attention” for any of these:
- a
Serverheader that contains a digit, such asnginx/1.24.0(a barenginxorcloudflareis fine); - any
X-Powered-By,X-AspNet-VersionorX-AspNetMvc-Versionheader, with or without a version, since these headers serve no purpose for visitors; - a
<meta name="generator">tag whose content contains a digit.
The report shows the exact values we found.
How to fix
Web servers
Nginx: hide the version in the Server header and on error pages:
server_tokens off;
The header then reads just nginx. Removing it entirely needs a third-party module or a proxy in
front.
Apache:
ServerTokens Prod
ServerSignature Off
ServerTokens Prod reduces the header to Apache. ServerSignature Off removes the version line
from error pages. ServerTokens must be set in the main server configuration, not in .htaccess.
IIS: in current IIS 10 releases, set removeServerHeader="true" on the requestFiltering element in
web.config.
Languages and frameworks
PHP: in php.ini:
expose_php = Off
ASP.NET (web.config), to remove X-AspNet-Version and X-Powered-By:
<system.web>
<httpRuntime enableVersionHeader="false" />
</system.web>
<system.webServer>
<httpProtocol>
<customHeaders>
<remove name="X-Powered-By" />
</customHeaders>
</httpProtocol>
</system.webServer>
For X-AspNetMvc-Version, set MvcHandler.DisableMvcResponseHeader = true; at application start.
Express (Node.js):
app.disable('x-powered-by');
At the proxy or CDN
If you cannot change the origin, strip the headers on the way out.
Nginx as a reverse proxy
proxy_hide_header X-Powered-By;
Apache (mod_headers)
Header always unset X-Powered-By
Cloudflare: use a Response Header Transform Rule to remove X-Powered-By.
CMS generator tags
WordPress adds a generator tag with its version to the page head. Remove it in your theme’s
functions.php or a small plugin:
remove_action('wp_head', 'wp_generator');
Some plugins and page builders add their own generator tags or version query strings. Check your page source after changes. Other systems, such as Joomla and Drupal, have similar settings or theme hooks; search their documentation for “generator meta tag”.
Keep updating
Hiding versions only helps if what you run is current. Keep your server, language runtime, CMS
core, plugins and themes on supported releases, and subscribe to their security announcements.
Version strings also leak through other places, such as default error pages, readme and
CHANGELOG files left in the web root, and asset URLs with ?ver= parameters, so remove what you
do not need to publish.
Further reading: OWASP: Fingerprint Web Server.