Shield SysWP Shield
Documentation

SysWP Shield documentation

Everything you need to install, configure, and get the most out of the plugin. Updated on every release.

🚀 Getting Started

Installation

Download syswp-shield.zip from shield.syswp.pro/plugin. In your WordPress admin, go to Plugins → Add New → Upload Plugin, choose the zip, install, and activate. After activation you will see an admin notice prompting you to connect a free SysWP account — protection only starts running after the connection is completed. See the next section for the connect flow.

Connect (free SaaS account)

SysWP Shield is the WordPress client for the SysWP threat-intelligence network, so an active connection is required for the firewall pipeline to run. Account creation is free, takes ~30 seconds, no credit card.

Step-by-step:

  1. Go to Shield → Settings → Connection in your wp-admin.
  2. Click "Connect to SysWP Shield (free)". Your browser opens shield.syswp.pro.
  3. Sign in (or sign up — same flow). The SaaS shows you a consent screen with the site URL it is about to link.
  4. Click Confirm. The SaaS issues credentials, your WP site exchanges them server-to-server, you land back in wp-admin with "Protection ACTIVE".

The connect flow is OAuth-style — credentials never appear in URL bars or browser history. The plugin and the SaaS perform a one-time token exchange behind the scenes.

Free plan unlocks immediately on connect: cross-site network consensus, vulnerability digest, central dashboard, AI bot management. Premium adds multi-site management and longer log retention.

Requirements

  • WordPress 6.0 or newer (tested up to 7.0)
  • PHP 8.0+
  • Outbound HTTPS from the WP server (for heartbeat to the SaaS)
  • WP-Cron enabled OR a system cron hitting wp-cron.php

🏗 Architecture & Combinations

Why a plugin instead of a CDN/edge tool?

Honest answer: no single tool — plugin OR CDN — protects 100%. Real WordPress security is layered, and each layer does what the others can't:

  • CDN/edge layer (Cloudflare, Sucuri WAF, AWS Shield) — absorbs volumetric attacks (DDoS L3/L4, network floods) before they hit your server. Best at: bandwidth saturation, packet floods, geographic blocking.
  • Plugin layer (SysWP Shield) — does the smart work that lives inside WordPress: 16 behavioral signals, FCrDNS-verified bots, AI scraper classification, network consensus across sites, Wordfence vulnerability scanning. Best at: precise per-request decisions with full WordPress context.
  • Server layer (PHP-FPM timeouts, Apache/nginx config) — handles slowloris, connection-level abuse.
  • Operational layer (2FA, backups, plugin updates) — handles credential leaks, 0-days, social engineering.

Shield is intentionally a plugin — not a CDN replacement — because:

  • Install in 30 seconds: one-click upload, no DNS change, no risk of misconfiguration breaking the site.
  • Free tier viable: zero infrastructure cost per customer. A real CDN tier needs ~$10-50K/month in servers/peering — incompatible with free.
  • WordPress context: we read your installed plugins/themes/version, your custom rules, your user roles. A CDN sees raw HTTP traffic; we see what your site actually does.
  • Cross-site network: when one site in our network flags an attacker, every other site blocks them in minutes. This requires the plugin to be the source of truth for that site's state.

The right architecture: CDN + Shield together. Cloudflare's free WAF + our free tier covers ~95% of real-world WordPress attacks at zero cost. We never compete with your CDN — we complement it.

Combining Shield with Cloudflare

Cloudflare's free tier + Shield's free tier is the most cost-effective WordPress security stack you can build. Here's how to wire them together correctly:

1. Trust Cloudflare's real-IP headers. When CF is in front, every request reaches your server with CF's IP as REMOTE_ADDR and the visitor's real IP in CF-Connecting-IP. Shield reads this header automatically — but only if you enable the toggle:

Settings → Whitelist → "Trust Cloudflare automatically" → ON.

Without this, Shield would ban CF's edge IPs (because they'd show up as the source of every request) — that effectively kills your site for everyone.

2. Don't double-rate-limit. If you have a Cloudflare rate-limit rule that already throttles /wp-login.php, you can leave Shield's rate-limit rule active too — they're complementary. CF blocks the obvious volumetric brute-force; Shield catches the slow distributed brute-force that CF's threshold misses.

3. Let Shield use CF's country header. CF sets CF-IPCountry on every request. Shield uses it for: country-based firewall rules, the threat report's geographic dimension, and the auto-detect-language feature on the SaaS dashboard. No config needed — it just works.

4. CDN cache invalidation on block. When Shield blocks an IP, it sets Surrogate-Control: max-age=3600 and CDN-Cache-Control: max-age=3600 on the 403 response. Cloudflare reads these and caches the 403 — so the next 1,000 requests from the same blocked IP NEVER reach your server. Massive perf win during an attack.

5. What each layer handles:

  • CF: volumetric DDoS, basic bot challenge, geographic blocking, edge caching
  • Shield: 16-signal behavioral detection, AI scraper classification, network consensus, Wordfence vuln scanning, login audit, rescue mode, traffic mix donut
  • Both: rate limiting (CF for crude, Shield for surgical)

Result: a $0/month security stack that beats most $300/month enterprise solutions on the metrics that matter for WordPress sites.

What attacks does Shield stop?

Honest table — what we handle, what we don't, and who handles it instead:

Attack vectorShield handles?If not, who does?
Login brute-force (wp-login.php)✓ Yes — rate limiter (5/60s, 1h block)
XML-RPC abuse✓ Yes — rate limiter
Single-IP HTTP flood✓ Yes — high_velocity signal + escalation
Distributed credential stuffing✓ Yes — network consensus + coordinated_pattern
Content scraping flood✓ Yes — scraper_behavior signal
SQL injection / XSS attempts✓ Yes — exploit_patterns regex
Known plugin CVE exploitation✓ Yes — Wordfence vuln scan + admin notice
Volumetric DDoS (L3/L4 floods)✗ No — packets die in networkCloudflare / AWS Shield
Slowloris / slow-read✗ No — connection-levelApache/nginx (RequestReadTimeout)
DNS amplification / reflection✗ No — network layerYour hosting provider / CDN
Stolen SSH/FTP credentials✗ No — happens outside HTTP2FA, key rotation, fail2ban
WordPress core 0-day~ Partial — exploit_patterns may catch the payloadWordPress security team patch + your update discipline

Read this honestly: we cover the application-layer attacks that hit WordPress sites every day in the wild. We don't cover network-layer attacks (impossible from a plugin) or operational compromises (require human discipline + 2FA + backups). The path to "100% protection" is defense-in-depth, not any single tool.

🍩 Traffic Mix

The six categories

Every public request is classified into one of six buckets:

  • 🟢 Humans — real visitors (low bot score)
  • 🟪 Crawlers — Googlebot, Bingbot, Facebook, Apple, etc. — verified by FCrDNS
  • 🟣 AI scrapers — GPTBot, ClaudeBot, CCBot, Perplexity, Bytespider, +16 more
  • 🔵 SysWP — our own infrastructure scanners (SEO/sitemap/uptime)
  • 🟧 Bots — throttled scrapers (suspicious but not blocked)
  • 🟥 Attacks — blocked malicious traffic

Internal admin traffic (wp-cron, Gutenberg AJAX, your own logged-in admin polling) is excluded so the percentages reflect actual visitor traffic.

Where the donut appears

Three places, all reading the same data:

  • WordPress Shield → Dashboard — donut + 24h hourly stacked chart
  • SaaS /sites/:id — same donut, just for that site
  • SaaS /dashboard — donut aggregated across all your sites
  • SaaS /admin/dashboard (super-admin) — network-wide

🤖 AI Scrapers

The three purposes

AI bots aren't all alike. We split them into three families with independent toggles:

  • 🧠 Training — bots that scrape your content to train future LLMs (GPTBot, ClaudeBot, CCBot, Bytespider, Applebot-Extended, Meta-ExternalAgent, +9 more). Recommended ON for publishers, OFF for marketing sites.
  • 🔍 Search/Answer — bots that index your site for real-time AI answers (OAI-SearchBot, PerplexityBot, Amazonbot, YouBot). Recommended OFF — these drive AI-cited traffic back to you.
  • 👤 User-initiated — triggered when a real person pastes your URL into ChatGPT or Perplexity (ChatGPT-User, Perplexity-User, Claude-Web). Not recommended to block — that's blocking real users.

Where to manage AI policy

Two places, both work. Changes sync via heartbeat (push-mode: ~1s, poll-mode: ~2 min):

  • Inside WordPress: Shield → Bot Management → AI scrapers card
  • From the SaaS: /sites/:id → AI scrapers policy card (better for agencies managing multiple sites)

🛡 Vulnerability Scanner

How it works

The plugin sends your installed plugins, themes, and WordPress version with every heartbeat. The SaaS matches that stack against the Wordfence Intelligence CVE database (synced daily). When a known vulnerability affects your stack, the SaaS pushes the result back to the plugin — visible in Shield → Vulnerabilities.

How you're notified

  • Persistent admin notice on every wp-admin page when critical/high vulns are detected. Per-user dismissable but reappears when the count changes (a NEW vuln won't go silent because you dismissed yesterday's).
  • Weekly email digest every Monday — ONE email per account summarizing open vulns + new + resolved deltas across all your sites.

🆘 Rescue Mode

When you're locked out

Every install gets a unique 32-character rescue token. Visit https://yoursite.com/?syswp_rescue=<token> from any browser — your visiting IP gets whitelisted, blocks/hits/reputation cleared, and you can log in normally. Token rotates from Settings → Connection. Rate-limited 10/hour per IP. Audit-logged.

Important: rescue mode does NOT bypass authentication. It only unblocks the IP firewall layer — you still need valid credentials to log in.

🔄 Plugin ↔ SaaS Sync

Push vs Poll mode

The SaaS auto-detects which mode applies on first connect:

  • Push (preferred): SaaS calls your plugin's REST endpoint directly. Commands deliver in ~1 second. Requires your /wp-json/syswp-shield/v1/* endpoints to be reachable from our IP.
  • Poll (fallback): plugin pulls commands during heartbeats. Used when push detection fails (firewall blocking, intranet, security plugin interfering). Cadence: 2 min between heartbeats.

Low-traffic sites

WordPress's WP-Cron only fires when someone visits the site. On low-traffic sites this means the heartbeat can lag 30+ minutes. We solve this with a heartbeat keeper cron on the SaaS that pings push-mode sites silent more than 10 minutes — forcing an immediate heartbeat. No action required from you.

If your site is poll-mode (push detection failed), enable a real cron on your server pointing to wp-cron.php for guaranteed timing.

🔧 Troubleshooting

Connection fails

Settings → Connection shows the exact error reason. Common cases:

  • bad_signature: API secret was truncated during paste. Re-copy from /sites/:id and paste again.
  • clock_skew: server time is more than 5 minutes off. Sync with NTP.
  • missing_headers: a reverse proxy is stripping our X-* HMAC headers. Whitelist them.
  • http_500: server error on our side — check the trace_id in the error message and contact support.

I don't have SSH access

Every recovery flow we ship works through cPanel File Manager + phpMyAdmin. We never assume SSH. If you're ever locked out and the rescue token doesn't help, contact support — we have documented step-by-step paths for: deactivating the plugin via File Manager (rename the folder), clearing blocks via phpMyAdmin (truncate wp_shield_blocks), resetting 2FA (delete wp_usermeta entries with key like syswp_2fa_%).

Stack Health Audit

What it audits

Every heartbeat the plugin reports the operational state of your stack: WordPress version (running vs latest available), PHP version (and whether it's past EOL), web-server software, plugin update count, theme totals + inactive count, and WP_DEBUG_LOG status + log file size. Rendered as a card on /sites/:id under Stack health.

Why this matters for security: outdated plugins are the #1 attack vector for WordPress compromises (per Wordfence Intelligence). Outdated PHP means no security patches. Inactive themes are still updated by WP-Cron and remain exploitable. WP_DEBUG_LOG can leak credentials, paths, and SQL errors — accessible via direct URL on most hosts.

Risk Score integration

Stack hygiene contributes a new factor (0–25 pts) to the per-site Risk Score: WP outdated +5, PHP past EOL +10, plugin updates pending +1 each (cap 8), inactive themes +1 each (cap 5), WP_DEBUG_LOG enabled +5. The total is capped at 25 so this dimension can't solo-blow your score, but a chronically un-maintained site easily collects 15+ points here.

1-click cleanup actions (Starter+)

Delete inactive theme — pushes a delete_theme command that delegates to WP's core delete_theme() function (handles file removal safely + fires the right hooks). The plugin refuses to delete the active theme or its parent template defensively.

Disable WP_DEBUG_LOG — pushes a disable_debug_log command. Plugin reads wp-config.php, regex-replaces define('WP_DEBUG_LOG', true) with false, BACKS UP the file BEFORE writing, and runs php -l on the result. If the syntax check fails the backup is restored automatically. Refuses complex variants (ternary expressions etc.) so the user fixes them manually instead of risking a broken wp-config.

🛡 DDoS Protection Layers

Three layers — what we cover

DDoS happens at three different layers, each requiring a different defense:

  1. L3/L4 (network) — SYN floods, UDP floods, amplification. Tens of Gbps that saturate the pipe BEFORE PHP runs. Shield CANNOT defend at this layer, and no WordPress plugin can — by the time the packets reach PHP they've already overwhelmed the network. The only mitigation is a CDN/scrubbing edge in front of the origin.
  2. L7 (application) — HTTP floods. Many requests overwhelming PHP/MySQL. Shield protects here via rate limiting, behavioral bot detection, attack-mode auto-tightening, brute-force enforcement, and consensus-based IP blocking across the network. Pro+ adds Tor-exit detection and datacenter-origin scoring for distributed botnets.
  3. Application/account — credential stuffing, endpoint-specific abuse, slow-and-distributed attacks. Shield protects fully via the Login Tracker brute-force enforcer (≥5 fails/1h, ≥3 distinct usernames, ≥10 fails/24h), the 16-signal bot detector, and the cross-site consensus network.

The honest pitch: Shield covers L7 + application. For L3/L4 we recommend Cloudflare Free in front of your origin — see the next section.

Cloudflare Free + Shield (recommended setup)

Cloudflare Free covers unlimited L3/L4 DDoS for any size attack — yes, even 100 Gbps+ — at zero cost. Setup takes ~10 minutes:

  1. Create a Cloudflare Free account at cloudflare.com
  2. Add your site, follow Cloudflare's scan of your DNS records.
  3. Cloudflare gives you 2 nameservers — change them at your domain registrar (Namecheap, GoDaddy, etc.). Propagation: 1-24 hours.
  4. In Cloudflare → SSL/TLS → set to Full (strict if your origin has a valid cert) so Cloudflare and origin both encrypt.
  5. Cloudflare → Network → enable "WebSockets" if your site uses real-time features (chat, live feeds).
  6. Done. Your origin is now behind Cloudflare's edge.

Shield + Cloudflare compatibility:

  • Shield auto-detects the CF-Connecting-IP header and uses the visitor's real IP for blocking decisions (not Cloudflare's edge IP). Configured at first install via the Trusted Reverse Proxies setting.
  • Shield's rate limits + WAF rules run AT the origin AFTER Cloudflare's edge. Two layers of defense, not conflicting.
  • Cloudflare's "Bot Fight Mode" can over-block legitimate Googlebot — turn it OFF and let Shield's FCrDNS-verified bot detection handle bot policy. Or keep it ON if you don't care about SEO bots.

When to upgrade Cloudflare:

  • CF Pro ($25/mo) — adds image optimization, mobile redirects, and the "WAF" suite (rule-based filtering at edge). Useful if you want to filter common exploit patterns BEFORE they reach your origin.
  • CF Business ($250/mo) — adds advanced rate limiting, custom WAF rules, log push. Worth it for sites doing >$10K/mo in revenue where downtime is expensive.

For most Shield customers, CF Free is enough. We don't earn anything from this recommendation — just the right answer.

🔑 One-click Auto-login

How it works

Click "Login to wp-admin" on any /sites/:id page in the SaaS. The SaaS generates a 256-bit single-use token, pushes it to the plugin via HMAC-authenticated sync command, and then redirects your browser to /wp-json/syswp-shield/v1/autologin?token=XXX. The plugin validates the token, deletes the matching transient (single-use enforcement), sets WP auth cookies for the resolved user, and redirects to /wp-admin. Total elapsed: ~2 seconds on push-mode sites.

Security model

Two-factor by design: auto-login requires (1) a valid SaaS account session AND (2) the plugin installed on the target site. Compromising one is not enough.

Token security: 256 bits of entropy (32 random bytes hex-encoded), single-use enforcement via plugin transient delete-before-cookies, 5-minute TTL, IP logged on issue + use, tied to the specific SaaS user_id who initiated.

Audit trail: every auto-login is logged on both sides (SaaS + plugin) AND triggers an email notification to the SaaS account holder. Even if your SaaS account were ever compromised, you SEE the autologins happening and can react. Same pattern Stripe / GitHub / Gmail use for "new sign-in detected" alerts.

Push-mode requirement: requires push delivery (your server allows outbound HTTPS to the plugin REST endpoint). Poll-mode sites get a warning instead of a failed autologin.

🔐 Two-Factor Authentication

Enrollment (FREE for everyone)

Any user with a WordPress account can enroll voluntarily — no admin permission required, no paid tier needed. From /wp-admin/profile.php, scroll to the "Two-Factor Authentication" section and click "Enable Two-Factor Auth". The plugin generates a 160-bit secret + an otpauth:// URI, renders a QR code (server-side SVG, secret never leaves your browser), and waits for you to enter the first 6-digit code from your authenticator app. Compatible with Google Authenticator, 1Password, Authy, Bitwarden, FreeOTP, and any RFC 6238 client.

On successful first verification, the plugin commits the secret + generates 10 single-use recovery codes (8-character alphanumeric, ~41 bits each, total ~80 trillion combinations across all 10). The codes are shown ONCE in a yellow box — save them in your password manager NOW. Each code can be used one time to sign in if you lose your phone.

Login flow: after typing your password normally on /wp-login.php, the plugin renders an interstitial form asking for the 6-digit code. The form uses WordPress's native login layout (login_header() / login_footer()) so it matches your wp-login styling. Failed codes are rate-limited (5 attempts per 15 minutes per user) to prevent brute-forcing. The TOTP includes ±1 step drift tolerance for phones with poor NTP sync.

Per-role mandatory policy (Starter+)

From Shield → Two-Factor Auth in the WordPress admin, site owners can mandate 2FA enrollment for selected roles (Administrator, Editor, Author, Subscriber, custom roles). Each role row shows the compliance metric — 2 / 3 (67%) means 2 of 3 users in that role have already enrolled.

Grace period: configurable from 1 to 365 days (default 14). Users in required roles who haven't enrolled get a persistent admin notice on every wp-admin page warning them how many days are left. The notice color escalates: blue (>7 days), amber (2-7 days), red (last day). Each notice has an "Enroll now" button that goes straight to their profile.

Forced-enrollment login interstitial: once the policy is on, users in the required roles who try to sign in without 2FA get a full-page enrollment screen (QR + verify) on top of login_header(). They must enroll right then — clicking "Cancel and sign out" logs them back out. After verify, they get the 10 recovery codes via the standard flash → profile.php redirect path.

Post-grace lockout: when a user's grace period runs out without enrollment, they get a clear lockout page on the next sign-in attempt explaining "contact your administrator to reset your account". Another admin (or the rescue token) must clear the user's 2FA state before they can sign in again. Per-user grace start is computed as MAX(policy_set_at, user_registered) — users who join AFTER the policy was set still get the full grace period from their registration date.

Recovery + SaaS-side reveal (Pro+)

Three escape hatches when a user is locked out of their authenticator app:

1. Recovery codes (FREE) — the 10 single-use codes shown at enrollment. Treat them like passwords; save them in your password manager. On login, type one in the same field as the TOTP code (XXXX-XXXX format).

2. Other-admin reset (FREE) — any user with manage_options on the same site can reset another user's 2FA from Users → Edit → Reset 2FA (admin override). Audit-logged. After reset, the user re-enrolls fresh on next login.

3. SaaS-side recovery (Pro+, push-mode required) — from shield.syswp.pro/sites/:id/2fa, click "Reveal codes" on the user's row. Confirm with your account password (re-auth defense), then the SaaS pushes a synchronous command to the plugin which decrypts the recovery codes locally with wp_salt('auth') and returns them. The plaintext codes are shown for 60 seconds in your browser, never persisted on the SaaS DB. The user receives an out-of-band email notification ("your 2FA recovery codes were just shown by [admin]") so any rogue access is detected. Audit-logged on both sides. 24-hour cooldown per user.

Why poll-mode is rejected for reveal: the SaaS needs a synchronous round-trip to display plaintext in the same browser session that triggered the reveal. Poll-mode plugins respond on their next heartbeat (1-2 min later) which would mean stashing plaintext somewhere or reloading the page — both are security regressions. The button is visibly disabled with a tooltip on poll-mode sites; switch to push delivery to enable.

Rescue mode: the existing rescue token (Settings → Connection in the plugin) is also extended in 0.24.0 with a disable_2fa_emergency verb for the truly locked-out case. The token whitelists your IP and clears 2FA state in one shot — last-resort recovery path.

Ready to get started?

Free SaaS account, 30-second setup, no credit card. Plugin connects, network protection activates, you're live.