Title: DoctorX Hardening
Author: xaviercode
Published: <strong>November 9, 2026</strong>
Last modified: November 9, 2026

---

Search plugins

![](https://ps.w.org/doctorx-hardening/assets/banner-772x250.png?rev=3791744)

![](https://ps.w.org/doctorx-hardening/assets/icon-256x256.gif?rev=3791744)

# DoctorX Hardening

 By [xaviercode](https://profiles.wordpress.org/xaviercode/)

[Download](https://downloads.wordpress.org/plugin/doctorx-hardening.0.7.5.zip)

 * [Details](https://wordpress.org/plugins/doctorx-hardening/#description)
 * [Reviews](https://wordpress.org/plugins/doctorx-hardening/#reviews)
 *  [Installation](https://wordpress.org/plugins/doctorx-hardening/#installation)
 * [Development](https://wordpress.org/plugins/doctorx-hardening/#developers)

 [Support](https://wordpress.org/support/plugin/doctorx-hardening/)

## Description

DoctorX Hardening makes your WordPress site harder to break into. It closes a few
doors that WordPress leaves open, lets people add a code from their phone when they
sign in, and can keep a record of who did what on your site.

You do not need to know anything about security to use it. Turn it on and the main
protections work right away. Everything is free. Nothing is locked and there is 
no paid version.

#### What it does as soon as you turn it on

 * **Hides your usernames.** Normally anyone can look up the usernames on a WordPress
   site. A username is half of what someone needs to break in. Visitors can no longer
   see them.
 * **Hides your list of plugins.** Normally WordPress tells anyone who asks which
   plugins your site runs. Attackers use that list to look for a weak one. Visitors
   no longer get it.
 * **Keeps author pages from giving names away.** Links to author pages now go to
   your home page. If your site shows author pages on purpose, switch this one off.
 * **Stops a small WordPress guess.** When someone types a short address like /fr/
   that does not exist, they get “page not found” instead of being sent to a page
   with a similar name.
 * **Offers two-step sign-in.** Each person can choose to type a 6-digit code from
   a free phone app after their password. Then a stolen password alone is not enough
   to get in. Nobody has to use it unless you make it required.

Each one has its own on/off switch under Settings  Hardening.

#### Extra protections you can switch on

These are all off until you switch them on. Each one says how to undo it.

 * **Lock out password guessers.** An internet address that gets the password wrong
   5 times in a day cannot sign in for 30 days. You choose addresses that are never
   locked out, such as your office.
 * **Require two-step sign-in** for the roles you choose, such as administrators,
   from a date you pick.
 * **Email a code** to someone who does not have their phone with them.
 * **Close little-used doors:** XML-RPC (an old way for apps to sign in), app passwords,
   and the WordPress version number shown in your pages.
 * **Hide your sign-in page** at an address only you know. Not for shops or member
   sites, where visitors sign in themselves.
 * **Block scanners.** A visitor who asks for secret files that only hacking tools
   look for is blocked from the whole site for 7 days. Search engines are never 
   blocked.
 * **Activity record.** See who signed in, who failed to, and who changed posts,
   pages, plugins, settings or users, and when. Get an email, Slack, Teams, Discord
   or Telegram alert when something important happens.
 * **security.txt.** A small standard file that tells someone who finds a security
   problem on your site how to reach you.
 * **Cloudflare rules,** if your site uses Cloudflare. Add ready made blocking rules
   with one button and take them away with another.
 * **Ready made lines for your web server,** for you or your web host to copy in.

#### What it does not do

So you know where its job ends:

 * It is not a virus or malware scanner. It does not clean a site that has already
   been hacked.
 * It does not check every visit for attacks the way a firewall service does.
 * It does not make backups.
 * It does not update or fix your other plugins and themes. Keep them up to date.
 * It does not change what visitors, search engines or AI assistants see on your
   pages. Your search ranking is not affected.
 * Hiding things makes an attack harder, not impossible. Strong passwords and updates
   still matter.
 * It sends nothing about your site or your visitors to DoctorX or anyone else. 
   The outside services listed further down (such as Cloudflare or Slack) are only
   used if you set them up yourself.

#### Who it is for

Any WordPress site owner who wants the common holes closed without learning security.
It works with any theme and needs no other plugin.

Made by [DoctorX.ca](https://www.doctorx.ca/).

### External services

Nothing in this plugin talks to an outside service until you ask it to. None of 
the outside services below is used on a website set up not to send (DOCTORX_HARDENING_MAY_CONNECT
set to false, or the doctorx_hardening_may_connect filter), such as a staging copy,
except WordPress.org’s checksums, which WordPress itself also fetches.

 * **Cloudflare API** (https://api.cloudflare.com/client/v4), only after you save
   a Cloudflare API token of your own on Settings  Hardening  Sign-in and server,
   and only for what you press there or switch on. That is:
    - listing the zones the token can see
    - reading a zone’s custom firewall and rate-limit rules (Preview)
    - reading the zone’s cache rules, once a day, for the self-check (read only)
    - adding, changing or putting back rules (Apply, Undo, Copy)
    - sending the probe ban’s addresses as IP access rules (Send them now)
    - with “When a page changes, have Cloudflare forget it” (or DoctorX Command 
      Center’s “Empty caches”), the addresses of changed pages or a “forget everything”
      request.
 * Sent: the token (as the request’s authorisation), the zone’s id, the rules this
   plugin generates (your host names, your trusted addresses, the hidden door’s 
   address when it is on), banned internet addresses, and page addresses. Nothing
   about your visitors or accounts is sent. Cloudflare’s terms: https://www.cloudflare.
   com/website-terms/ and privacy policy: https://www.cloudflare.com/privacypolicy/
 * **ipinfo.io** (https://ipinfo.io), only when you choose “ipinfo.io” under “Where
   addresses are” on the activity record’s More settings screen, save your own token,
   and an administrator opens an address in the record: that one internet address
   and your token. ipinfo’s terms: https://ipinfo.io/terms-of-service and privacy
   policy: https://ipinfo.io/privacy-policy
 * **Google Maps Static API** (https://maps.googleapis.com), only when you switch
   on the sign-in map and save your own Google Maps key, and only when an administrator
   opens the map. Sent: up to 60 rounded map points (latitude and longitude to three
   decimals, about 100 metres) and your key. No addresses, names or accounts are
   sent. Google’s terms: https://cloud.google.com/maps-platform/terms and privacy
   policy: https://policies.google.com/privacy
 * **Alerts**, only to the destinations you add on the activity record’s More settings
   screen (Alerts) and only for the rules you set. Sent: the alert’s subject, text
   and a link to the record. For a webhook, also your site’s address, the rule’s
   name and the event (as below). The destinations can be:
    - Slack (the webhook address you paste). Terms https://slack.com/main-services-
      agreement and privacy https://slack.com/trust/privacy/privacy-policy
    - Discord. Terms https://discord.com/terms and privacy https://discord.com/privacy
    - Microsoft Teams. Terms https://www.microsoft.com/en-us/servicesagreement and
      privacy https://www.microsoft.com/en-us/privacy/privacystatement
    - Telegram (api.telegram.org with your bot’s token and chat). Terms https://
      telegram.org/tos and privacy https://telegram.org/privacy
    - any address of your own that takes JSON, signed with your secret if you set
      one.
 * **Log forwarding**, only when you switch it on on the activity record’s More 
   settings screen and switch on a destination with its connection details. Sent:
   every event as it is written, with its date, kind, level, message, who did it(
   user id, login and email address), the internet address and any addresses passed
   on by a proxy, the browser’s user agent, what it was about, the event’s details
   and your site’s address. (Writing to this server’s own system log is not an outside
   service and also happens on a website set up not to send.) The destinations can
   be:
    - this server’s own system log
    - a syslog server you name (UDP, TCP or TLS)
    - Datadog’s Logs API with your key. Terms https://www.datadoghq.com/legal/terms/
      and privacy https://www.datadoghq.com/legal/privacy/
    - Splunk’s HTTP Event Collector with your token. Terms https://www.splunk.com/
      en_us/legal/splunk-general-terms.html and privacy (Splunk is part of Cisco)
      https://www.cisco.com/site/us/en/about/legal/privacy.html
    - any webhook address of yours.
 * **WordPress.org** (https://api.wordpress.org), only when you switch on “Check
   WordPress’s own files once a day” in the activity record’s settings: once a day,
   your WordPress version and language, to fetch the official checksums of WordPress’s
   files (the same request WordPress makes for its own updates). WordPress.org’s
   privacy policy: https://wordpress.org/about/privacy/
 * **Your server’s DNS resolver**, only when you switch on “Also ask for the address’s
   host name” and an administrator opens an address in the record: that one internet
   address, to look up its host name (reverse DNS).
 * The emails this plugin sends (sign-in codes, the hidden door’s address, notes
   about two-step sign-in) go through your site’s own mail setup to your own people.
 * **Your own site’s address**, once a day, for the self-check: a few requests to
   your own site (a probe file in each private folder and a private probe page),
   which pass through your proxy or CDN if you have one. Nothing is sent to anybody
   else.
 * The crawler-list script on the “Lines for your web server” screen is a file you
   download and run on your server yourself: it fetches the address lists Google,
   Bing and Cloudflare publish (developers.google.com, www.bing.com, www.cloudflare.
   com). The plugin itself does not fetch them.

### Source code and credits

All code is included unminified. The picture you scan when setting up two-step sign-
in is drawn in the browser by QR Code Generator for JavaScript by Kazuhiko Arase(
MIT licence), included unchanged in assets/vendor/qrcode-generator.js. The word “
QR Code” is a registered trademark of DENSO WAVE INCORPORATED.

## Screenshots

[⌊Settings → Hardening: each protection with its own switch.⌉⌊Settings → Hardening:
each protection with its own switch.⌉[

Settings  Hardening: each protection with its own switch.

[⌊Setting up two-step sign-in: scan the code with an authenticator app, then type
the code it shows.⌉⌊Setting up two-step sign-in: scan the code with an authenticator
app, then type the code it shows.⌉[

Setting up two-step sign-in: scan the code with an authenticator app, then type 
the code it shows.

[⌊The sign-in page asks for the six-digit code after the password.⌉⌊The sign-in 
page asks for the six-digit code after the password.⌉[

The sign-in page asks for the six-digit code after the password.

[⌊The activity record (Tools → Activity): who did what on the site, with filters
and downloads.⌉⌊The activity record (Tools → Activity): who did what on the site,
with filters and downloads.⌉[

The activity record (Tools  Activity): who did what on the site, with filters and
downloads.

[⌊History insights: events a day, failed sign-ins and the most active people.⌉⌊History
insights: events a day, failed sign-ins and the most active people.⌉[

History insights: events a day, failed sign-ins and the most active people.

## Installation

 1. In your WordPress dashboard go to Plugins  Add New, search for “DoctorX Hardening”,
    press Install, then Activate.
 2. That is all. The protections in “What it does as soon as you turn it on” are now
    working. Open Settings  Hardening to see them, and switch off any you do not want.
 3. To add a phone code to your own sign-in, go to Users  Two-step sign-in (or Profile
    Two-step sign-in). You need a free authenticator app on your phone, such as Google
    Authenticator or Microsoft Authenticator. It takes about two minutes. Keep the 
    backup codes it gives you somewhere safe.
 4. Optional: to keep an activity record, tick “Keep an activity record” on Settings
    Hardening. You will find it under Tools  Activity.
 5. Optional: for a security.txt file, type a contact email on Settings  Hardening 
    and press Save.

## FAQ

### What are the limits of each protection?

The fine print, so that nobody relies on more than is there:

 * **Hidden plugin list:** only the list is hidden. A person who already knows or
   guesses a plugin can still find it in other ways.
 * **Two-step sign-in** works on normal sign-in pages, including most shop and membership
   plugins. Apps that sign in with a plain password are refused for an account that
   has it on. Give each app its own app password instead (at the bottom of your 
   profile). Sign-in through another service, such as “Sign in with Google”, does
   not pass through it.
 * **Wrong codes are limited:** 5 wrong codes in 15 minutes, or 20 in a day, pause
   the code step. The person is emailed. While it is paused the real person cannot
   sign in either, so set a new password if someone else knows yours. A new password
   ends the pause.
 * **Any administrator can switch two-step sign-in off for everybody.** When that
   is done on the settings screen or the Plugins screen, everybody who used it is
   emailed. If it is switched off in some other way (by editing files or the database),
   nobody is told.
 * **The emergency line** DOCTORX_HARDENING_NO_TWO_STEP in wp-config.php turns the
   phone code off for every account. It is for a locked-out owner, only for as long
   as needed.
 * **Multisite networks** do not get two-step sign-in or the hidden sign-in page.
 * **The phone app’s secret key** is stored encrypted with your site’s security 
   keys. If your host changes those keys, everybody sets two-step sign-in up again(
   backup codes still work to get in).
 * **security.txt** is a notice, not a lock. It makes it easy for an honest person
   to reach you.
 * **The password-guess lockout** counts by internet address. Many people can share
   one address, such as an office, and a lockout holds for all of them. That is 
   why you can list trusted addresses, and why an address an administrator used 
   is only ever paused for an hour. A site behind a proxy or Cloudflare must name
   it in the settings, or every visitor looks like the same address.
 * **The hidden sign-in page** hides the page. It is not a lock. Anyone who learns
   the address can still try, and the lockout and phone code still apply.
 * **The scanner block** only sees requests that reach WordPress. Your web server
   may answer some of them first. The web server lines and Cloudflare rules cover
   those.
 * **A code by email** is weaker than the phone app. Whoever has both the password
   and the email account gets in.
 * **Cloudflare’s free plan** allows five custom rules and one rate limit rule. 
   The DoctorX rules use two or three and the rate limit.
 * **The web server lines** are text for a person to put in place. The plugin cannot
   check that they were.

### Will the block editor or the mobile app still work?

The block editor, yes. People who work on the site, and apps that sign in as them
with an application password, still get the full list of what the site can do. A
signed-in customer or subscriber gets the answer without the list, like a visitor.
The list of user accounts stays readable to anybody who is signed in, as WordPress
has it. Only visitors lose it.

One thing changes for apps. An app that signs in with the ordinary password of an
account that has two-step sign-in on is refused: give it an application password
instead (see “What about apps and services that sign in with my password?” below).

### My theme shows author names under each post. Do they disappear?

No. The author’s display name still shows. Only the link behind it now points to
the home page instead of an author page.

### I use an SEO plugin that makes its own author sitemap.

This plugin only removes authors from WordPress’s built-in sitemap. Turn off author
sitemaps in your SEO plugin too.

### Something on my site stopped finding its way after I updated.

A few outside apps, and scripts in some themes, read the list at /wp-json/ without
signing in, to find out what the site offers. Untick “Hide the list of what your
site can do from visitors” and it is as before. A developer can instead keep one
part of the list open with the `doctorx_hardening_open_rest_namespaces` filter.

### Which authenticator app do I need?

Any app that makes six-digit sign-in codes that change every 30 seconds. Your phone’s
app shop has several free ones, and most password managers do it too. Nothing has
to be bought and no account has to be opened anywhere.

### I lost my phone. How do I get in?

Type one of your backup codes where the sign-in page asks for the six-digit code.
Each works once. Then switch two-step sign-in off under Users (or Profile)  Two-
step sign-in, with another backup code, and set it up again on the new phone.

### I lost my phone and my backup codes.

Somebody who may edit your account (on most sites, another administrator) can switch
two-step sign-in off for you: Users, your name, “Switch it off for this account”.
An email about it goes to your address.

If you are the only administrator, add this line to wp-config.php, above the line
that says “That’s all, stop editing” (your web host can do this for you):

    ```
    define( 'DOCTORX_HARDENING_NO_TWO_STEP', true );
    ```

Nobody is asked for a code while the line is there, on any account: every account
opens with its password alone. So do it only when nobody else can know your password
or the password of any other account that can change the site (if in doubt, have
new passwords set first), and for as short a time as you can. Somebody who signs
in while the line is there stays signed in after it is taken out, until they sign
out or their password is changed. Sign in, open Users  Two-step sign-in, and press“
Switch two-step sign-in off”: while the line is there, that button asks for no code.
Set it up again with your new phone, and take the line out.

### It says “too many wrong sign-in codes”, and it was not me.

Then somebody typed your password correctly and guessed at the code. The lock stopped
the guessing. Use “Lost your password?” on the sign-in page to set a new password:
that shuts them out and opens the lock, and you sign in with your new password and
a code as usual.

If the email with the link does not arrive, another administrator can set a new 
password for you on your profile (Users, your name), which opens the lock too. If
you are the only administrator, ask your web host to set a new password for your
account: hosts can do that without signing in to the site. The stranger is then 
out, and you sign in with the new password and a code (if the lock is still on, 
it opens at the time the page shows).

Do not add the wp-config.php line from the answer above while somebody else knows
your password. That line switches the second step off for every account, so the 
stranger would be signed in with the password alone. Change the password first. 
Use the line only for a lost phone.

If your site’s “Lost your password?” page belongs to a shop or membership plugin,
and your WordPress is a release from before November 2024, a password set there 
may not open the lock. It then opens at the time shown, or when the password is 
changed on the profile screen.

### Nobody’s codes work any more.

The codes depend on the time. If everybody’s codes fail at once, the clock of the
website’s server is probably wrong by more than half a minute: ask your web host
to check it. If only yours fail, check that your phone sets its clock automatically.

### Does two-step sign-in apply to everybody? Can I make it compulsory?

Each person switches it on for their own account. Settings  Hardening shows how 
many of the site’s administrators have it on. To make it compulsory for some roles,
from a date, use “Two-step sign-in required” on Settings  Hardening  Sign-in and
server.

### What about apps and services that sign in with my password?

An account with two-step sign-in can no longer be used with just its password by
a program (XML-RPC, a script, a sign-in box that works without loading a page): 
there would be nowhere to ask for the code. Give each app its own application password,
at the bottom of your profile (if there is no “Application Passwords” section there,
another plugin or your web host has switched them off). That is safer anyway: you
can take one app’s key away without changing your password.

### Our host changed the site’s “security keys” (salts), and now nobody’s codes work.

The key each app shares with the site is kept encrypted with your site’s security
keys. When those keys change (after a break-in, or because a host or plugin does
it on a schedule), the codes can no longer be checked. The plugin notices at the
next visit to the sign-in page and writes to everybody with two-step sign-in, and
the page that asks for the code says what happened. Settings  Hardening says for
thirty days what was done and whether everybody could be reached. (If the site’s
address or its folder changed at the same time, as on a copy of the site, nobody
is written to. The plugin keeps a mark of the place for this, not the address, so
that a copy made by replacing the address throughout the database is still told 
from the site itself.) Sign in with a backup code, then set it up again or switch
it off with another backup code: either takes two minutes. Backup codes are not 
affected by the change.

If a host or a plugin changes the keys on a schedule, this happens every time. Ask
them to stop, or two-step sign-in is not practical on that site.

### Where is the security.txt file, and why can I not see it?

At /.well-known/security.txt on your domain, which is where the standard puts it.
It is served only when the site is on HTTPS and lives at the top of its domain, 
when a contact is set, and while its date is good. Some web servers refuse every
address with “/.” in it before WordPress is asked. The “Check that visitors can 
read it” button on the settings screen tells you, and your host can let that one
address through. If a file of that name already lies on the server, it wins: the
button tells you that too.

### Why does the security.txt file run out?

The standard requires a date, so that nobody reports a problem to an address that
stopped being read years ago. A contact you give or change is good for 360 days.
You get an email and a notice on Settings  Hardening 30 days before the end. Pressing
Save on the settings screen then confirms the contact for another 360 days. If you
do nothing, the file is taken down on that date and comes back the moment you press
Save.

### I am paused by the password-guess lockout on my own site.

Wait until the time the sign-in page shows, or sign in from another network (a phone
without Wi-Fi): only the address is paused, not your account. Or have your web host(
or anyone with access to the server) do one of these:

 * run `wp doctorx-hardening unlock --all` (or `unlock YOUR_ADDRESS`), or `wp doctorx-
   hardening guard off`
 * add `define( 'DOCTORX_HARDENING_NO_LOCKOUT', true );` to wp-config.php, above“
   That’s all, stop editing”. Nobody is paused or counted while it is there, and
   Settings  Hardening reminds you to take it out.

Add your office and home addresses to the trusted list so this cannot happen there.

### My own address was banned by the probe ban.

Sign in from another network (a phone without Wi-Fi) and lift the ban on Settings
Hardening  Sign-in and server, or run `wp doctorx-hardening unban --all` (or `wp
doctorx-hardening unlock ADDRESS`, which lifts a sign-in pause and a ban of that
address) on the server, or add `define( 'DOCTORX_HARDENING_NO_PROBE_BAN', true );`
to wp-config.php: nobody is banned or counted while it is there.

### I lost the address of the hidden sign-in door.

It was emailed to the site’s administration address when it was set. Otherwise run`
wp doctorx-hardening door` on the server to see it, `wp doctorx-hardening door off`
to switch the door off, or add `define( 'DOCTORX_HARDENING_NO_DOOR', true );` to
wp-config.php: wp-login.php answers again at once.

### Will any of this hurt my search ranking or AI assistants?

No part of it changes what visitors, search engines or AI assistants read on your
pages. The probe ban does not count a crawler. The Cloudflare rules leave every 
crawler Cloudflare verifies alone. The server lines do not name a crawler to turn
away. “Hide the WordPress version” changes a few characters in the addresses of 
WordPress’s own script files, nothing that is read.

### What happens when I delete the plugin?

Its settings are removed (on a multisite network, on every site). So are the sign-
in guard’s settings, the paused and banned addresses and the sealed Cloudflare token.
The rules already at Cloudflare stay there: remove them with Undo first if you want
them gone. Everything kept for two-step sign-in on every account is removed too,
and so is the activity record with its events. (Simple History’s own tables, if 
you still have them, are left alone.) Signing in then takes only the password again.
Deactivating without deleting keeps everything for when you switch it back on. While
it is deactivated nobody is asked for a code, and when it is deactivated on the 
Plugins screen everybody who had two-step sign-in is told by email.

### What does the activity record keep, and for how long?

Each event says what happened, when, who did it (a signed-in person, an anonymous
visitor, WordPress itself, or WP-CLI), the address the request came from, the browser’s
name, and the details of what changed (a post’s title before and after, a plugin’s
version before and after). Addresses are kept without their last part unless you
choose to keep them whole. Events are removed after the number of days you choose(
60 unless you change it), once a day, and the removal is itself recorded. Administrators
read everything. Editors read the events about what they can change themselves. 
Addresses are shown to administrators only.

### I used Simple History. Do I lose its log?

No. Switch the activity record on, then press “Bring in Simple History’s events”
on Settings  Hardening (or run “wp doctorx-hardening activity import”). Every event
comes over with its date, address, details and who did it. Pressing it again brings
in only what is new. Simple History’s own tables are not changed, so switching back
is reactivating it. Code written for Simple History (“do_action( ‘simple_history_log’,…)”)
keeps being recorded once Simple History is gone.

### Can it tell me when something happens?

Yes. On the activity record’s “More settings” screen, add a destination: an email
address, a Slack, Discord or Microsoft Teams webhook, a Telegram bot, or any webhook.
Then add a rule. It can be a ready one (security, content, updates, failed sign-
ins, plugins installed, somebody made an administrator) or your own (kinds of events,
the lowest level, who did it, words). “Alert me about events like these” on the 
record makes a rule from what you searched. Each rule sends at most the number of
alerts an hour you set, and a run of failed sign-ins alerts at the 1st, 10th, 100th
attempt. Nothing is sent until you switch alerts on.

### Can it send the record to our log service?

Yes: syslog (this server’s, or another over UDP, TCP or TLS), Datadog, Splunk or
any webhook. Keys, tokens and passwords are kept sealed and are not shown again.
Events are sent once the page has answered, at most 50 a request. What a request
cannot send (more events, a destination that is down) waits, and is sent in order
by a scheduled job that exists only while forwarding is on and something waits. 
At most 5,000 events wait for each destination. Past that the oldest are dropped,
and the screen, `wp doctorx-hardening activity forward list` and the activity record
say how many. Events made by backfill are not forwarded. Events dated in the past
by hand also wait their turn (at most 500 a destination).

Delivery is “at least once”: after a failure half-way an event can arrive twice.
So every event carries a delivery id that a receiver can use to drop repeats. It
is the “uid”: your site, the event’s number and its count. Webhooks also get it 
in the X-DRX-Event-Id header. Destinations on this server itself or on link-local
addresses (such as a cloud metadata service) are refused. A destination’s name is
looked up once and the connection goes to the address that was checked. A name that
cannot be found is not sent to. TLS certificates are checked, for syslog over TLS
and for the database with TLS, against the certificates WordPress trusts. Code can
name your own CA file with the filter doctorx_hardening_activity_ca_file. A website
set up not to send (the line `define( 'DOCTORX_HARDENING_MAY_CONNECT', false );`
in wp-config.php) sends no alert, forwards nothing and looks nothing up.

### Does it look up where an address is?

Only if you choose how. It can use a database file on your server (MaxMind GeoLite2,
DB-IP Lite or IPinfo’s .mmdb), and then nothing leaves the server. Or it can use
ipinfo.io with your own token, and then only when an administrator opens an address(
not on a website set up not to send). Out of the box nothing is looked up.

### Does the activity record slow the site down?

Not for visitors: nothing of it runs on a page view. A failed sign-in costs one 
database write. A run of them from one address is counted on one line.

### Privacy: what does it keep about people, and where does it go?

 * For each account with two-step sign-in the plugin keeps, in your own database:
    - the key shared with the authenticator app (encrypted)
    - hashes of the backup codes
    - the day it was switched on, and which code was used last
    - the times of recent wrong codes (those older than a day are removed the next
      time a code is typed for the account)
    - when the account was last warned by email.
 * While somebody sets it up, the new key is kept (encrypted) until they finish 
   or cancel. New backup codes are kept (encrypted) for up to ten minutes, until
   the screen has shown them once. A sign-in that is waiting for its code can be
   used for ten minutes, and keeps the address the person was on their way to. WordPress
   clears the stored note away later, with its other short-lived notes. After a 
   change of the site’s security keys, the names of up to twenty people who could
   not be told by email are kept for the settings screen, which shows them for thirty
   days. They are removed at the first visit to the sign-in page after those thirty
   days.
 * It emails the account’s own address when two-step sign-in is switched on or off
   for the account, when a backup code is used, when a wrong code is typed after
   the right password (once a day at most), when wrong codes lock the second step,
   when the site’s security keys were changed, and when two-step sign-in stops for
   the whole site.
 * The contact you give for security.txt is published in that file for anybody to
   read. Use an address meant for that.
 * The activity record (when you switch it on) keeps, in your own database, what
   is described under “What does the activity record keep” above, for the number
   of days you choose. It adds a paragraph about itself to the suggested text of
   your privacy policy (Settings  Privacy). It takes part in WordPress’s “Export
   Personal Data” and “Erase Personal Data” tools: erasing takes the person’s name,
   address and browser out of their events. Notes a person wrote on events, and 
   notes or entries added by hand that name their email address, are in their export.
   Erasing takes them off as the notes’ writer and takes the address out of those
   words, and leaves other people’s events their own details. The weekly email (
   if you switch it on) goes to the addresses you give. The feed (if you switch 
   it on) is readable by whoever has its secret. Alerts and forwarding (if you switch
   them on and set a destination up) send events, with the person’s name and address,
   to the services you choose. The suggested privacy text then names them. Looking
   up where an address is sends it to ipinfo.io only if you choose that and only
   when an administrator opens it.
 * Nothing is sent to DoctorX.ca or to anybody else. “Check that visitors can read
   it” makes your site fetch its own file.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“DoctorX Hardening” is open source software. The following people have contributed
to this plugin.

Contributors

 *   [ xaviercode ](https://profiles.wordpress.org/xaviercode/)

[Translate “DoctorX Hardening” into your language.](https://translate.wordpress.org/projects/wp-plugins/doctorx-hardening)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/doctorx-hardening/),
check out the [SVN repository](https://plugins.svn.wordpress.org/doctorx-hardening/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/doctorx-hardening/)
by [RSS](https://plugins.trac.wordpress.org/log/doctorx-hardening/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 0.7.5

 * Security: the activity record keeps an event that comes from a form (the file
   editor, settings screens, signing out everywhere, a new account and others) only
   after that form’s own security check and the person’s rights are confirmed.
 * Fix: when two site self-checks start at the same moment, only one of them runs.
 * Behind a proxy: once the proxy addresses are listed, the other DoctorX plugins
   on this site read the visitor’s address the same way, and the screen says so.
 * Fix: the activity record’s More settings and a new feed secret are kept again.
 * Fix: trusted addresses are left out of every Cloudflare rule, of the nginx lines
   and of the ban list sent to Cloudflare, as the guard does. A trusted range written
   as ::ffff: with a short prefix no longer holds every IPv4 address.
 * Fix: Cloudflare’s own addresses are spared from pauses and bans only on a site
   behind Cloudflare.
 * Fix: alerts to Discord and Teams show typed names as plain words.
 * A signed-in person’s admin-ajax and REST requests sent from another website are
   refused. A request that names no website, a link followed from another website
   and an application password go on as before.
 * The activity feed’s secret is now sent in a header (the feed reader’s password),
   not in the address, because addresses are written to server logs. The old secret
   is replaced once.

#### 0.7.1

 * Fix: a sign-in waiting for its code is kept in the database with its own end 
   time. On a site with an object cache, a cache flush in the middle of signing 
   in no longer sends the person back to the sign-in page. The same ten minutes,
   one use and lock after five wrong codes apply.
 * Fix: the backup codes shown once, the note after an administrator switches two-
   step sign-in off for someone, the Cloudflare preview waiting for Apply and the
   notes shown after a button are kept the same way.
 * On a multisite network, a note or a Cloudflare preview waiting for Apply stays
   on the site it was made on.
 * New: a daily self-check. Each private folder under uploads gets a small probe
   file that is fetched without a cookie and deleted at once. If a visitor can read
   it, the Sign-in and server tab names the folder with the nginx and Apache lines
   that close it.
 * New: the same check fetches a private probe once with a one-time cookie and once
   without. If the answer without the cookie is the private one, or a cache hit,
   the tab says your proxy or CDN caches by address alone. With a Cloudflare token
   it also lists the zone’s cache rules that make answers cacheable (read only).
 * The check only reads. It never changes the web server or Cloudflare. A site that
   cannot reach its own address skips it, and the tab says so once. A “Check now”
   button runs it at once.
 * After the update, a sign-in that was already waiting for its code ends. The person
   signs in again.

#### 0.6.9

 * Fix: on a server that gives IPv4 addresses in IPv6 form (::ffff:203.0.113.9),
   each visitor is counted on their own. One visitor’s failed sign-ins no longer
   pause everyone, and the trusted list and private addresses match.
 * Fix: behind a proxy that adds the port to X-Forwarded-For (203.0.113.9:51234),
   the guard reads the proxy’s entry. A visitor can no longer choose the address
   the guard counts.
 * Fix: when a proxy writes something in X-Forwarded-For that is not an address,
   the guard counts the proxy’s own address, not what the visitor wrote before it.
 * Fix: the activity record notes changes made in Redirection when the web address
   uses capital letters.
 * Fix: the activity record keeps IPv4 addresses given in IPv6 form as IPv4, and
   a forwarded address with a port, as the guard reads them. The trusted list, the
   proxies list and lifting a pause read every way of writing such an address.

#### 0.6.8

 * First release on WordPress.org. Needs WordPress 6.2 or later.
 * Hidden user list and route list, author pages kept private, no guessed pages 
   for language-style addresses.
 * Two-step sign-in with an authenticator app and backup codes.
 * security.txt with its expiry date and reminders.
 * Sign-in and server protections, each off until you switch it on: password-guess
   lockout, one message for wrong names and passwords, small doors shut, two-step
   sign-in required for chosen roles, a code by email, a hidden sign-in door, a 
   probe ban, Cloudflare edge rules with your own token, and lines for your web 
   server.
 * Activity record (off until you switch it on) under Tools  Activity, with filters,
   downloads, insights, a weekly email, Simple History import and WP-CLI commands.
   Alerts, forwarding, core file checks and address lookups are each off until you
   switch them on.

## Meta

 *  Version **0.7.5**
 *  Last updated **2 days ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.2 or higher **
 *  Tested up to **7.1.4**
 *  PHP version ** 7.4 or higher **
 * Tags
 * [Activity Log](https://wordpress.org/plugins/tags/activity-log/)[security](https://wordpress.org/plugins/tags/security/)
   [security.txt](https://wordpress.org/plugins/tags/security-txt/)[two factor authentication](https://wordpress.org/plugins/tags/two-factor-authentication/)
   [user enumeration](https://wordpress.org/plugins/tags/user-enumeration/)
 *  [Advanced View](https://wordpress.org/plugins/doctorx-hardening/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/doctorx-hardening/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/doctorx-hardening/reviews/)

## Contributors

 *   [ xaviercode ](https://profiles.wordpress.org/xaviercode/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/doctorx-hardening/)