WPScan: what the WordPress scanner finds, and what it needs to find it
WPScan WordPress security scanner. Written for security professionals and blog maintainers to test the security of their WordPress websites. Contact us via [email protected]
At a glance
- What is it?
- WPScan is a Ruby CLI that fingerprints WordPress installs and matches them against the WPScan vulnerability database. Here is how it works, how to install it, and where the free tier stops.
- Who is it for?
- Adopt WPScan if you maintain a WordPress site, run authorized client assessments, or want plugin and user enumeration from a scriptable CLI; the RubyGems install and the Docker image both work without a paid account, and version and theme detection run without any token.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly Ruby, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap WPScan fills: version drift on WordPress sites
A WordPress site is rarely one piece of software. It is core, a theme, and a plugin directory that often holds twenty or more packages written by different authors, each with its own release cadence. The site owner usually knows the core version because the dashboard nags about it. They rarely know which plugin is two years behind. WPScan exists to answer that question from the outside, without credentials, by fingerprinting what the site exposes and matching the results against a vulnerability database. The README frames the audience directly: security professionals and blog maintainers. Those are two different jobs. A consultant runs it against a client's host under a scope agreement and needs the enumeration flags and the API. A maintainer runs it against their own blog and mostly needs to know that a plugin they forgot about has a published issue. The tool is the same; the flags differ.
How WPScan fingerprints a site without logging in
The default scan is deliberately conservative. Running wpscan --url blog.tld performs version detection, theme detection, and interesting findings discovery, which the README describes as a good compromise between speed and accuracy. Plugin enumeration is not part of that default, because finding plugins means sending requests that look like probing. The -e option turns it on, with values such as ap for all plugins, vp for vulnerable plugins, and bf for backup folders. Detection mode matters here. The README states that --plugins-detection defaults to passive, and that when you use --enumerate you should set --plugins-detection accordingly. That is the central trade-off of the tool: passive detection reads what the site already serves, while a more aggressive mode sends requests that a site with logging or a web application firewall will notice. There is a --stealthy flag for the cases where being noticed is the problem. The scan output is matched against the local database, and the CLI uses the WordPress Vulnerability Database API to retrieve vulnerability data in real time, which is why the token matters.
Installing WPScan and running a first scan
WPScan is a Ruby gem. The README lists Ruby >= 3.3 and Curl >= 7.72 as prerequisites, and warns that Curl 7.29 has a segfault and that versions below 7.72 could produce a Stream error in the HTTP/2 framing layer. On a pentesting distribution such as Kali Linux, the README recommends installing or updating through the package manager when one is available. On macOS, Homebrew is the shortest path:
brew install wpscanteam/tap/wpscanFor a gem install, the native extensions are the usual failure point. The README notes that WPScan depends on gems with native extensions such as yajl-ruby, nokogiri and ffi, so a C toolchain and Ruby development headers must be present first, otherwise the build fails with errors like Failed to build gem native extension. On Debian or Ubuntu the prerequisite packages are:
sudo apt install build-essential ruby-dev
gem install wpscanOn macOS, if a Gem::FilePermissionError appears because of System Integrity Protection, the README offers sudo gem install -n /usr/local/bin wpscan as one workaround. Once installed, the first scan needs no token:
wpscan --url blog.tldYou should see the detected WordPress version, the active theme, and interesting findings. The README also documents a Docker route: docker pull wpscanteam/wpscan, then run the image with --url and --enumerate, for example --enumerate u for usernames or --enumerate u1-100 for a range. Full user documentation lives in the project wiki, and wpscan --help lists the remaining options.
The API token, the 25-request ceiling and the stale database trap
This is the part that decides whether WPScan is a free tool or a metered one. The README states that an API token must be supplied via the --api-token option or a configuration file for WPScan to retrieve vulnerability data, and that a token comes from registering an account on wpscan.com. It also states the free allowance plainly: up to 25 API requests per day. A single --enumerate ap run against a plugin-heavy site can consume a meaningful share of that budget, so scanning a portfolio of sites in one afternoon is not what the free tier is sized for. The second constraint is the local database. wpscan --update refreshes it, and the Docker image bakes a copy in at build time. Because the README's example commands use --rm, any update performed during a container run is discarded when the container exits, and the next run starts from the baked-in copy. Mounting a named volume at /wpscan/.cache/wpscan/db keeps it across runs, so --update only re-downloads files whose checksums changed. Database location follows the XDG Base Directory Specification: new installations use ~/.cache/wpscan/db, while existing installations keep the legacy ~/.wpscan/db path. The README gives the migration command, mv ~/.wpscan ~/.cache/wpscan, and notes that runtime files such as the HTTP cache and cookie jar live under $TMPDIR/wpscan when that variable is set, overridable with --cache-dir and --cookie-jar.
Where WPScan is the wrong tool
WPScan enumerates. It does not inspect file contents, compare hashes against a known-good baseline, or read server logs. If your actual question is whether a site is already compromised, a scan that reports a current plugin version and a clean theme tells you nothing about an injected script in a template file or a modified core file. The README's own framing is version detection, theme detection, and interesting findings discovery, plus optional plugin, user and backup-folder enumeration. That is an exposure assessment, not an incident response tool. The second limitation is detection mode. With --plugins-detection left at its passive default, plugins that do not advertise themselves in the HTML will not appear, and the scan can under-report. Switching to a louder mode produces more findings at the cost of visibility to the target's defenses, which is precisely the wrong trade in a scan you have not been authorized to run. Third, the free API tier of 25 requests per day makes the tool awkward for anyone scanning many hosts, and without a token the vulnerability matching is limited to what the local database already holds.
WPScan compared with a general-purpose web scanner
The obvious alternative is a general web application scanner such as OWASP ZAP or Nikto. The difference is not quality, it is what each one knows. A general scanner crawls a site and applies generic checks: header configuration, exposed paths, injection probes, known server banners. It has no concept of a WordPress plugin slug, no notion that a theme has a version number, and no vulnerability database keyed to WordPress components. WPScan works the other way around. It has a narrow target and deep knowledge of that target, which is why it can tell you that a specific plugin at a specific version matches a published issue. The cost of that focus is that it will not find a misconfigured S3 bucket, an open redirect in custom code, or a SQL injection in a bespoke form handler. For a WordPress site the sensible arrangement is both: WPScan for the component inventory, a general scanner for everything the components sit on.
Maintenance, updates and the licence question
The repository is not archived and the last push was on 2026-09-26, two days before this writing. Recent releases are v4.0.0 on 2026-05-19, v4.0.1 on 2026-07-08 and v4.1.0 on 2026-07-23. Upgrading the tool is separate from updating its data. The README states that wpscan --update refreshes the local database, while updating WPScan itself is done with gem update wpscan or through the package manager, and it calls the package-manager path quite important for distributions such as Kali Linux, where the command is apt-get update && apt-get upgrade. Installing through a package manager and then running gem update wpscan on the same machine can leave you with two copies, so pick one path and stay on it. On licensing, the repository metadata reports NOASSERTION for the license, which means the GitHub API could not map the LICENSE file to a known identifier. The LICENSE file is present at the repository root. Read it before redistributing the tool or bundling it into a commercial service; this article cannot tell you what it permits, and nothing here is legal advice.
Editorial conclusion
Adopt WPScan if you maintain a WordPress site, run authorized client assessments, or want plugin and user enumeration from a scriptable CLI; the RubyGems install and the Docker image both work without a paid account, and version and theme detection run without any token. Do not adopt it as a malware scanner or as a substitute for reading your own logs: the README describes version, theme, plugin, user and backup-folder enumeration, not file-integrity or payload analysis, and the 25 requests per day on the free API tier will not carry a large portfolio through a full plugin sweep. Before you commit, register for an API token and run wpscan --url on one staging host with -e vp, then compare the plugin list it returns against the plugins you know are installed; that gap tells you how much of your real exposure the passive detection mode can actually see.
Frequently asked questions
What is WPScan used for?
It is a WordPress security scanner written in Ruby. The README describes it as a tool for security professionals and blog maintainers to test the security of their WordPress websites, and the default scan performs version detection, theme detection and interesting findings discovery.
Is WPScan free?
The CLI is installable from RubyGems and Docker without payment, but the vulnerability data comes from the WordPress Vulnerability Database API, which requires a token from a wpscan.com account. The README states the free allowance is up to 25 API requests per day.
How do I install WPScan on Ubuntu?
Install the C toolchain and Ruby headers first with sudo apt install build-essential ruby-dev, then run gem install wpscan. The README warns that without those packages the install fails with Failed to build gem native extension because of gems such as yajl-ruby, nokogiri and ffi.
How do I use a WPScan API token?
Pass it with the --api-token option, or put it in a configuration file as described in the README. The token comes from registering an account on wpscan.com, and it is what lets the CLI retrieve vulnerability data from the WordPress Vulnerability Database API.
Can WPScan scan a site for malware?
No. The README describes version detection, theme detection and optional plugin, user and backup-folder enumeration. It does not document file-integrity checking or payload analysis, so a clean scan does not establish that a site is free of injected code.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/wpscanteam-wpscan)