Many school websites broadcast their WordPress, Drupal, or Joomla version number in the page source. Attackers use this to target known vulnerabilities. Here's where it leaks and how to hide it.
Content Management Systems like WordPress, Drupal, and Joomla publish their version number in multiple places by default — HTML meta tags, RSS feeds, script file paths, and response headers. This is called CMS version exposure.
<!-- WordPress exposes version in the HTML head by default --> <meta name="generator" content="WordPress 6.4.1" /> <!-- Also in RSS feed --> <generator>https://wordpress.org/?v=6.4.1</generator> <!-- And in script/style URLs with version query strings --> <script src="/wp-includes/js/jquery.min.js?ver=6.4.1"></script>
When a school's site announces "we are running WordPress 6.4.1," any attacker — human or automated scanner — can immediately check: "What CVEs affect WordPress 6.4.1?"
Cybersecurity incidents tracked on SchoolBreach.org consistently involve outdated CMS installations. A school may install WordPress in 2020 and leave it running for years without updates. In that time, dozens of vulnerabilities accumulate.
Version exposure tells an attacker exactly how far behind you are.
Attackers don't manually check school websites one by one. They run automated tools that scan thousands of sites, identify CMS versions, and flag all sites running versions with known exploits. Your school site gets added to a list and targeted automatically.
WordPress plugins add their own version numbers to script and style URLs:
<link rel="stylesheet" href="/wp-content/plugins/contact-form-7/includes/css/styles.css?ver=5.7.5" />
Plugin vulnerabilities are even more common than core WordPress vulnerabilities, and version exposure applies equally.
| Location | What It Shows |
|----------|--------------|
| HTML <meta name="generator"> | CMS name and version |
| RSS/Atom feed <generator> tag | WordPress version |
| Script/style URL ?ver= parameters | Core and plugin versions |
| /wp-admin/ login page source | WordPress branding |
| /readme.html | WordPress version (if not deleted) |
| /CHANGELOG.txt | Drupal version history |
| HTTP X-Generator header | CMS name and version |
| /wp-json/ REST API | WordPress version in JSON response |
Add to your theme's functions.php:
remove_action('wp_head', 'wp_generator');
add_filter('the_generator', '__return_empty_string');function remove_version_from_scripts($src) {
if (strpos($src, 'ver=')) {
$src = remove_query_arg('ver', $src);
}
return $src;
}
add_filter('style_loader_src', 'remove_version_from_scripts');
add_filter('script_loader_src', 'remove_version_from_scripts');These files in the WordPress root reveal the version. Delete them after every WordPress update (or automate this in your deployment process).
rm /var/www/yourschool/public_html/readme.html rm /var/www/yourschool/public_html/license.txt
Add to functions.php:
add_filter('json_index_request', function($response) {
$response->remove_link('https://api.w.org/');
unset($response->data['namespaces']);
return $response;
});Wordfence, iThemes Security, or WP Hardening plugins handle most of these in a single settings panel without custom code.
// In settings.php: $conf['drupal_http_request_fails'] = TRUE; // Also: delete CHANGELOG.txt, INSTALL.txt, README.txt from web root
Hiding the version number reduces your attack surface but does not eliminate vulnerabilities. The real fix is:
A school running the latest WordPress version with the version hidden is far safer than one running an old version with the version hidden.
The Site Scanner checks your school's site for CMS and plugin version exposure.