{"id":357373,"date":"2026-08-31T21:16:19","date_gmt":"2026-08-31T21:16:19","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/security-automation-manager\/"},"modified":"2026-09-04T16:57:25","modified_gmt":"2026-09-04T16:57:25","slug":"vcns-security-automation-manager","status":"publish","type":"plugin","link":"https:\/\/af.wordpress.org\/plugins\/vcns-security-automation-manager\/","author":23521940,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"2.9.75","stable_tag":"2.9.75","tested":"7.1","requires":"6.4","requires_php":"8.1","requires_plugins":null,"header_name":"VCNS Security Automation Manager","header_author":"VCNS Tech Ltd","header_description":"Roll out and enforce CSP, HSTS, X-Frame-Options headers with violation reports; free ACME\/Let's Encrypt SSL\/TLS certificate automation.","assets_banners_color":"0e2235","last_updated":"2026-09-04 16:57:25","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/github.com\/vcns\/security-automation-manager","header_author_uri":"https:\/\/vcns.tech","rating":0,"author_block_rating":0,"active_installs":0,"downloads":161,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","changelog"],"tags":{"2.9.26":{"tag":"2.9.26","author":"vcnstech","date":"2026-08-31 21:16:01","revision":3674968},"2.9.27":{"tag":"2.9.27","author":"vcnstech","date":"2026-08-31 23:29:08","revision":3675055},"2.9.28":{"tag":"2.9.28","author":"vcnstech","date":"2026-08-31 23:42:34","revision":3675062},"2.9.29":{"tag":"2.9.29","author":"vcnstech","date":"2026-09-01 00:10:22","revision":3675078},"2.9.30":{"tag":"2.9.30","author":"vcnstech","date":"2026-09-01 00:51:01","revision":3675114},"2.9.68":{"tag":"2.9.68","author":"vcnstech","date":"2026-09-04 00:44:32","revision":3680525},"2.9.75":{"tag":"2.9.75","author":"vcnstech","date":"2026-09-04 16:57:25","revision":3681557}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3675114,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3675114,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3675114,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3675114,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["2.9.26","2.9.27","2.9.28","2.9.29","2.9.30","2.9.68","2.9.75"],"block_files":[],"assets_screenshots":[],"screenshots":[]},"plugin_section":[],"plugin_tags":[68184,19966,34310,600,278547],"plugin_category":[54],"plugin_contributors":[278548],"plugin_business_model":[],"class_list":["post-357373","plugin","type-plugin","status-publish","hentry","plugin_tags-content-security-policy","plugin_tags-csp","plugin_tags-hsts","plugin_tags-security","plugin_tags-ssl-certificates","plugin_category-security-and-spam-protection","plugin_contributors-vcnstech","plugin_committers-vcnstech"],"banners":{"banner":"https:\/\/ps.w.org\/vcns-security-automation-manager\/assets\/banner-772x250.png?rev=3675114","banner_2x":"https:\/\/ps.w.org\/vcns-security-automation-manager\/assets\/banner-1544x500.png?rev=3675114","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/vcns-security-automation-manager\/assets\/icon-128x128.png?rev=3675114","icon_2x":"https:\/\/ps.w.org\/vcns-security-automation-manager\/assets\/icon-256x256.png?rev=3675114","generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p>Turning on strict security headers usually means picking between two bad options: leave Content-Security-Policy off and stay exposed, or turn it on and watch it silently break your checkout page, your embedded videos, or your analytics -- with no warning before it happens.<\/p>\n\n<p>Security Automation Manager takes a third option. It watches your site quietly first, in report-only mode, learning exactly which scripts, styles, and fonts your site actually loads -- nothing gets blocked while it learns. Once you can see the whole picture, you approve a policy built from your real site, not a guess. Only then does it start enforcing.<\/p>\n\n<h4>Everything below is free, with nothing held back<\/h4>\n\n<ul>\n<li><strong>Content Security Policy<\/strong> that proposes itself from real traffic, runs report-only until you approve it, and keeps learning as your site changes.<\/li>\n<li><strong>HSTS, X-Frame-Options, Referrer-Policy, Permissions-Policy<\/strong>, and five more security headers, each shipped with sane, hardened defaults.<\/li>\n<li><strong>Reverse tabnabbing protection, a third-party script inventory, and Subresource Integrity (SRI) hashing<\/strong> for everything your site pulls in from elsewhere.<\/li>\n<li><strong>Free SSL\/TLS certificates<\/strong> via Let's Encrypt, issued and renewed automatically, with 41 built-in DNS providers for wildcard domains -- Cloudflare, AWS Route 53, and Google Cloud DNS among them.<\/li>\n<\/ul>\n\n<p>The WordPress.org edition is a complete free plugin with no subscription-locked functionality. VCNS also distributes a separate commercial edition that includes Fully Automatic mode and associated commercial services.<\/p>\n\n<h4>Built for the moment things go wrong, not just the moment you install it<\/h4>\n\n<p>Every policy change is written to an append-only audit log, with a reason recorded. Conflict detection catches another plugin or your host quietly emitting a competing security header before it confuses you. Nothing enforces without a report-only learning period first, on every pillar that supports one.<\/p>\n\n<h4>For the technically curious<\/h4>\n\n<p>CSP ships per-surface profiles, nonce injection, source discovery, violation reporting, policy-change review, and readiness checks, alongside conflict detection for any CSP header already being emitted elsewhere. Seven more pillars (X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, Strict-Transport-Security, Cross-Origin-Resource-Policy, X-Permitted-Cross-Domain-Policies) are straightforward per-surface toggles. Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy get their own lighter report-only workflow via the browser Reporting API (Chromium-based browsers only, as of this writing). Certificates issues and renews via ACME DNS-01 or HTTP-01 domain validation, with credentials and private keys encrypted at rest, deploying via cPanel, filesystem export, or manual download.<\/p>\n\n<h3>External services<\/h3>\n\n<p>This WordPress.org build does not contact third-party services for plugin updates, licensing, checkout, telemetry, or remote product configuration.<\/p>\n\n<p>GitHub release builds are published separately for administrators who install from GitHub rather than WordPress.org; this update check is never present in the WordPress.org-channel package (this code is physically absent from it, not merely inactive). The GitHub-channel ZIP checks https:\/\/vcns.github.io\/wp-updates\/security-automation-manager\/update.json from administrator update contexts only, validates the advertised package host and SHA-256 checksum, and then lets WordPress perform the update. This manifest is VCNS's own infrastructure, not a third party; the request sends no personal or site-identifying data, only a plain HTTPS GET for a static, publicly-readable JSON file. The file is served from vcns.github.io, a GitHub Pages subdomain -- GitHub Pages has no separate terms or privacy documents of its own; the whole *.github.io domain is governed entirely by GitHub's own Terms of Service (https:\/\/docs.github.com\/en\/site-policy\/github-terms\/github-terms-of-service) and Privacy Statement (https:\/\/docs.github.com\/en\/site-policy\/privacy-policies\/github-privacy-statement), the same as github.com itself. Define WP_SAM_DISABLE_AUTO_UPDATE as true in wp-config.php to prevent background auto-updates for the GitHub-channel package.<\/p>\n\n<p>By default, the plugin emits CSP reporting headers that point browsers back to this WordPress site's own REST endpoint:<\/p>\n\n<ul>\n<li><code>\/wp-json\/sam\/v1\/report<\/code><\/li>\n<\/ul>\n\n<p>Administrators may override the reporting server URL when the public HTTPS endpoint differs from the WordPress-detected site URL, such as behind a proxy, CDN, or load balancer. If the override points to another host, browsers will send CSP reports to that configured endpoint; local report learning only works when the URL routes back to this plugin's report endpoint.<\/p>\n\n<p>Purpose:\n* receive browser-generated CSP violation reports for this site;\n* store reports locally so administrators can review and refine policy safely.<\/p>\n\n<p>Data handled:\n* browser CSP violation report fields such as blocked URL, document URL, violated directive, referrer, user agent, line\/column where provided, and an optional script sample where the active policy requests <code>report-sample<\/code>.<\/p>\n\n<p>Reports received by this plugin are validated and stored in this site's WordPress database. They are not sent to any external provider by default.<\/p>\n\n<p>For Cloudflare, CDN, and reverse-proxy deployments, administrators can configure an origin-only policy header name such as X-Origin-CSP-Policy. The proxy can then copy that origin header into the browser-facing Content-Security-Policy-Report-Only or Content-Security-Policy header.<\/p>\n\n<p>The Scripts page's External tab has a \"Suggest\" button, only triggered by an administrator explicitly clicking it, that fetches a URL the administrator themselves supplies (restricted to a third-party origin already observed on this site) and computes a Subresource Integrity hash from it, saving that hash immediately as the pinned value with no separate confirmation step. No content from that fetch is stored or sent anywhere else; only the computed hash is written to this site's own database. Nothing is fetched automatically or in the background as part of this feature.<\/p>\n\n<p>The Scripts page's Internal tab, when enabled for a surface, reads this site's own theme\/plugin\/core files directly from local disk to compute their Subresource Integrity hash -- never a network fetch of any kind, since the file being hashed is the exact file this server is about to serve.<\/p>\n\n<p>The Certificates page, only when an administrator configures it, requests TLS certificates over the ACME v2 protocol. Nothing is contacted until certificates are explicitly configured. Credentials and private keys are encrypted at rest. Issuing a certificate happens inside WordPress; installing it into the web server depends on your hosting platform -- automatic installation uses cPanel's install_ssl API where available, and https:\/\/vcns.github.io\/security-automation-manager\/certificates.html explains the basic steps for other platforms.<\/p>\n\n<p>Every certificate request or renewal contacts the certificate authority:<\/p>\n\n<ul>\n<li>Let's Encrypt (acme-v02.api.letsencrypt.org, or the staging equivalent), operated by the Internet Security Research Group (ISRG). Subscriber Agreement: https:\/\/letsencrypt.org\/repository\/ -- Privacy Policy: https:\/\/letsencrypt.org\/privacy\/<\/li>\n<\/ul>\n\n<p>Data sent to Let's Encrypt: the domain name(s) being requested; the ACME account's public-key material (used to sign every request and identify the account, never a private key); an optional contact email address, only if the administrator supplies one; the certificate signing request (CSR) at finalization; and challenge-response\/validation data as the ACME protocol's issuance flow requires.<\/p>\n\n<p>When a DNS provider is selected for DNS-01 domain validation, that provider's API is also contacted at certificate request and renewal time, using credentials the administrator supplies. Data sent depends on the specific request: API credentials\/tokens on every call; the domain and DNS zone name; requests to discover which zone matches the domain; the DNS record name being created or deleted (always of the form <code>_acme-challenge.&lt;domain&gt;<\/code>); the ACME TXT challenge value; and, for providers that require it, an account, project, or zone identifier. This plugin includes 41 built-in DNS provider drivers; below is each one's operating company and legal links, where the provider is a third-party service:<\/p>\n\n<ul>\n<li>Akamai (Edge DNS) -- Akamai Technologies, Inc. -- Terms: https:\/\/www.akamai.com\/legal\/portal-terms -- Privacy: https:\/\/www.akamai.com\/legal\/privacy-statement<\/li>\n<li>Alibaba Cloud DNS -- Alibaba Cloud -- Terms: https:\/\/www.alibabacloud.com\/help\/en\/legal\/latest\/alibaba-cloud-international-website-product-terms-of-service -- Privacy: https:\/\/www.alibabacloud.com\/help\/en\/legal\/latest\/alibaba-cloud-international-website-privacy-policy<\/li>\n<li>Microsoft Azure DNS -- Microsoft Corporation -- Terms and Privacy (agreement depends on purchase channel): https:\/\/azure.microsoft.com\/en-us\/support\/legal\/<\/li>\n<li>Bunny.net DNS -- BunnyWay d.o.o. -- Terms: https:\/\/bunny.net\/tos\/ -- Privacy: https:\/\/bunny.net\/privacy\/<\/li>\n<li>Cloudflare DNS -- Cloudflare, Inc. -- Terms: https:\/\/www.cloudflare.com\/terms\/ -- Privacy: https:\/\/www.cloudflare.com\/privacypolicy\/<\/li>\n<li>ClouDNS -- Cloud DNS Ltd -- Terms: https:\/\/www.cloudns.net\/tos\/ -- Privacy: https:\/\/www.cloudns.net\/privacy-policy\/<\/li>\n<li>deSEC -- deSEC e.V. -- Terms: https:\/\/desec.io\/terms\/ -- Privacy: https:\/\/desec.io\/privacy-policy\/<\/li>\n<li>DigitalOcean DNS -- DigitalOcean, LLC -- Terms: https:\/\/www.digitalocean.com\/legal\/terms-of-service-agreement -- Privacy: https:\/\/www.digitalocean.com\/legal\/privacy-policy<\/li>\n<li>DNSimple -- DNSimple Corporation -- Terms: https:\/\/dnsimple.com\/terms -- Privacy: https:\/\/dnsimple.com\/privacy<\/li>\n<li>DNS Made Easy (API: api.dnsmadeeasy.com -- dnsmadeeasy.com itself has no separate legal pages of its own; its own site directs to DigiCert's) -- DigiCert, Inc. -- Terms: https:\/\/www.digicert.com\/legal-repository -- Privacy: https:\/\/privacy.digicert.com\/policies\/en\/?name=dns-network-security-products-privacy-notice<\/li>\n<li>DNSPod -- Tencent Cloud -- Terms: https:\/\/docs.dnspod.cn\/account\/terms-of-service\/ -- Privacy: https:\/\/docs.dnspod.cn\/account\/privacy-policy\/ (Chinese-language)<\/li>\n<li>Domeneshop -- Domeneshop AS -- Terms and Privacy (single combined document, Norwegian-language): https:\/\/domene.shop\/terms<\/li>\n<li>DreamHost DNS -- DreamHost, LLC -- Terms: https:\/\/www.dreamhost.com\/legal\/terms-of-service\/ -- Privacy: https:\/\/www.dreamhost.com\/legal\/privacy-policy\/<\/li>\n<li>Dynu -- Dynu Systems, Inc. -- Terms: https:\/\/www.dynu.com\/en-US\/Legal\/TermsOfUse -- Privacy: https:\/\/www.dynu.com\/en-US\/Legal\/PrivacyPolicy<\/li>\n<li>easyDNS -- easyDNS Technologies Inc. -- Terms: https:\/\/easydns.com\/legal\/terms-of-service\/ -- Privacy: https:\/\/easydns.com\/legal\/privacy-policy\/<\/li>\n<li>Gandi DNS -- Gandi SAS -- Terms: https:\/\/www.gandi.net\/en\/contracts\/terms-of-service -- Privacy: https:\/\/www.gandi.net\/en\/contracts\/privacy-policy<\/li>\n<li>GleSYS -- Glesys AB -- Terms: https:\/\/glesys.com\/legal\/general-terms-and-conditions\/ -- Privacy: https:\/\/glesys.com\/legal\/privacy-policy\/<\/li>\n<li>GoDaddy DNS -- GoDaddy.com, LLC -- Terms: https:\/\/www.godaddy.com\/legal\/agreements\/universal-terms-of-service-agreement -- Privacy: https:\/\/www.godaddy.com\/agreements\/privacy<\/li>\n<li>Google Cloud DNS -- Google LLC -- Terms: https:\/\/cloud.google.com\/terms -- Privacy: https:\/\/cloud.google.com\/terms\/cloud-privacy-notice<\/li>\n<li>Hetzner DNS -- Hetzner Online GmbH -- Terms: https:\/\/www.hetzner.com\/legal\/terms-and-conditions\/ -- Privacy: https:\/\/www.hetzner.com\/legal\/privacy-policy\/<\/li>\n<li>INWX (API: api.domrobot.com, DomRobot, INWX's own API product -- domrobot.com is an API-only hostname and does not resolve to a website of its own) -- INWX GmbH -- Terms: https:\/\/www.inwx.com\/en\/aboutus\/terms -- Privacy: https:\/\/www.inwx.com\/en\/aboutus\/dataprotection<\/li>\n<li>IONOS DNS -- IONOS Inc. -- Terms: https:\/\/www.ionos.com\/terms-gtc\/general-terms-and-conditions\/ -- Privacy: https:\/\/www.ionos.com\/terms-gtc\/privacy-policy\/<\/li>\n<li>Joker.com DNS -- CSL Computer Service Langenbach GmbH -- Terms: https:\/\/joker.com\/terms\/general -- Privacy: https:\/\/joker.com\/index.joker?mode=page&amp;page=impressum<\/li>\n<li>Linode DNS -- operated by Akamai Technologies since Linode's acquisition -- Terms: https:\/\/www.akamai.com\/legal\/msa -- Privacy: https:\/\/www.akamai.com\/legal\/privacy-statement<\/li>\n<li>Mythic Beasts -- Mythic Beasts Ltd -- Terms: https:\/\/www.mythic-beasts.com\/terms\/overview -- Privacy: https:\/\/www.mythic-beasts.com\/terms\/privacy<\/li>\n<li>Namecheap DNS -- Namecheap, Inc. -- Terms: https:\/\/www.namecheap.com\/legal\/universal\/universal-tos\/ -- Privacy: https:\/\/www.namecheap.com\/legal\/general\/privacy-policy\/<\/li>\n<li>Name.com DNS -- Name.com, Inc. -- Terms: https:\/\/www.name.com\/policies\/registration-agreement -- Privacy: https:\/\/www.name.com\/privacy-policy<\/li>\n<li>NameSilo DNS -- NameSilo, LLC -- Terms: https:\/\/www.namesilo.com\/support\/v2\/articles\/general-terms\/terms-and-conditions -- Privacy: https:\/\/www.namesilo.com\/support\/v2\/articles\/general-terms\/privacy-policy<\/li>\n<li>netcup DNS -- netcup GmbH -- Terms: https:\/\/www.netcup.com\/en\/terms-and-conditions -- Privacy: https:\/\/www.netcup.com\/en\/contact\/data-privacy<\/li>\n<li>Netlify DNS -- Netlify, Inc. -- Terms: https:\/\/www.netlify.com\/legal\/terms-of-use\/ -- Privacy: https:\/\/www.netlify.com\/privacy\/<\/li>\n<li>Njalla -- operating entity not published -- Terms (also covers data collection; no separate privacy policy is published): https:\/\/njal.la\/tos\/<\/li>\n<li>NS1 -- operated by IBM since NS1's acquisition -- Terms: https:\/\/www.ibm.com\/legal\/terms -- Privacy: https:\/\/www.ibm.com\/us-en\/privacy<\/li>\n<li>OVH DNS -- OVH Groupe SA (OVHcloud) -- Terms: https:\/\/www.ovhcloud.com\/en\/terms-and-conditions\/ -- Privacy: https:\/\/www.ovhcloud.com\/en\/terms-and-conditions\/privacy-policy\/<\/li>\n<li>Porkbun DNS -- Porkbun LLC -- Terms: https:\/\/porkbun.com\/legal\/agreement\/product_terms_of_service -- Privacy: https:\/\/porkbun.com\/legal\/agreement\/privacy_policy<\/li>\n<li>AWS Route 53 -- Amazon Web Services, Inc. -- Terms: https:\/\/aws.amazon.com\/agreement\/ -- Privacy: https:\/\/aws.amazon.com\/privacy\/<\/li>\n<li>Scaleway DNS -- Scaleway S.A.S. -- Terms: https:\/\/www.scaleway.com\/en\/contracts\/ -- Privacy: https:\/\/www.scaleway.com\/en\/privacy-policy\/<\/li>\n<li>Vercel DNS -- Vercel Inc. -- Terms: https:\/\/vercel.com\/legal\/terms -- Privacy: https:\/\/vercel.com\/legal\/privacy-policy<\/li>\n<li>Vultr DNS -- The Constant Company, LLC -- Terms: https:\/\/www.vultr.com\/legal\/tos\/ -- Privacy: https:\/\/www.vultr.com\/legal\/privacy\/<\/li>\n<\/ul>\n\n<p>The remaining three DNS-01 drivers (acme-dns, PowerDNS, and RFC 2136 dynamic DNS updates) are not third-party services: they contact infrastructure the administrator operates or points at themselves (a self-hosted acme-dns instance, a self-hosted PowerDNS Authoritative Server, or any DNS server speaking the RFC 2136 standard), so no external terms or privacy policy apply.<\/p>\n\n<p>When an administrator configures automatic cPanel deployment, once a certificate is successfully issued the plugin sends an HTTPS request to the cPanel host the administrator specifies (cPanel's UAPI SSL::install_ssl endpoint), containing: the cPanel account username and API token supplied by the administrator (as an Authorization header); the domain name; the issued certificate; the certificate chain; and the certificate's private key. This is the one automatic-deployment method that transmits the private key itself, since installing a certificate requires it. Nothing is sent unless cPanel deployment is explicitly configured, and it happens once per issuance or renewal, immediately after the certificate is issued. Because the endpoint is the administrator's own hosting provider, not a service this plugin operates or has a relationship with, no single Terms of Service or Privacy Policy governs it -- those are whatever the administrator's own hosting provider publishes for their account and API access.<\/p>\n\n<!--section=changelog-->\n<h4>2.9.75<\/h4>\n\n<ul>\n<li>Fixed: <code>.github\/workflows\/wporg-deploy.yml<\/code>'s 24-hour \"one submission per day\" gate was documented as a WordPress.org platform requirement -- it isn't. An already-approved plugin's SVN commits go live immediately with no human review queue (that queue is specific to the initial plugin submission). Corrected the misleading comments and added an explicit <code>bypass_cadence_convention<\/code> manual-dispatch option so this team's own cadence convention can be skipped for one run when needed, without weakening the standing default. No plugin behaviour change.<\/li>\n<\/ul>\n\n<h4>2.9.74<\/h4>\n\n<ul>\n<li>Added: real traffic-control filtering by Tor exit-node status, ASN, and country -- the missing half of Geo-IP\/ASN\/Tor awareness (previously evidence-only). Tor exit-node filtering is a new detector (works alongside the existing 19, enable\/observe\/enforce from the Detectors tab). ASN and country blocking are a new \"Network Rules\" list on Traffic Controls &gt; Network Intelligence -- enter an ASN (e.g. AS15169) or a two-letter country code to block, and it's checked on every request alongside IP Rules. ASN\/Geo-IP lookups stay off (zero added cost) until you add at least one rule; only Tor's exit-node check runs unconditionally, since it's a cheap local table lookup rather than a live query.<\/li>\n<\/ul>\n\n<h4>2.9.73<\/h4>\n\n<ul>\n<li>Fixed: the Settings\/Overview page's About tab had drifted badly behind the actual feature set -- it still described \"nine further HTTP security headers\" (now eleven -- Information Masking and Cache-Control shipped since that text was written) and never mentioned Continuous Intelligence (request observation, nineteen built-in attack detectors, bot\/crawler recognition, custom fail2ban-style rules, traffic controls) or Baseline &amp; Drift (file\/theme\/plugin change detection) at all, despite both being fully shipped features with their own admin pages. Rewrote the \"What this plugin covers\" and \"The gap this fills\" sections to reflect the current product.<\/li>\n<\/ul>\n\n<h4>2.9.72<\/h4>\n\n<ul>\n<li>Added: an Edit action on Continuous Intelligence &gt; Vendors -- every vendor row (built-in or custom) previously showed only a bare \"-\" in the Actions column unless it was a custom, deletable one. The underlying storage already supported editing a built-in vendor in place (e.g. to add a vendor-published CIDR range once verified) without touching its built-in status, but the admin UI never exposed a way to reach it. The \"Add a vendor\" form now doubles as an edit form (pre-filled, with the Key field locked once a vendor exists) when reached via the new Edit link, matching the same edit-in-place pattern already used by Custom Rules.<\/li>\n<\/ul>\n\n<h4>2.9.71<\/h4>\n\n<ul>\n<li>Added: automatic recognition of loopback traffic (127.0.0.0\/8, ::1) on the Continuous Intelligence &gt; Identities tab -- a request from the server's own loopback address (wp-cron's own loopback call, a Site Health check, or an administrator testing from the same machine) is now recognised automatically as \"Loopback (this server)\" instead of sitting in the review queue as Unclassified. This is a new automatic recognition state, not a silent authorisation -- an administrator can still explicitly deny a loopback source (e.g. a site where a reverse proxy makes every visitor look like loopback), and that decision always wins, matching how every other recognition signal in this plugin already works.<\/li>\n<\/ul>\n\n<h4>2.9.70<\/h4>\n\n<ul>\n<li>Added: the public GitHub Pages help site's landing page (docs\/index.html) now explains what Content Security Policy actually defends against -- cross-site scripting (XSS) -- rather than only describing how the plugin's rollout workflow behaves. The ten-pillar card grid also gained a short \"why this matters\" clause per header (e.g. what clickjacking is, why a leaking Referer header is a privacy problem) instead of listing configuration mechanics alone. First installment of extending the UI documentation retrofit to the public docs site.<\/li>\n<\/ul>\n\n<h4>2.9.69<\/h4>\n\n<ul>\n<li>Added: plain-language explainer text on the Content Security Policy dashboard's Profiles, For Review, Policy Audit, Violations, Scan Log, and Settings tabs. Second installment of the UI documentation retrofit -- explains what each tab's data actually means and why it matters (e.g. why Occurrences never resets, what a \"scan\" actually checks, what the Trusted Types and Bypass Best Practices toggles are for) rather than leaving the reader to infer it from column headers and filter fields alone. Start Here already had this treatment and was left unchanged.<\/li>\n<\/ul>\n\n<h4>2.9.68<\/h4>\n\n<ul>\n<li>Fixed: the \"Settings\" link on the Plugins list page pointed at the Content Security Policy dashboard's own Settings tab instead of the plugin's actual landing page. It now goes to Settings\/Overview, matching the top-level admin menu's own first entry (also labelled \"Settings\").<\/li>\n<\/ul>\n\n<h4>2.9.67<\/h4>\n\n<ul>\n<li>Added: plain-language explainer text on the Settings\/Overview page (Overview, Readiness, and Security Health tabs) -- each of the five status layers, and the readiness and health checks below them, now has a short paragraph explaining what it covers, why it matters, and what a Fail or Warning actually means in practice. First installment of a wider documentation pass across the admin UI aimed at making the plugin approachable to administrators without a security background, not just to people who already know what CSP, MIME-sniffing, or clickjacking mean.<\/li>\n<\/ul>\n\n<h4>2.9.66<\/h4>\n\n<ul>\n<li>Added: Custom Rules -- your own regex-based detection rules, similar to a fail2ban filter (Traffic Controls -&gt; Custom Rules). Give a rule a name, a PHP-style regular expression, which part of the request to match it against (request URI, path, query string, or User-Agent), a severity, and optionally limit it to specific surfaces. A saved rule appears automatically on the Detectors tab, exactly like a built-in detector family, so it can be enabled\/disabled and opted into enforcement the same way -- it starts in Observe-only mode by default. Includes a \"Test a pattern\" tool to check a pattern against a sample value without saving anything. A pattern that doesn't compile is rejected at save time rather than silently matching nothing.<\/li>\n<\/ul>\n\n<h4>2.9.65<\/h4>\n\n<ul>\n<li>Fixed: several documentation files had drifted from the current codebase (GitHub issue #163) -- SECURITY.md's supported-versions table still named a years-old release line (now an evergreen \"latest version only\" policy that can't go stale the same way again); COMMERCIAL_TERMS.md still referred to the plugin by its pre-rename name, \"CSP Automation Manager\"; docs\/architecture.md and docs\/testing-and-quality.md still referenced database table and option names renamed away in schema v9; docs\/database-schema.md's version history table stopped at schema v12 while the plugin has shipped 24 schema versions since. All corrected, and extended the automated documentation-consistency test suite so drift like this is caught by CI going forward rather than found by manual audit again.<\/li>\n<\/ul>\n\n<h4>2.9.64<\/h4>\n\n<ul>\n<li>Added: a full security-controls inventory document (<code>docs\/security-controls-inventory.md<\/code>, GitHub issue #162) covering all 19 implemented HTTP security\/content-protection controls -- purpose, supported surfaces, default state, report-only\/enforcement\/discovery capability, approval requirements, breakage risk, rollback behaviour, audit events, limitations, and relevant standards for each. Written from and grounded directly in the current codebase, not general assumptions about what a header \"usually\" does -- several non-obvious findings are called out explicitly, including that Reverse Tabnabbing Protection and External Script Integrity can, in practice, only ever be active on the frontend surface regardless of their admin\/login\/api configuration, and that Trusted Types' own code comment claiming \"always report-only regardless of surface mode\" does not match its actual behaviour on an enforce-mode surface (also corrected in the code itself as a documentation fix, not a behaviour change).<\/li>\n<\/ul>\n\n<h4>2.9.63<\/h4>\n\n<ul>\n<li>Fixed: the External Scripts admin table's pagination never capped an out-of-range page number at the real last page (e.g. requesting page 9999 of a 3-page list rendered \"Page 9999 of 3\" instead of the last real page) -- every other paginated admin table in this plugin already clamped correctly; this was the one that didn't. Also added regression test coverage across all seven of this plugin's paginated admin tables (GitHub issue #167) confirming each one correctly caps out-of-range pages, preserves filters across a page change, and handles an empty result set without error.<\/li>\n<\/ul>\n\n<h4>2.9.62<\/h4>\n\n<ul>\n<li>Internal: replaced Content-Security-Policy's protected, subclass-overridable database-loading methods with an explicit, constructor-injected <code>Policy_Data_Loader<\/code> collaborator (GitHub issue #170). No behaviour change for real WordPress sites -- confirmed live that CSP headers (nonces, approved hashes, approved sources, all directives) are still emitted exactly as before. This only affects internal architecture and the plugin's own test suite.<\/li>\n<\/ul>\n\n<h4>2.9.61<\/h4>\n\n<ul>\n<li>Internal: improved the PHPUnit test suite's <code>wpdb::prepare()<\/code> stub (GitHub issue #169) to mirror real WordPress behaviour more closely -- <code>%f<\/code>\/<code>%i<\/code> placeholder support, an argument-count mismatch now correctly returning null instead of silently mismatching, and confirmed LIKE-expression wildcard handling. No user-facing change; this only affects the plugin's own test suite.<\/li>\n<\/ul>\n\n<h4>2.9.60<\/h4>\n\n<ul>\n<li>Added: Cache-Control, a new pillar (GitHub issue #221) with a named-preset Cache-Control value per surface (no-store; private, no-cache; public with a 5-minute or 1-hour max-age). Unlike every other pillar, this one is not enabled by default on any surface -- Cache-Control is a caching\/performance decision, not a universal security default, and shipping it pre-enabled would risk silently changing a site's frontend caching behaviour on upgrade.<\/li>\n<li>Added: automatic conflict detection so this pillar never competes with an existing caching mechanism, per the issue's own explicit safety requirement. It disables itself (with a clear on-screen explanation) when a known caching plugin is detected (WP Rocket, W3 Total Cache, WP Super Cache, LiteSpeed Cache, WP Fastest Cache, Cache Enabler, SiteGround Speed Optimizer, WP-Optimize, or Breeze -- more can be added over time) or when an admin has acknowledged a CDN\/edge cache is in front of the site (a manual acknowledgement, since a reverse proxy's own caching isn't observable from inside a single PHP request).<\/li>\n<\/ul>\n\n<h4>2.9.59<\/h4>\n\n<ul>\n<li>Added: Information Masking, a new pillar (GitHub issue #220) removing headers that disclose the server stack, PHP version, or this site's own hostname -- X-Powered-By (PHP version), Server (web-server signature), and X-Pingback (this site's own xmlrpc.php URL). Per-surface enable toggle, same shape as X-Content-Type-Options; enabled on every surface by default, matching every other simple pillar. X-Powered-By and X-Pingback removal is always reliable; Server is best-effort -- many hosts set it at the web-server layer before PHP ever runs, a layer no WordPress plugin can reach. A new live readiness check (Information Masking admin page) probes this site's own front page and reports whether each header is actually absent, so that host-dependent limitation is visible rather than silently assumed to work.<\/li>\n<\/ul>\n\n<h4>2.9.58<\/h4>\n\n<ul>\n<li>Added: robots.txt disallow-rule compliance, completing the robots.txt behaviour signal started in an earlier release. This site's own robots.txt is now fetched and cached daily (the same way a real crawler would read it), and a source already recognised as a known crawler or scanner vendor requesting a path it disallows is now recorded as evidence. An ordinary, unrecognised visitor is never evaluated against these rules -- robots.txt is a voluntary convention for automated crawlers, not something that applies to people. Like the other bot-classification signals, this can optionally be switched to Enforce on the Detectors tab; defaults to observation only.<\/li>\n<\/ul>\n\n<h4>2.9.57<\/h4>\n\n<ul>\n<li>Added: Phase 4C of the roadmap, fifth increment -- URI-pattern recognition, closing the last of the three signals (identity, request-rate, URI-pattern) the roadmap calls for combining into bot classification. Every recognised source now has its last 10 request paths logged (visible as a hover tooltip on the Identities tab's Classification column -- directly answering \"log the fact they're hitting the endpoint\"). An unrecognised source whose recent paths show a consistent sequential-ID pattern (e.g. \/product\/101, \/product\/102, \/product\/103, \/product\/104) is now classified as \"Enumerating\" -- checked ahead of the existing rate-based signal, since a script walking IDs is worth flagging whether or not it has tripped a rate limit yet. A known crawler's own path history is never checked this way, since systematically walking a site's posts is normal, expected crawler behaviour.<\/li>\n<\/ul>\n\n<h4>2.9.56<\/h4>\n\n<ul>\n<li>Added: Phase 4C of the roadmap, fourth increment -- session\/cookie behaviour and header-consistency signals. A login attempt (POST to wp-login.php) that never carries back the wordpress_test_cookie WordPress itself sets when rendering the login form is now recorded as evidence -- consistent with scripted credential-stuffing that posts straight to the login handler rather than a real browser that loaded the form first. Separately, a request whose User-Agent claims a specific, versioned browser (Chrome, Firefox, Edge, or Safari) but sends no Accept-Language header at all -- something every mainstream browser always sends -- is also now recorded, since that's a stronger signal of a copy-pasted User-Agent than an actual browser. Both default to observation only, like every other detector.<\/li>\n<\/ul>\n\n<h4>2.9.55<\/h4>\n\n<ul>\n<li>Added: Phase 4C of the roadmap, third increment -- robots.txt visit recognition, the first piece of robots.txt-behaviour tracking. A source examining robots.txt is now recorded as its own low-severity, observation-only evidence, correlatable by IP against everything else this plugin already knows about that source (its identity, its bot classification). Checking whether a source goes on to actually respect what robots.txt disallows is a bigger piece not yet built.<\/li>\n<\/ul>\n\n<h4>2.9.54<\/h4>\n\n<ul>\n<li>Added: Phase 4C of the roadmap, second increment -- bot\/crawler classification that avoids a binary \"bot or not\" model. The Identities tab now shows a Classification column combining what's already known about each source: an explicit admin decision always wins if one exists; otherwise a recognised vendor is split into \"Verified crawler\" (matches the vendor's own published network data) versus \"Claimed crawler (unverified)\" -- a real impersonation signal, since claiming to be Googlebot without matching Google's network is worth noticing; an unrecognised source is split into \"Aggressive \/ rate-escalated\" versus plain \"Unclassified\" depending on whether it's actually triggered progressive rate-limiting. Nothing new is written to the database -- purely a read-time view over evidence this plugin already records.<\/li>\n<\/ul>\n\n<h4>2.9.53<\/h4>\n\n<ul>\n<li>Added: HTTP Method Intelligence -- OPTIONS requests are now classified instead of treated as reconnaissance by default. A genuine browser CORS preflight (carrying both an Origin header and an Access-Control-Request-Method header, exactly as the Fetch\/CORS spec defines) is recorded as low-severity, confirmed-expected evidence; an OPTIONS request missing that pair is recorded separately at medium severity, since it could be legitimate API-discovery tooling or reconnaissance -- headers alone can't tell those apart. Like HTML Injection and Legacy WordPress Endpoints, this can optionally be switched to Enforce on the Detectors tab; defaults to observation only.<\/li>\n<\/ul>\n\n<h4>2.9.52<\/h4>\n\n<ul>\n<li>Added: Phase 4C of the roadmap, first increment -- AI crawler recognition. The built-in scanner\/crawler catalogue now also includes GPTBot (OpenAI), ClaudeBot (Anthropic), CCBot (Common Crawl), and PerplexityBot, verified against each vendor's own current published documentation the same way Googlebot\/Bingbot already are: CCBot by forward-confirmed reverse DNS, the other three by their vendor's published IP-range list (no IP ranges are hardcoded -- add current ones from the linked source via the existing Scanner Vendors admin page if you want IP-match verification too).<\/li>\n<\/ul>\n\n<h4>2.9.51<\/h4>\n\n<ul>\n<li>Added: Phase 4B of the roadmap, fourth and final increment -- a thirteenth detector family, Legacy WordPress Endpoints, recognising requests to xmlrpc.php (still legitimate in some setups, but also a common pingback-SSRF and credential-stuffing target), wp-trackback.php, and the long-removed wp-app.php. Per the roadmap's own requirement that \"RPC\/XML-RPC controls must be configurable rather than assumed universally safe to block,\" this is the second detector (after HTML Injection) that can be switched to Enforce on the Detectors tab -- still defaults to observation only. This completes Phase 4B: all 13 detector families are now registered, and the control-action framework is fully wired.<\/li>\n<li>Fixed: request observation now also runs on WordPress's <code>init<\/code> hook, alongside the existing send_headers\/login_init\/wp_redirect coverage. xmlrpc.php (and wp-cron.php) bootstrap WordPress directly and never fire send_headers, so without this fix they were invisible to every detector -- found while verifying the new Legacy Endpoints detector against a real site, not merely in the test suite.<\/li>\n<\/ul>\n\n<h4>2.9.50<\/h4>\n\n<ul>\n<li>Added: Phase 4B of the roadmap, third increment -- a twelfth detector family, PHP and PHPUnit Probes. Recognises specific, well-known vulnerability signatures: the PHPUnit eval-stdin.php remote code execution path (CVE-2017-9841), an exposed phpinfo()-style diagnostic script, the Laravel Ignition debug RCE path (CVE-2021-3129), the old php-cgi argument-injection query string (CVE-2012-1823), and a Symfony profiler path -- none of which are ever legitimate on a WordPress install. Defaults to observation only, same as every detector not explicitly opted into blocking.<\/li>\n<\/ul>\n\n<h4>2.9.49<\/h4>\n\n<ul>\n<li>Added: Phase 4B of the roadmap, second increment -- an eleventh detector family, HTML Injection. Recognises suspicious markup in a request (script tags, image\/SVG\/body tags carrying an onerror\/onload\/onclick handler, an iframe, a javascript: link, and similar), while staying deliberately careful not to flag ordinary text containing \"&lt;\" or the word \"on...\". Like every other detector, it defaults to observation only -- but unlike most, it can optionally be switched to Enforce on the new Detectors tab, since a legitimate endpoint that's known not to accept HTML can safely treat a match more strictly.<\/li>\n<\/ul>\n\n<p><h4>2.9.48<\/h4><\/p>\n\n<ul>\n<li>Added: Phase 4B of the roadmap, first increment -- the control-action framework. Every detector family can now be individually enabled or disabled, and (where the family allows it) switched from pure observation to also feeding the same progressive-response blocking ladder rate limiting and login-brute-force protection already use, still gated behind that surface's own Observe\/Enforce mode. New \"Detectors\" tab on the Traffic Controls page. Nothing changes for any existing install unless you explicitly opt a detector into enforcement -- every detector still defaults to observation only.<\/li>\n<\/ul>\n\n<p><h4>2.9.47<\/h4><\/p>\n\n<ul>\n<li>Added: Phase 4A of the roadmap, third and final increment (Geo-IP Controls) -- an opt-in feature using your own IPinfo (ipinfo.io) account, never a shared VCNS credential. Disabled until you add a token on the Network Intelligence tab; the token is encrypted at rest using the same mechanism already protecting certificate and DNS-provider credentials. Once enabled, evidence a detector already produced now also notes the source's country, region, and city. A \"Look Up\" tool lets you check any IP directly. MaxMind support was deliberately not built in this pass -- its free tier is a downloaded database, not a live lookup service, and adding it would mean this plugin's first external code dependency; that stays a separate future decision. This completes Phase 4A (Tor Awareness, ASN Controls, Geo-IP Controls).<\/li>\n<\/ul>\n\n<p><h4>2.9.46<\/h4><\/p>\n\n<ul>\n<li>Added: Phase 4A of the roadmap, second increment (ASN Controls) -- the plugin can now resolve which network\/organisation a source IP belongs to, using Team Cymru's free, unauthenticated ASN lookup service (no account needed). Results are cached for 30 days so the cost is only paid once per IP. Like Tor awareness, this is observation only -- when another detector already produces evidence for a request, that evidence now also notes the source's ASN and organisation name. The Network Intelligence tab gains a \"Look Up\" tool so you can check any IP's ASN directly; Geo-IP remains noted there as planned next.<\/li>\n<\/ul>\n\n<p><h4>2.9.45<\/h4><\/p>\n\n<ul>\n<li>Added: Phase 4A of the roadmap (Tor Awareness) -- the plugin now recognises requests originating from a known Tor exit node, using the Tor Project's own public exit-node list (no account or API key needed, refreshed daily). This is observation only: Tor identity never implies malicious intent and nothing is blocked because of it. When another detector already produces evidence for a request, that evidence now also notes whether the source was a Tor exit node. A new \"Network Intelligence\" tab on the Traffic Controls page shows the current list status and a manual refresh option; ASN and Geo-IP are noted there as planned next.<\/li>\n<\/ul>\n\n<p><h4>2.9.44<\/h4><\/p>\n\n<ul>\n<li>Added: Phase 3J of the roadmap -- Advanced Optional Intelligence, a new \"Advanced Intelligence\" page with four tabs. Campaigns correlates request-observation events into a possible coordinated campaign when many distinct source IPs trigger the same detector on the same surface -- observe\/correlate\/notify only; blocking every participant is a separate, explicit action requiring a reason. Honey Paths lets you configure decoy paths no legitimate visitor ever requests; disabled until you add one, and a hit is recorded exactly like any other detector finding, never served special content. Change Windows lets you declare an intentional change (an upgrade, a deployment) in progress, recording the current baseline as a rollback reference, then shows exactly what drifted while the window was open. Timeline merges site changes, security drift, and campaigns into one chronological, correlation-only view. Two new administrator-account signals (new admin account created, existing user granted the administrator role) now feed the same change history this correlates against.<\/li>\n<li>Added: an indexed <code>ip<\/code> column on the request-observation events table, needed for Campaign correlation to count distinct sources cheaply.<\/li>\n<\/ul>\n\n<p><h4>2.9.43<\/h4><\/p>\n\n<ul>\n<li>Added: Phase 3I of the roadmap -- Assurance and Reporting. A new \"Security Health\" tab on the Settings page gives a plain-language, non-gamified summary of security outcomes -- enforcement posture, open drift, certificate expiry, unclassified third-party dependencies, active exceptions, automation posture, and evidence freshness -- so you can see \"what's the state of my security controls?\" without opening every individual page. An \"Evidence Export\" downloads a JSON snapshot of currently-configured controls, open exceptions, certificate state, baseline\/drift status, and recent audit history, useful for a security review, an MSP report, or audit preparation -- it explicitly documents this as evidence to support a review, never a compliance certification.<\/li>\n<\/ul>\n\n<p><h4>2.9.42<\/h4><\/p>\n\n<ul>\n<li>Added: Phase 3F of the roadmap -- Baseline and Drift. Capture an approved snapshot of this site's locally-known configuration (CSP headers, security header toggles, external dependency and internal-asset-integrity inventories, certificate state, and WordPress\/theme\/plugin versions) from the new Baseline &amp; Drift page, then run scans to see exactly what changed since. Each difference is risk-classified, checked for a plausible (never claimed-causal) correlation with a recent plugin\/theme\/core change, and can be reviewed as expected, approved, or left open for investigation -- items that revert to match the baseline are marked resolved automatically. A real Change Log now tracks plugin\/theme\/core update history for this correlation, separate from the plugin's existing CSP-learning-window signal.<\/li>\n<\/ul>\n\n<p><h4>2.9.41<\/h4><\/p>\n\n<ul>\n<li>Added: Phase 3E of the roadmap -- Traffic Controls. This plugin's first active request-blocking capability: per-surface rate limiting, a manual IP allow\/block list, and progressive automatic escalation (warn -&gt; throttle -&gt; temporary block -&gt; extended block), viewable and manageable from the new Traffic Controls page. Every surface starts in Observe mode -- nothing is ever blocked until you explicitly switch a surface to Enforce -- and an already-authenticated administrator is never blocked by automatic detection, only by an explicit IP block rule you add yourself. ASN and Geo-IP controls from the roadmap are deliberately deferred: this plugin has no verified network-intelligence data source for them yet.<\/li>\n<\/ul>\n\n<h4>2.9.40<\/h4>\n\n<ul>\n<li>Added: Phase 3D of the roadmap -- Identity and Scanner Intelligence. A new Continuous Intelligence \"Identities\" tab shows every claimed identity resolved from real traffic (crawler\/scanner recognition via User-Agent + optional published IP ranges), always kept structurally distinct from authorisation: a recognised source is never automatically treated as authorised, and only an explicit administrator decision (with a required reason) changes that. A new \"Vendors\" tab manages the known-identity catalogue, seeded with two built-in search crawlers (Googlebot, Bingbot) verified by forward-confirmed reverse DNS rather than a hardcoded IP range; administrators can add their own verified commercial scanner vendors, each requiring a source URL.<\/li>\n<\/ul>\n\n<h4>2.9.39<\/h4>\n\n<ul>\n<li>Fixed: the CSP learning window (the bounded period after a \"material change\" during which newly-discovered hosts from real browser traffic get re-evaluated) only re-opened for plugin activations\/deactivations\/updates and post\/page saves -- a theme update or a WordPress core update never reopened it, even though either can change the exact bytes of inline scripts\/styles and the third-party hosts a page depends on just as much as a plugin update can. <code>Learning_Window::mark_upgrader_change()<\/code> (renamed from <code>mark_plugin_upgrader_change()<\/code>) now also recognises <code>'theme'<\/code> and <code>'core'<\/code> from <code>upgrader_process_complete<\/code>.<\/li>\n<\/ul>\n\n<h4>2.9.38<\/h4>\n\n<ul>\n<li>Changed: the Settings Overview table now shows CSP's per-surface automation posture on the Layer 2 (Controlled Automation) row, where it belongs, instead of a placeholder pointing down at Layer 4. Layer 4's \"Automation\" column is removed -- CSP was the only pillar that ever populated it, every other row showed a blank dash.<\/li>\n<\/ul>\n\n<h4>2.9.37<\/h4>\n\n<ul>\n<li>Added: Phase 3A of the roadmap's primary-navigation redesign -- four new plain-language lifecycle pages (Observe, Decide, Control, Verify) under Security Automation Manager, each linking to the relevant existing pages\/tabs with an explanation of what that stage means, honest about what's not built yet (no traffic-blocking capability exists; no external verification service exists yet).<\/li>\n<li>Changed: the left-hand admin menu now shows Observe, Decide, Control, Verify, and Settings (renamed from Overview) as the primary entries. Certificates, Continuous Intelligence, Cross-Origin Policies, CSP, HSTS, Permissions-Policy, Referrer-Policy, Reverse Tabnabbing, Scripts, X-Content-Type-Options, and X-Frame-Options remain fully accessible at their existing URLs as drill-down pages; only their left-nav entries moved.<\/li>\n<\/ul>\n\n<h4>2.9.36<\/h4>\n\n<ul>\n<li>Added: Phase 3C of <code>.roadmap\/phase3_early_plan.md<\/code> -- ten deterministic detector families for the Continuous Intelligence framework introduced in 2.9.35: technology mismatch, command injection, SQL injection, sensitive-directory probing, sensitive-file probing, setup\/install probes, script\/web-shell probes, protocol injection, version-control artefacts, and vulnerability probes. Every rule is Observe-only (nothing is blocked), reconnaissance-scoped, and specifically designed to stay quiet on ordinary WordPress traffic -- pattern matching was reviewed against real false-positive cases (a legitimate site search, a plugin's own changelog file, ordinary <code>?cat=<\/code>\/<code>?id=<\/code> query variables) before shipping. Findings now populate the \"Continuous Intelligence\" admin page introduced in 2.9.35.<\/li>\n<\/ul>\n\n<h4>2.9.35<\/h4>\n\n<ul>\n<li>Added: Phase 3B of <code>.roadmap\/phase3_early_plan.md<\/code> -- the Request Observation Framework. Every request (frontend, admin, login, and REST API) is now observed and classified by surface, laying the foundation for future traffic intelligence. This release ships the observation skeleton only: no detector is registered yet, so the new \"Continuous Intelligence\" admin page and its underlying event table stay empty, and nothing is written to them, until a detector exists in a future release to evaluate what's observed.<\/li>\n<\/ul>\n\n<h4>2.9.34<\/h4>\n\n<ul>\n<li>Changed: the Overview tab's status table now shows all five protection layers (Governance and Operations, Controlled Automation, Continuous Intelligence, Browser Security Policies, Transport &amp; Certificate Trust) as consistent tables with real links, instead of reducing three of them to a single sentence. Layer 1 now links directly to the Readiness\/Recovery\/Updates tabs with a real computed status for each; Layer 2 links to the CSP automation settings; Layer 3 is an honest placeholder, since it has no pillars until a future phase.<\/li>\n<\/ul>\n\n<h4>2.9.33<\/h4>\n\n<ul>\n<li>No plugin functionality change -- release\/CI pipeline change only (the WordPress.org SVN deploy now runs from its own separate <code>wporg-vX.Y.Z<\/code> tag instead of every version tag, so a routine GitHub release no longer implies a WordPress.org submission). This version exists only to produce a properly-tagged commit for that pipeline change to take effect from.<\/li>\n<\/ul>\n\n<h4>2.9.32<\/h4>\n\n<ul>\n<li>Changed: rewrote the plugin's one-line description (plugin header and the top of this readme) to actually cover what the plugin does, its breadth, and the free\/no-paywall promise -- the previous line only mentioned CSP and TLS certificates and left out the other eight headers and script integrity entirely.<\/li>\n<\/ul>\n\n<h4>2.9.31<\/h4>\n\n<ul>\n<li>Added: the Overview tab's pillar status table is now grouped by protection layer -- \"Layer 4: Browser Security Policies\" (CSP and the other twelve header\/content-rewrite pillars) and \"Layer 5: Transport &amp; Certificate Trust\" (Certificates, which previously had no row in this table at all). Each pillar now shows one of four consistent states per surface -- Not configured, Disabled, Report-only, or Active -- instead of a plain On\/Off that couldn't tell \"never touched\" apart from \"deliberately turned off\". CSP's own automation posture (Manual \/ Automatic...) is now shown alongside its status.<\/li>\n<li>Changed: internal only -- the pillar list this table renders from is now a single registry class (<code>Pillar_Registry<\/code>) instead of a hand-maintained array that had already drifted out of sync with the plugin's actual install-time defaults.<\/li>\n<\/ul>\n\n<h4>2.9.30<\/h4>\n\n<ul>\n<li>Changed: replaced the WordPress.org listing icon and banner. The previous design used an invented shield mark and an amber accent colour with no connection to VCNS's actual brand, and only mentioned CSP\/HSTS\/SSL-TLS -- a fraction of what the plugin actually does. The new artwork uses VCNS's real cloud-and-circuit mark and brand gradient (teal to cyan), and calls out the full scope: 10 security headers, automatic TLS via ACME, and script\/content integrity protections.<\/li>\n<\/ul>\n\n<h4>2.9.29<\/h4>\n\n<ul>\n<li>Added: a persistent admin notice on every wp-admin page (not just the Certificates page) when the most recent ACME certificate issuance or renewal failed -- a failed WP-Cron renewal could previously go unnoticed until the certificate actually expired. The existing \"Last run\" row on Certificates &gt; Issue\/Renew is now colour-coded (red for failed, green for success) so it's unmistakable when you're already looking at it.<\/li>\n<li>Fixed: the public help site (docs\/) referenced seven screenshot filenames that never existed, showing as broken images since the site first went live. Replaced them with the real screenshots, and added several more to sections that already describe a feature but never illustrated it (X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Strict-Transport-Security, Cross-Origin-Opener-Policy, Cross-Origin-Embedder-Policy, Reverse Tabnabbing, and both Scripts tabs).<\/li>\n<\/ul>\n\n<h4>2.9.28<\/h4>\n\n<ul>\n<li>Fixed: the WordPress.org listing icon\/banner from 2.9.27 deployed one directory too deep and never actually showed up -- corrected the path, and removed two stray files (an old build zip and an internal draft) that had been live on the public listing since before this plugin's approval.<\/li>\n<li>Fixed: same dropdown-width issue as 2.9.27's Permissions-Policy fix, on Referrer-Policy's \"unsafe-url\" option -- shortened the label, moved the full explanation to the page's own description text.<\/li>\n<li>Fixed: the Scripts &gt; Internal Hash Inventory table had the same uneven column-width problem as the For Review table -- URL and Hash now get proportionally more room.<\/li>\n<\/ul>\n\n<h4>2.9.27<\/h4>\n\n<ul>\n<li>Added: a plugin icon and header banner for the WordPress.org listing.<\/li>\n<li>Changed: rewrote the plugin description to lead with what the plugin actually does for you, instead of a feature inventory -- the full technical detail is still there, just further down.<\/li>\n<li>Fixed: the For Review table's columns were sized evenly regardless of content, forcing long hostnames to wrap mid-word; Host now gets proportionally more room.<\/li>\n<li>Fixed: Permissions-Policy directive dropdowns were stretched wide by one long option's description text (\"All -- any origin, including third-party iframes and embeds (not recommended)\"). Options are now short labels; the fuller explanation moved to the page's existing description text below the table.<\/li>\n<\/ul>\n\n<h4>2.9.26<\/h4>\n\n<ul>\n<li>No plugin functionality change -- release\/CI pipeline fix  &hellip;<\/li>\n<\/ul>","raw_excerpt":"Ten security headers that learn your site before enforcing -- nothing breaks. Plus free automatic TLS certificates and script integrity. No paywall.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/af.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/357373","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/af.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/af.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/af.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=357373"}],"author":[{"embeddable":true,"href":"https:\/\/af.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/vcnstech"}],"wp:attachment":[{"href":"https:\/\/af.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=357373"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/af.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=357373"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/af.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=357373"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/af.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=357373"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/af.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=357373"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/af.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=357373"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}