Skip to Content
OpenVAPTAlpha
Pre-release. Academic, non-commercial, source-available code built by AI Cybersecurity Engineers. Free for your own use, 100% at your own risk. This website collects no data. Read MoreRead Less
Pre-release. OpenVAPT has no Stable release yet. Every build is an Alpha, Beta or Release Candidate: it may be incomplete or wrong, so use it only on test machines, 100% at your own risk. See Release Channels
Academic, non-commercial, source-available code built by AI Cybersecurity Engineers. These are AI systems, not people or registered engineers. Free for your own personal or business use, on your own machines, 100% at your own risk. Not for sale. Not for providing services. This website collects no data. Read the Acknowledgements
Pre-release. OpenVAPT has no Stable release yet. Every build is an Alpha, Beta or Release Candidate: it may be incomplete or wrong, so use it only on test machines, 100% at your own risk. See Release Channels
Academic, non-commercial, source-available code built by AI Cybersecurity Engineers. These are AI systems, not people or registered engineers. Free for your own personal or business use, on your own machines, 100% at your own risk. Not for sale. Not for providing services. This website collects no data. Read the Acknowledgements
LowWEB-CMS-001Information ExposureWeb Apps

WordPress Version Disclosed

Checks whether WordPress sites reveal their exact version in the page or in readme.html.

Why It Matters
The version number lets automated tools pick matching exploits for outdated cores and plugins.
How It Detects
Looks for the WordPress generator meta tag on the home page and requests /readme.html, which counts only when it carries the WordPress readme signature (the logo heading and a Version line), so a soft-404 page that merely mentions WordPress does not fire.
How to Fix
Keep WordPress updated (automatic minor updates on). Remove the generator tag (remove_action('wp_head','wp_generator')) and delete readme.html after each update, or block it at the web server.
How to Verify
curl -s https://<site>/ | grep -i 'name="generator"'
CVSS v3.1 Vector
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
Control Category
Information Exposure: CIS Controls v8 3, 16; NIST CSF 2.0 PR.DS
Fix Effort
Low
CIS Controls v8 Safeguard
16.7
NIST CSF 2.0 Subcategory
PR.PS-01
OWASP WSTG v4.2
WSTG-INFO-08
CWE
CWE-497
OWASP Top 10
A05:2021, A06:2021
OWASP ASVS 4.0.3
14.3.3
NIST SP 800-53 Rev. 5
CM-7, SI-11
References
WordPress Developer Resources, Hardening WordPress
Learn the theory behind this check: P6 Information Exposure and Misconfiguration, P14 CMS Hardening in Depth: WordPress, Joomla and Drupal.

Source Code

The complete file that defines this check. Run it with openvapt scan --only WEB-CMS-001, or read it offline with openvapt explain WEB-CMS-001.

internal/checks/web/cms.go · Lines 1-84View on GitHub at This Commit
1package web
2
3import (
4 "context"
5 "regexp"
6 "time"
7
8 "github.com/openvapt/openvapt/internal/check"
9 "github.com/openvapt/openvapt/internal/sys"
10)
11
12// wpReadmeRe matches the signature of WordPress's own readme.html: the logo
13// heading followed by the version line, for example
14// <h1 id="logo"><a href="https://wordpress.org/">WordPress</a><br /> Version 6.4</h1>.
15var wpReadmeRe = regexp.MustCompile(`(?is)<h1 id="logo">.{0,200}?wordpress.{0,200}?version\s+(\d+(?:\.\d+)+)`)
16
17// wpReadmeVersion returns the version stated by a WordPress readme.html.
18func wpReadmeVersion(body string) (string, bool) {
19 if m := wpReadmeRe.FindStringSubmatch(body); m != nil {
20 return m[1], true
21 }
22 return "", false
23}
24
25func today() string { return time.Now().UTC().Format("2006-01-02") }
26
27func init() {
28 check.Register(&check.Check{
29 ID: "WEB-CMS-001",
30 Title: "WordPress Version Disclosed",
31 Domain: check.DomainWeb,
32 Severity: check.Low,
33 CVSS: "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N",
34 Summary: "Checks whether WordPress sites reveal their exact version in the page or in readme.html.",
35 Rationale: "The version number lets automated tools pick matching exploits for outdated cores and plugins.",
36 Detection: "Looks for the WordPress generator meta tag on the home page and requests /readme.html, which counts only when it carries the WordPress readme signature (the logo heading and a Version line), so a soft-404 page that merely mentions WordPress does not fire.",
37 Fix: "Keep WordPress updated (automatic minor updates on). Remove the generator tag (remove_action('wp_head','wp_generator')) and delete readme.html after each update, or block it at the web server.",
38 Verify: "curl -s https://<site>/ | grep -i 'name=\"generator\"'",
39 Refs: []check.Ref{{Title: "WordPress Developer Resources, Hardening WordPress", URL: "https://developer.wordpress.org/advanced-administration/security/hardening/"}},
40 Standards: check.Standards{CWE: []string{"CWE-497"}, OWASP: []string{"A05:2021", "A06:2021"}, ASVS: []string{"14.3.3"}, WSTG: []string{"WSTG-INFO-08"}, NIST: []string{"CM-7", "SI-11"}},
41 Run: func(ctx context.Context, s sys.System) []check.Result {
42 gen := regexp.MustCompile(`(?i)<meta name="generator" content="WordPress ([\d.]+)"`)
43 return ForEachSite(ctx, s, func(st Site) check.Result {
44 var ev []string
45 if m := gen.FindStringSubmatch(st.Home.Body); m != nil {
46 ev = append(ev, "generator tag: WordPress "+m[1])
47 }
48 if r, err := st.Get(ctx, s, "/readme.html"); err == nil && r.Status == 200 {
49 if v, ok := wpReadmeVersion(r.Body); ok {
50 ev = append(ev, "/readme.html is public and states WordPress "+v)
51 }
52 }
53 if len(ev) > 0 {
54 return check.FailR(st.Name, "WordPress version is disclosed", ev...)
55 }
56 return check.PassR(st.Name, "No WordPress version disclosure found")
57 })
58 },
59 })
60
61 check.Register(&check.Check{
62 ID: "WEB-CMS-002",
63 Title: "WordPress XML-RPC Interface Enabled",
64 Domain: check.DomainWeb,
65 Severity: check.Low,
66 CVSS: "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L",
67 Summary: "Checks whether xmlrpc.php answers on WordPress sites.",
68 Rationale: "XML-RPC allows many password guesses in one request (system.multicall) and is abused for pingback amplification. Few sites still need it.",
69 Detection: "Sends one GET to /xmlrpc.php; the standard reply 'XML-RPC server accepts POST requests only.' confirms it is enabled. No XML-RPC call is made.",
70 Fix: "Block it at the web server (<Files xmlrpc.php> Require all denied </Files>) or disable it with a security plugin, unless Jetpack or the mobile app needs it.",
71 Verify: "curl -s https://<site>/xmlrpc.php should return 403 or 404.",
72 Refs: []check.Ref{{Title: "WordPress Developer Resources, Brute Force Attacks (XML-RPC)", URL: "https://developer.wordpress.org/advanced-administration/security/brute-force/"}},
73 Standards: check.Standards{CWE: []string{"CWE-307"}, OWASP: []string{"A07:2021"}, NIST: []string{"AC-7", "CM-7"}},
74 Run: func(ctx context.Context, s sys.System) []check.Result {
75 return ForEachSite(ctx, s, func(st Site) check.Result {
76 r, err := st.Get(ctx, s, "/xmlrpc.php")
77 if err == nil && regexp.MustCompile(`XML-RPC server accepts POST`).MatchString(r.Body) {
78 return check.FailR(st.Name, "xmlrpc.php is enabled")
79 }
80 return check.PassR(st.Name, "xmlrpc.php is not reachable")
81 })
82 },
83 })
84}

Also available as plain Markdown for notes, scripts and AI tools. Same facts, same source, no styling.

Cite This Page

If this page helped your work, please cite it. The version and web address are filled in; the access date is today's date in your browser. Every other style, and when credit is required, is on How to Cite OpenVAPT.

APA 7
OpenVAPT. (2026). WEB-CMS-001 WordPress Version Disclosed (Version 0.1.0-alpha.6). OpenVAPT Check Catalogue. Retrieved October 16, 2026, from https://openvapt.com/checks/WEB-CMS-001.html

In text: (OpenVAPT, 2026). Accessed: the date shown is today's date from your own browser (the site's build date without JavaScript); change it to the day you read the page.

BibTeX
@misc{openvapt_web_cms_001,
  author       = {{OpenVAPT}},
  title        = {{WEB-CMS-001 WordPress Version Disclosed}},
  year         = {2026},
  howpublished = {\url{https://openvapt.com/checks/WEB-CMS-001.html}},
  note         = {OpenVAPT Check Catalogue, version 0.1.0-alpha.6. Accessed 16 October 2026}
}

Accessed: the date shown is today's date from your own browser (the site's build date without JavaScript); change it to the day you read the page.

Citing OpenVAPT does not mean OpenVAPT endorses, approves or has reviewed your work.