Self-hosted service
wpscanteam/wpscan avatar
wpscanteam/wpscan

wpscan: the install paths, the baked database and the 25 request ceiling

WPScan WordPress security scanner. Written for security professionals and blog maintainers to test the security of their WordPress websites. Contact us via [email protected]

9,852 stars1,347 forksRubyNOASSERTION

At a glance

What is it?
WPScan is a Ruby command line scanner for WordPress sites, aimed at security professionals and at people who maintain their own blog. It installs by gem, Homebrew, a distribution package or Docker, keeps its vulnerability data in a local cache, and stops reporting vulnerabilities once the daily API allowance runs out.
Who is it for?
Take the Homebrew or package manager route if a pentesting distribution already ships it, and the gem route if you need to control the version, with build-essential and ruby-dev installed before you run gem install wpscan. Use the Docker image when you cannot put Ruby on the host, and mount a named volume at /wpscan/.cache/wpscan/db or you will scan against a database that went stale when the image was built.
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 7 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 November 13, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • wpscanteam/wpscan9,852 ★ · +58
Star history
Repository2026-09-302026-11-13
wpscanteam/wpscan9.8k9.9k

58 Stars in the last 44 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Three install paths, and two of them need a C toolchain

WPScan is a Ruby program, and the README gives several ways to get it. On macOS the shortest is Homebrew:

shell
brew install wpscanteam/tap/wpscan

On a pentesting distribution such as Kali Linux it recommends the package manager when one is available. Everywhere else the route is RubyGems, which is where the real work sits: WPScan depends on gems with native extensions such as `yajl-ruby`, `nokogiri` and `ffi`, so a working C toolchain and the Ruby development headers have to be there before the install starts. The commands per distribution are:

shell
sudo apt install build-essential ruby-dev
sudo dnf install @development-tools ruby-devel
sudo pacman -S base-devel ruby
sudo apk add build-base ruby-dev

On macOS that means the Xcode Command Line Tools, installed with `xcode-select --install`. Only then:

shell
gem install wpscan

Docker is the fourth option, and the one that needs nothing on the host beyond a daemon: `docker pull wpscanteam/wpscan`.

Ruby 3.3 and Curl 7.72 are floors, and 7.29 crashes

Two version floors sit above the install commands. Ruby must be 3.3 or newer, and Curl must be 7.72 or newer, with the latest stable recommended for both. The README gives a reason for the Curl floor and a reason to avoid one version in the middle: 7.29 has a segfault, and anything below 7.72 can produce `Stream error in the HTTP/2 framing layer` in some cases.

The build failures are easier to diagnose because the README names them. Without the toolchain in place, `gem install wpscan` stops with errors like `Failed to build gem native extension` or `make: x86_64-linux-gnu-gcc: No such file or directory`. One more trap is specific to macOS: if SIP raises a `Gem::FilePermissionError`, the README offers two ways out, installing RVM and repeating the install, or `sudo gem install -n /usr/local/bin wpscan`. Nokogiri may also want system packages from your package manager.

The image bakes the database in, and --rm discards your update

The Docker section explains a caveat. The image ships with a copy of the local database baked in at build time, and every example command runs with `--rm`. So any database update you trigger inside a container is discarded when the container exits, and the next run starts again from that baked-in copy, which the README calls potentially stale.

The fix is a named volume at `/wpscan/.cache/wpscan/db`, the `wpscan` user's cache directory inside the container:

shell
docker run -it --rm -v wpscan-db:/wpscan/.cache/wpscan/db wpscanteam/wpscan --update

Mounted that way, the database survives across runs, `wpscan --update` only re-downloads files whose checksums actually changed, and the five day staleness prompt behaves the way it does for a local install. The volume is created on first use if it does not exist yet.

Enumeration looks the same way, with the volume in place:

shell
docker run -it --rm -v wpscan-db:/wpscan/.cache/wpscan/db wpscanteam/wpscan --url https://target.tld/ --enumerate u

Swap `u` for `u1-100` to sweep a range instead of a single name.

wpscan --update and gem update wpscan move different things

Two updates exist and confusing them wastes an afternoon. `wpscan --update` refreshes the local database on your machine. `gem update wpscan` upgrades the program itself, and on a distribution where WPScan came from a package manager the README points at `apt-get update && apt-get upgrade` instead.

The third source of data is remote. WPScan queries the WordPress Vulnerability Database API for vulnerability information in real time, and it needs a token for that, supplied through `--api-token` or through a configuration file. An account on WPScan.com is where the token comes from.

Here is the limit that decides whether a scan means anything. Up to 25 API requests per day are free, which the README says should suit scanning most WordPress websites once a day. When the day's 25 are gone, WPScan keeps working normally and returns findings, but with no vulnerability data behind them. A report with nothing in the vulnerability column at the end of a long day is not evidence that the site is clean; it is evidence that the lookup budget ran out. Enterprise customers can point the scan at a local database dump instead and drop the request limit entirely.

XDG moved the database out of ~/.wpscan

An older install and a newer one put the same files in different places. New installations use `~/.cache/wpscan/db`, or `$XDG_CACHE_HOME/wpscan/db` when that variable is set, following the XDG Base Directory Specification. Existing installations keep `~/.wpscan/db`, which is maintained for backward compatibility.

If you are migrating, the README gives the move:

shell
mv ~/.wpscan ~/.cache/wpscan

Runtime files follow the same convention. The default HTTP cache and the cookie jar land under `$TMPDIR/wpscan` when `TMPDIR` is set, and otherwise in the per-user cache directory, for instance `~/.cache/wpscan/cache` and `~/.cache/wpscan/cookie_jar.txt`. Both locations have command line overrides, `--cache-dir` and `--cookie-jar`, which matter when two scans must not share state, or when a cookie jar has to survive a cleanup that empties a temporary directory.

plugins-detection defaults to passive, which starves --enumerate

The plain scan is one command:

shell
wpscan --url blog.tld

It runs with defaults the README calls a good compromise between speed and accuracy: version detection, theme detection and interesting findings. Enumeration is opt-in through `-e`, with `-e ap` for all plugins, `-e vp` for vulnerable plugins and `-e bf` for backup folders. There is a quieter mode too, `wpscan --stealthy --url blog.tld`.

The detail that decides whether enumeration returns anything is a default value: plugins-detection is passive unless you change it. The README spells out the consequence, that when you use `--enumerate` you have to set `--plugins-detection` accordingly. Left alone, an enumeration run against a site that is not sending plugin hints can come back thin while looking like a successful scan.

Two smaller notes from the same section. `wpscan --help` lists everything else, and if you built WPScan from the source you have to run that command from outside the git repo. The full option reference lives in the project wiki rather than in the README.

Dockerfile builds on ruby:4.0.3-alpine and drops the toolchain

The Dockerfile answers the question the install section leaves open, and it explains the stale database. It is a two stage build on `ruby:4.0.9-alpine`. The builder installs the full compile set, among them git, libcurl, ruby-dev, libffi-dev, make, gcc, musl-dev, zlib-dev, procps and sqlite-dev, then forces the Ruby platform, skips the `test` and `development` groups, runs `bundle install` with eight jobs and finishes with `rake install --trace`.

The runtime image keeps only `libcurl procps sqlite-libs`, creates an unprivileged `wpscan` user whose home is `/wpscan`, and hands the tree over to it. That user is who writes the database, which is why the volume has to mount at `/wpscan/.cache/wpscan/db`. Two lines explain the rest:

dockerfile
RUN /usr/local/bundle/bin/wpscan --update --verbose

ENTRYPOINT ["/usr/local/bundle/bin/wpscan"]

The update runs during the build, once, as the `wpscan` user, before the image exists. Its result is frozen into the image at that moment, and the entrypoint is the bare binary, with no wrapper to refresh it later.

Three tags in ten weeks, and a LICENSE the metadata does not name

The version line has moved quickly. v4.0.1 was published on 2026-07-08, v4.1.0 on 2026-07-23 and v4.2.0 on 2026-10-27, so a pin that is more than a few months old is behind at least one minor release, and a project that has to keep its scanner current should decide whether it tracks releases or follows the package its distribution ships. The last push was on 2026-10-27, and the repository is not archived.

The repository also ships the machinery of a tested Ruby project: spec/, .rspec, .simplecov, .rubocop.yml, .qlty/, a Rakefile, wpscan.gemspec, and both .ruby-version and .ruby-gemset. That layout is what you clone if you intend to run the test suite rather than install a gem.

Licence needs care. A LICENSE file sits at the top level, while the repository metadata reports the licence as unasserted, so the two do not agree on their face. Read LICENSE before you ship WPScan inside something you distribute.

Editorial conclusion

Take the Homebrew or package manager route if a pentesting distribution already ships it, and the gem route if you need to control the version, with build-essential and ruby-dev installed before you run gem install wpscan. Use the Docker image when you cannot put Ruby on the host, and mount a named volume at /wpscan/.cache/wpscan/db or you will scan against a database that went stale when the image was built. Before trusting a clean result, check that your API token still has requests left for the day, since WPScan keeps scanning after the 25 free calls are spent and simply stops matching vulnerabilities.

Frequently asked questions

What is the use of WPScan?

It scans a WordPress site for version, theme and plugin information, then matches what it finds against vulnerability data. A default run does version detection, theme detection and interesting findings discovery, and `-e` adds enumeration of plugins, themes, users and backup folders.

Is WPScan free?

The tool is installed with gem, Homebrew or Docker, and up to 25 API requests per day come free of charge. Once those are used up WPScan keeps running and still returns findings, but without any vulnerability data.

What is the price of WPScan?

It states that 25 API requests per day are free of charge and that Enterprise customers can scan against a local database dump with no request limits.

How do I install WPScan?

On macOS, `brew install wpscanteam/tap/wpscan`. On a pentesting distribution, use the package manager when it offers one. Otherwise install the build tools for your distribution, for example `sudo apt install build-essential ruby-dev`, and then run `gem install wpscan`.

How do I use WPScan in Kali Linux?

The README recommends installing or updating WPScan with the package manager when a pentesting distribution provides one, and points at `apt-get update && apt-get upgrade` for keeping it current. Installing by gem in the same distribution means you own the Ruby toolchain yourself.

How do I use a WPScan API token?

Supply the token with the `--api-token` option or through a configuration file, and get one by registering an account on WPScan.com. It is what lets the CLI pull vulnerability data in real time, and it is counted against the 25 free requests per day.

Official sources

  1. Issues
  2. Project website
  3. README
  4. Releases
  5. wpscanteam/wpscan on GitHub
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/wpscanteam-wpscan.svg)](https://hysenlabs.com/projects/wpscanteam-wpscan)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/wpscanteam-wpscan.svg)](https://hysenlabs.com/projects/wpscanteam-wpscan)

Was this useful?