Title: ATV Web Security
Author: atvsoftwarelabs
Published: <strong>October 21, 2026</strong>
Last modified: October 22, 2026

---

Search plugins

![](https://ps.w.org/atv-web-security/assets/banner-772x250.png?rev=3757882)

![](https://ps.w.org/atv-web-security/assets/icon-256x256.png?rev=3757882)

# ATV Web Security

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

[Download](https://downloads.wordpress.org/plugin/atv-web-security.1.0.38.zip)

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

 [Support](https://wordpress.org/support/plugin/atv-web-security/)

## Description

ATV Web Security puts your WordPress website into a “protected” state where visitors
can still read and use the site, but nothing can persist changes to it — not plugins,
not compromised administrators, not direct database access, and not a PHP shell.

How it works — multiple independent layers:

 * WordPress protection — plugin/theme/core operations, file editors, user creation,
   option writes and administrator actions are intercepted and denied.
 * Database protection — the database account’s write privileges are REVOKED at 
   the MySQL/MariaDB server level using a separate privileged MySQL account (allowed
   flows are re-granted only row-level INSERT/UPDATE/DELETE), so even direct SQL
   from arbitrary code is refused. The site account’s own GRANT authority is never
   consumed, because revoking it would permanently destroy the restore path. An 
   application-layer SQL firewall blocks write queries even when privileges cannot
   be changed.
 * Filesystem protection — write bits are stripped from wp-admin, wp-includes, plugins,
   themes, mu-plugins, the plugin itself and critical config files. Original permissions
   are snapshotted and restored on disable.
 * Upload protection — executable uploads are blocked by extension, MIME and content;
   the uploads directory is hardened so scripts cannot execute there.
 * API protection — REST, AJAX, XML-RPC, WP-CLI and cron-based mutation is blocked.
   Reads remain available.
 * Integration with the PHP firewall — traffic under wp-includes is rejected by 
   a small mu-plugin, links to private files are blocked, and low-level PHP tricks
   are neutralised.
 * Integrity monitoring — baseline hashes of core, configuration and plugin files
   are verified periodically.
 * Access rules (optional) — AbuseIPDB-powered website access block by IP reputation
   score and a login country rule that only allows the admin login page from a country
   you select. Both are off by default, respect an IP/CIDR allowlist, fail open 
   on lookup errors and cache results to stay within API rate limits.
 * Backend lock — the plugin lives in its own top-level admin menu; once protection
   is ON and a master password is set, the settings page stays hidden behind a lock
   screen until that password is entered (12-hour unlock, forged-cookie safe, brute-
   force rate limited). The master password accepts 8-64 letters, digits and symbols,
   and is the single password accepted to turn protection OFF (older 12-digit passwords
   keep working).
 * Email verification code (Two-Factor, optional) — administrators can be asked 
   for a six-digit code sent to their email address in addition to their WordPress
   password. The code field appears on the login form itself, right after the password
   is accepted, so the whole flow stays on one screen with no page refresh. Codes
   are valid for 10 minutes, can be resent once a minute (five codes per quarter
   hour), and the account locks for 15 minutes after five wrong entries. If the 
   mailer cannot deliver, the login stays blocked on purpose — recovery is a single
   command from the shell: wp atvws otp disable.
 * Passkeys / WebAuthn (optional, recommended for “only my device”) — registers 
   a hardware-backed credential with Windows Hello / TPM, Touch ID, a phone or a
   security key. The private key is created and used inside the device and never
   reaches the website, a cookie, JavaScript or a backup. With enforcement on, protected
   administrator logins are accepted only from a device whose passkey verifies; 
   an account with no passkey is never blocked, and recovery stays available. An
   account covered by a registered passkey skips the emailed code — either factor
   alone satisfies the login.
 * Trusted device lock (optional) — the portable fallback for browsers without WebAuthn.
   Binds protected actions to one computer with a one-time token in a secure HttpOnly,
   SameSite cookie. Any other computer gets a “link your device” screen that requires
   the master password, and linking/unlinking always requires it. The Recovery tab
   stays reachable so a lost device can never lock the owner out permanently. A 
   verified passkey also satisfies this gate.
 * Behavior policy (optional) — studies privileged activity and locks the session
   instantly when the risk score crosses a threshold: failed unlock (15), failed
   disable attempt (25), failed restore attempt (20), failed login (20), refused
   passkey login (10). Scores are windowed per source IP for 24 hours; the owner(
   a linked-device or verified passkey session, or an allowlisted IP) is never scored
   and can clear a lock with the master password.
 * Cryptomining defence — four independent layers: every rendered page is checked
   before it leaves PHP and script tags naming known mining services or pools are
   removed; WordPress’s own HTTP API is refused for pool domains; a time-sliced 
   filesystem scan walks wp-content and reports native executables and miner configuration
   markers; and a database scan searches posts and options for injected script blocks.
   The scans are report-only and surface on the Miners tab — nothing is quarantined
   by a heuristic match.
 * Detection & monitoring — a signed baseline of every script and stylesheet the
   login page loads, with a report the moment a new address appears (login page 
   watch); a scheduled self-probe that asks the site for risky paths (backups, dumps,
   dotfiles, debug logs) and flags anything the web server would hand to anyone (
   sensitive file probe); honeypot decoy paths and hidden form fields that trigger
   escalating, temporary bans for automated scanners; and a local vulnerability 
   inventory that flags plugins and themes that are outdated, abandoned (no release
   for 2+ years) or no longer listed in the wordpress.org API — computed locally,
   without phoning home.
 * Snapshot backup and restore — a signed copy of every file WordPress can change(
   core, plugins, themes, uploads, wp-config.php) plus a complete database dump.
   A snapshot is captured automatically the first time protection is enabled; that“
   current” snapshot is what the documented manual recovery procedure uses. You 
   can also keep as many named snapshots as you like (for example before a plugin
   or theme update) plus one automatic snapshot every day, each independently verifiable,
   restorable and deletable from the Snapshot tab or WP-CLI. There is no retention
   limit and nothing is ever deleted automatically — snapshots stay until you delete
   them yourself.
 * Live progress — snapshot create, snapshot restore and integrity scans show a 
   progress bar the moment you press the button, then fill in with stage, items 
   processed and percentage while the operation runs.
 * Total protection score — one honest number out of 100, shown on the Dashboard
   and in the header badge on every screen. Each security setting is worth a fixed
   number of points and only earns them once it is verified active, so the score
   drops the moment a layer stops working. The Dashboard lists every setting that
   is still pending, how many points it is worth, and which tab fixes it.
 * Setup tour — the first time you open the plugin, a guided walkthrough takes you
   through the tabs in order: Diagnostics, Set protection level, Snapshot, then 
   the rest of the configuration screens.
 * Clear layout — every screen is grouped into Everyday, Configure, Check and Incident,
   with a live protection badge, plain-language explanations of what each button
   does, and destructive actions visually separated from safe ones.
 * Recoverable — a forgotten master password no longer locks you out of the settings.
   Reset it from the plugin’s runtime directory in uploads with cPanel/FTP (create
   emergency-reset.key, then open emergency-reset.php), or from the shell with wp
   atvws password reset. Both routes sign out every session and are logged. WordPress
   account passwords can only be reset from WP-CLI. Email-code settings can be switched
   off from the shell with wp atvws otp disable.

Protection tiers:

 * MEDIUM — every PHP-level layer: WordPress, REST, AJAX, XML-RPC, upload, PHP shielding,
   integrity and CLI, plus the SQL firewall. Database grants and file permissions
   are left untouched, so it cannot lock you out of your own files and it runs on
   any host.
 * STRONG — everything in Medium, plus the database account loses its write grants
   AND the protected files are made read-only. Both must verify active.
 * HARD — everything in Strong, plus file changes are checked every hour instead
   of every six, and the tier does not count as fully in place until a verified 
   file baseline is stored.
 * LIMITED — protection is on but a core layer is switched off or did not verify
   after activation; the dashboard table shows which one before you rely on it.

Strong and Hard require a separate privileged MySQL account (the wizard or the ATVWS_DB_ADMIN_*
constants); without it those cards are shown as unavailable rather than silently
downgraded, and the site’s own GRANT authority is never consumed.

Choosing or changing a tier requires the master password, so a hijacked admin session
cannot quietly weaken the site. Every layer also has its own switch for fine-tuning
a tier; picking a new tier resets those switches. The old names STANDARD, AUTO and
HARDENED still work and map to Medium and Strong.

Allowed writes:

Persistent visitor flows (comments, contact forms, WooCommerce, user registration)
are BLOCKED by default. The owner re-enables only what the site genuinely needs 
from the “Allowed Writes” page. Everything else stays blocked.

Turning protection OFF is deliberately difficult (a strong request): you must submit
a form, confirm a checkbox, type the exact phrase, and re-enter your account password(
plus an optional passphrase). Emergency recovery paths (WP-CLI, a wp-config constant,
a recovery file, or manual panel instructions) are documented to make sure you can
always regain write access — see docs/RECOVERY.md.

### External services

This plugin can connect to the AbuseIPDB API. This is optional and off by default;
it is used only for the IP intelligence features (the site-wide IP reputation block
and the login country check), and only when you switch those features on.

What the service is and what it is used for:

 * AbuseIPDB provides an IP reputation and geolocation look-up. The plugin sends
   an IP address to AbuseIPDB to learn whether that address has been reported for
   abusive behaviour (a reputation score) and which country it is in, so the plugin
   can block abusive visitors or restrict administrator logins by country. No result
   is required for the site to work: if the lookup fails, the request is allowed(
   fail-open) and the failure is logged.

What data is sent and when:

 * The visitor’s IP address is sent to AbuseIPDB only at the moment a protected 
   request is checked by one of the IP intelligence features above, together with
   your own AbuseIPDB API key (in the request header) needed to authenticate the
   lookup.
 * No other data is sent. No personal data, no site content, no account information
   and no usage statistics leave the site. Requests are rate-limited, cached, and
   only made while the feature is enabled.

This service is provided by “AbuseIPDB LLC”. Terms of use, privacy policy.

 * Terms of use: https://www.abuseipdb.com/legal
 * Privacy policy: https://www.abuseipdb.com/privacy

## Installation

 1. Upload the `atv-web-security` folder to `/wp-content/plugins/`.
 2. Activate the plugin through the Plugins screen.
 3. Under the new top-level “ATV Web Security” admin menu, follow the setup tour: review
    the Diagnostics tab, then click “Turn ON Protection”.
 4. Store the recovery token that is displayed once.
 5. Configure “Allowed Writes”, “Protected Admins” and “Two-Factor” to match your site.

More detail: docs/INSTALL.md and docs/CONFIGURATION.md.

## FAQ

### Can visitors still read the site?

Yes. The site remains fully readable and functional for browsing. Only persistent
changes are blocked.

### What happens while protection is ON?

Users (including administrators) can browse, read and perform allowed writes. Plugin,
theme, core updates, file and database changes that are not explicitly allowlisted
are blocked. Turn protection OFF to build, update or modify anything.

### How do I turn protection OFF?

Use the Dashboard tab and follow the strong-disable form, or use one of the emergency
recovery methods described in docs/RECOVERY.md.

### Which password is accepted to turn protection OFF?

The master password (8-64 letters, digits and symbols) is accepted, and so is your
WordPress account password as a fallback — so a site that never configured a master
password is never locked out.

### How does the emailed verification code work?

When enabled, administrators are asked for a six-digit code sent to their email 
address after their password is accepted. The code field appears on the login form
itself, so no page refresh is needed and every step stays on one screen. A code 
is valid for 10 minutes, can be resent once a minute (five codes per quarter hour),
and the account locks for 15 minutes after five wrong entries.

### What if I cannot receive the emailed code?

The login stays blocked on purpose rather than silently downgrading to password-
only. Recover from the shell with wp atvws otp disable (or re-enter the master password
on an already-unlocked session).

### Passkey or email code — which do I need?

Either factor alone satisfies the check. An account covered by a registered passkey
skips the emailed code, and the passkey is hardware-bound so it survives cookie 
clearing and cannot be copied. Use the two-factor email code when a browser cannot
do WebAuthn.

### Do I need a passkey, or is the device token enough?

The device token is bound to the browser profile: clearing cookies or switching 
browsers unlinks it, and a copied cookie could be replayed. A passkey is bound to
the device’s secure hardware, so it survives cookie clearing and cannot be copied.
If you can only pick one, pick the passkey; keep the token as the fallback for browsers
that cannot do WebAuthn. Enforcement is off until you turn it on, and no account
is ever blocked without a registered passkey.

### What does the Miners tab do?

It reports cryptomining findings without touching anything: script tags naming mining
services or pools are removed from rendered pages, WordPress’s HTTP API is refused
for pool domains, a filesystem scan flags native executables and miner configuration
markers, and a database scan looks for injected script blocks. Every result is surfaced
on the Miners tab for you to review and act on.

### How does the vulnerability checker decide what is abandoned?

It measures locally, with no third-party call: a release older than two years is
flagged as unmaintained, a plugin or theme still on disk but no longer listed in
the wordpress.org API is flagged as closed, and the local modification time of the
plugin directory cross-checks both. An online feed lookup exists but is opt-in and
requires your own API key — nothing phones home about the site by default.

### Is my database really read-only?

On Strong and Hard Protection a separate privileged MySQL account revokes the database
account’s write privileges and the result is verified. On Medium Protection the 
SQL firewall blocks write queries from PHP instead. Details in docs/INSTALL.md and
docs/SECURITY_LIMITATIONS.md.

### What about caching plugins?

Cache plugins are confined to an explicit allowlist of cache directories; other 
paths stay read-only. See diagnostics for the ongoing compatibility status.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“ATV Web Security” is open source software. The following people have contributed
to this plugin.

Contributors

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

[Translate “ATV Web Security” into your language.](https://translate.wordpress.org/projects/wp-plugins/atv-web-security)

### Interested in development?

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

## Changelog

#### 1.0.37

 * Maintenance release addressing WordPress.org plugin review feedback. No feature
   or behaviour changes.
 * Admin stylesheet is now loaded with wp_enqueue_style instead of a printed raw
   style block.
 * Theme and plugin headers are read with get_file_data() instead of file_get_contents().
 * The AbuseIPDB external service is now documented, with links to its terms and
   privacy policy.
 * Runtime, state and recovery paths now use wp_upload_dir() and WPMU_PLUGIN_DIR
   for custom and multisite layouts.
 * Removed the global automatic-update filters; automatic updates are left to WordPress.
 * Removed the automatic mu-plugin installer; the optional MU bootstrap is a manual
   copy.
 * The miner-guard output buffer is now always closed.
 * The top-level admin menu is placed lower (position 100).
 * Remaining request inputs are sanitised and validated; output is escaped.

#### 1.0.36

 * Email verification code now appears as an inline field on the login form — no
   page refresh, the whole two-factor flow stays on one screen.
 * Resend is throttled to once a minute and five codes per quarter hour; a failed
   delivery keeps the login blocked on purpose so the mailer cannot fail open.
 * Codes are probed in the background on submit, with a clear error on the form 
   when the code is wrong.

#### 1.0.35

 * Added email verification codes (Two-Factor): administrators can be required to
   enter a six-digit code emailed to them after the account password. Passkey-covered
   accounts skip the code — either factor alone satisfies the login.

#### 1.0.34

 * Allowed writes now defer to the SQL firewall’s enforced rule server-side, so 
   a server-level write block is verified against the same rule that actually runs.

#### 1.0.0

 * Initial release.

## Meta

 *  Version **1.0.38**
 *  Last updated **16 hours ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.0 or higher **
 *  Tested up to **7.1.3**
 *  PHP version ** 8.0 or higher **
 * Tags
 * [lockdown](https://wordpress.org/plugins/tags/lockdown/)[malware](https://wordpress.org/plugins/tags/malware/)
   [protection](https://wordpress.org/plugins/tags/protection/)[security](https://wordpress.org/plugins/tags/security/)
   [two factor](https://wordpress.org/plugins/tags/two-factor/)
 *  [Advanced View](https://wordpress.org/plugins/atv-web-security/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/atv-web-security/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/atv-web-security/reviews/)

## Contributors

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

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/atv-web-security/)

## Donate

Would you like to support the advancement of this plugin?

 [ Donate to this plugin ](https://shop.atvsoftwarelabs.com/product/support-us/)