Severity Daily

IT and AI security incidents, checked against the primary source

Tag: unauthenticated

  • Mail Mint’s 9.8 was fixed in a release whose security note is about something else, and the record points the gadget chain at a bundled PostHog SDK

    Mail Mint’s 9.8 was fixed in a release whose security note is about something else, and the record points the gadget chain at a bundled PostHog SDK

    The unauthenticated deserialization was fixed on September 1 in a release whose only security bullet describes a different change, and the one file the record cites outside the plugin’s own code is a bundled third-party analytics SDK.

    What happened

    CVE-2026-10196 was published to the National Vulnerability Database at 12:16 p.m. UTC on Saturday, September 5, 2026, with Wordfence as the assigning CNA. It scores 9.8 on vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H and is classified CWE-502, deserialization of untrusted data.

    The product is Mail Mint – Email Marketing, Newsletter, Email Automation & WooCommerce Emails, published by getwpfunnels, which WordPress.org lists at more than 4,000 active installations. The record’s description says the plugin “is vulnerable to PHP Object Injection in all versions up to, and including, 1.31.0 via deserialization of untrusted input in the ‘handle_form_submission’ function,” and adds the sentence that carries the score: “The additional presence of a POP chain allows attackers to execute code on the server.”

    That sentence is doing all the work. An unauthenticated attacker who can get arbitrary serialized data into unserialize() has object instantiation, which on its own is often a nuisance. It becomes remote code execution only when the running codebase also contains a property-oriented programming chain β€” a class whose magic methods, invoked as PHP tears the object down, do something useful to an attacker. Without a chain the finding is high; with one it is 9.8.

    The record does not say where the chain is. Its source-code references do point somewhere specific. Wordfence cites three files, each twice β€” once at the 1.21.0 tag and once at trunk:

    • app/API/Actions/Frontend/FormAction.php at line 59
    • app/Database/models/ContactModel.php at line 460
    • vendor/posthog/posthog-php/lib/Consumer/ForkCurl.php at line 96

    The first two are Mail Mint’s own code β€” the form handler named in the description, and the model it writes through. The third is not Mail Mint’s code at all. It is PostHog’s PHP analytics SDK, vendored into the plugin’s vendor/ directory by Composer. Upstream, that class builds a curl command as a string and hands it to PHP’s exec(); the version on PostHog’s master branch calls exec() twice, at lines 64 and 77, and defines no magic methods of its own. We could not read the copy bundled inside Mail Mint at line 96 β€” the WordPress plugin repository’s code browser refuses automated retrieval β€” so we cannot confirm what that specific line contains or that it is the chain.

    The fix exists. WordPress.org shows the current version as 1.31.1, released September 1, 2026, four days before the CVE was published. The affected range stops at 1.31.0, so 1.31.1 is the version to be on. Two changesets are referenced in the record, 3545065 and 3675453; both returned rate-limit errors to us and are unread.

    The 1.31.1 changelog does use the word “security.” It attributes it to something else: “Contact action links now use unguessable tokens,” a link-forgery fix. The entry covering the code this CVE is about is worded as an improvement to form submission error handling. Neither deserialization nor object injection appears.

    Why it matters

    The severity of a deserialization bug is not a property of the deserialization bug. It is a property of everything else that happens to be loaded in the same PHP process at the same time. That is the uncomfortable part of CWE-502 and it is why these findings are so hard to triage from a distance.

    Mail Mint’s own code, on the record’s own account, supplies the sink: a form handler that unserializes attacker-controlled input without authentication. What lifts that from a serious bug to a 9.8 is a chain β€” and the only file the record points at that Mail Mint’s developers did not write is a bundled analytics library whose entire purpose is to shell out to curl. We are not asserting that PostHog’s SDK is vulnerable; a class that calls exec() is not a vulnerability, it is a design choice appropriate to a library that ships HTTP payloads. The point is narrower and more awkward: a plugin author’s exposure to this class of bug is set partly by the contents of a vendor/ directory they did not audit and may not think of as theirs.

    This is a recurring shape in the WordPress ecosystem specifically, because plugins ship their dependencies rather than resolving them at runtime. Every plugin on a site contributes its vendored classes to one shared autoloader and one shared process. A gadget introduced by plugin A can be reachable from a sink introduced by plugin B. Nothing in a CVE record for either plugin will tell you that, and nothing in a scanner’s output will either.

    The practical consequence for a defender is that “we removed the vulnerable plugin” and “we are safe” are different claims. If the sink is gone, that install is fixed. But the same vendored SDK ships inside other plugins, and the presence of a usable chain on a given site is a function of the whole plugin set, not of any one entry in it.

    The changelog point is smaller but worth recording, because it is the second time today this site has run into it. This morning we covered three WordPress plugins that reintroduced comment XSS after core had sanitized it, none of whose changelogs said security. Mail Mint’s does say security β€” about a different change in the same release. A site owner reading the 1.31.1 notes to decide whether to update urgently would conclude the security content was a link-tokenization improvement, and would have no way to know that the same release closed an unauthenticated path to code execution. The four-day gap between the release and the CVE is the window in which the changelog was the only public description of what 1.31.1 did.

    What to do

    • Update Mail Mint to 1.31.1 or later. The affected range is everything up to and including 1.31.0, and 1.31.1 has been available since September 1, 2026. This is the whole fix for the sink.
    • Check WooCommerce sites first. The plugin’s transactional and abandoned-cart features mean it is most often installed on stores, where the same process also holds order and customer data.
    • Treat the pre-update window as reachable. The path is unauthenticated with no user interaction, so exposure did not require a logged-in user. If the site was on 1.31.0 or earlier and public, review web server logs for POSTs to the plugin’s form endpoint and look for unexpected files under wp-content.
    • Inventory vendored dependencies, not just plugins. Grep your plugin directory for vendor/posthog, and more usefully for any vendored class that calls exec, shell_exec, proc_open or system. That set is your site’s gadget surface and it does not appear in any plugin list.
    • Do not read the changelog as the severity signal. Read the CVE record and the affected range.

    Sourcing note

    Checked against primary sources: the NVD record for CVE-2026-10196, retrieved September 5, 2026, which supplied the description, score, vector, CWE, affected range and the full reference list quoted above; the WordPress.org listing and changelog for the mail-mint plugin, which supplied the current version, its release date and install count; and PostHog’s posthog-php repository on GitHub for the upstream contents of lib/Consumer/ForkCurl.php.

    Could not reach: the WordPress plugin repository’s code browser, which refuses automated retrieval, so none of the six trac source references in the record were read, including the ForkCurl.php line 96 that this story discusses. The two referenced changesets returned HTTP 429 rate-limit errors and are unread, so what 1.31.1 actually changed is taken from the changelog rather than from a diff. Wordfence’s own threat-intelligence entry for this vulnerability does not render to automated retrieval.

    Unresolved: the record states a POP chain is present but does not name it, and we have not confirmed that the chain runs through the bundled PostHog SDK β€” that reading is inferred from the record’s reference list and is stated as an inference, not a finding. getwpfunnels has published no security advisory we could find. There is no indication in any source that this flaw has been exploited, and it is not in CISA’s Known Exploited Vulnerabilities catalog.

  • Post Grid’s new 9.8 says the flaw stops at 2.3.1, its own data says 2.3.32, and the plugin’s newest release is 2.3.24

    Post Grid’s new 9.8 says the flaw stops at 2.3.1, its own data says 2.3.32, and the plugin’s newest release is 2.3.24

    A critical CVE published Saturday morning against a plugin on more than 30,000 WordPress sites contains two version ranges that contradict each other, and the higher one tops out above any release the plugin has ever shipped.

    What happened

    CVE-2024-11080 was published to the CVE Program at 8:27 a.m. UTC on Saturday, September 5, 2026, and appeared in the National Vulnerability Database about fifty minutes later. Wordfence is the assigning CNA. The score is 9.8, vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H, and the CWE is CWE-94, code injection. The affected product is “Post Grid and Gutenberg Blocks – ComboBlocks,” published by PickPlugins, which WordPress.org lists at more than 30,000 active installations.

    The record’s description reads, in full: “The Post Grid and Gutenberg Blocks – ComboBlocks plugin for WordPress is vulnerable to Unauthenticated Hook Injection in versions 2.2.32 to 2.3.1 via several functions in the ~/includes/blocks/form-wrap/function.php file. This makes it possible for unauthenticated attackers to execute actions with hooks in WordPress, granted no other security controls are present in the function.”

    The machine-readable half of the same record says something different. In the CNA container retrieved from the CVE Program API, the affected block carries a single entry: vendor pickplugins, product Post Grid, "version":"2.2.85", "lessThanOrEqual":"2.3.32", "versionType":"semver", status affected. NVD reproduces the same range and carries no separate CPE configuration of its own.

    So one record states two ranges. The prose says the flaw runs from 2.2.32 to 2.3.1 β€” implying a site on anything from 2.3.2 upward is clear. The structured data says it runs from 2.2.85 to 2.3.32 β€” implying nothing below 2.3.33 is clear. The two ranges do not overlap at either end. We retrieved the record three times, twice from NVD with different query forms and once from the CVE Program API, and got the same two ranges every time.

    The upper bound is the part that will not resolve by picking the more cautious number. WordPress.org lists the plugin’s current version as 2.3.24, last updated July 19, 2026, with a changelog entry reading “fixed – Cross Site Scripting (XSS).” The version selector on the plugin’s advanced page runs down from 2.3.23 and shows nothing above 2.3.24. There is no 2.3.32. The affected range’s ceiling names a release that does not exist.

    That propagates. WPScan’s page for the plugin lists the same finding as “Post Grid and Gutenberg Blocks – ComboBlocks 2.2.85 – 2.3.32 – Unauthenticated Hook Injection,” dated September 4, 2026, at 9.8, and states it is fixed in 2.3.33. A site owner acting on that is being told to install a version one increment above another version that has never been released.

    Two smaller defects sit in the same record. The description points at ~/includes/blocks/form-wrap/function.php, singular. All three source references in the record point at form-wrap/functions.php, plural, at lines 116, 262 and 3249. And the CVE identifier itself is a 2024 one: the CVE Program record gives dateReserved as November 11, 2024, while its own disclosure timeline says the vendor was notified on September 2, 2026 at 1:42 p.m. UTC and the finding was disclosed on September 4, 2026 at 7:52 p.m. UTC. The researcher credited is Chloe Chamberland.

    Why it matters

    The two halves of a CVE record are read by two different audiences, and here they give opposite answers to the only question that matters.

    A human reading the NVD page sees “versions 2.2.32 to 2.3.1,” checks the site’s plugin screen, sees 2.3.24, and closes the tab. A scanner ingesting the record does not read the prose at all β€” it reads the affected block, sees a ceiling of 2.3.32, and flags 2.3.24 as vulnerable. Both are behaving correctly on the data in front of them, and one of them is wrong. Nothing in the record tells you which.

    Because the ceiling is above every shipped release, the structured data effectively says the plugin is unpatched, and the prose effectively says it was patched twenty-two releases ago. That is a two-year gap in a 9.8 rated as unauthenticated with no user interaction. And the plugin’s own changelog gives no help: the last release, 2.3.24 on July 19, 2026, predates by seven weeks the September 2, 2026 vendor notification recorded in this very CVE. Absent a release we cannot see, the vendor has not shipped anything since being told.

    The downstream effect is the interesting part, and it is not hypothetical. WPScan has already rendered “≀ 2.3.32” into “fixed in 2.3.33,” which is what a well-behaved aggregator does with an upper bound: it adds one. That is a reasonable rule applied to an unreasonable input, and the output is a remediation instruction pointing at a version nobody can install. This site has been tracking a family of these all week β€” Coolify, where the affected ceiling is also the current release; SonicWall’s SMA1000 records, which name no fixed version at all; goose, whose CVE names none either. Those records fail by saying too little. This one fails by saying two things.

    The description’s own hedge deserves a mention too. It ends “granted no other security controls are present in the function” β€” a conditional that materially changes exploitability, since a hook-injection primitive that lands in a function with its own capability or nonce check is not the same finding as one that does not. The 9.8 score carries no such conditional; CVSS has nowhere to put one. Readers who triage on the number alone will not see it.

    Finally, the identifier. CVE-2024-11080 will be read by a lot of people as a 2024 vulnerability, and it is not. The year in a CVE ID marks when the identifier was reserved, not when the flaw was found or fixed, and CNAs that handle volume reserve blocks well in advance and draw from them later. That is normal practice, not a defect. It becomes a practical problem when the record is otherwise ambiguous: an operator trying to work out whether 2.3.24 is affected cannot use the ID’s year to bound the answer, and here that was the last piece of context left.

    What to do

    There is no version you can confidently upgrade to, so this is a containment question rather than a patching one.

    • Inventory first. Find WordPress sites running Post Grid / ComboBlocks (slug post-grid) and record the exact version. Anything in the 2.2.x or 2.3.x range is inside at least one of the two published ranges.
    • Do not treat 2.3.2 or later as clear on the strength of the description. The record’s own structured data disagrees with it, and the structured data is what your scanner is using.
    • Do not go looking for 2.3.33. WordPress.org shows 2.3.24 as current as of September 5, 2026. If your tooling tells you to install 2.3.33, that instruction is derived from the disputed ceiling, not from a release.
    • Look at includes/blocks/form-wrap/functions.php, with the plural filename, around lines 116, 262 and 3249 β€” the three locations the record’s own references cite. If you maintain the site, that is the code to review or to gate.
    • Restrict unauthenticated access to the plugin’s form-wrap handlers at the WAF or reverse proxy if the plugin is load-bearing and cannot come out. This stands in for a patch and is not one.
    • Expect a scanner finding that will not clear. Until the range is corrected or a release above 2.3.32 exists, tools reading the structured data will keep flagging current installs. Document the dispute rather than suppressing the rule.

    Sourcing note

    Checked against primary sources: the CVE Program record for CVE-2024-11080 retrieved from cveawg.mitre.org on September 5, 2026, which supplied the affected block, the reserved and published dates, the disclosure timeline and the researcher credit; the NVD record for the same CVE, retrieved twice with different query forms; and the WordPress.org listing and version-history page for the post-grid plugin, which supplied the current version, last-updated date, changelog and install count. The WPScan entry is included as a secondary source and is cited for what it publishes, not as confirmation of the flaw.

    Could not reach: Wordfence’s own threat-intelligence entry for this vulnerability, which the CVE record links, does not render to automated retrieval, so the patched version Wordfence states on that page β€” which may resolve the contradiction β€” is not established here. We also could not retrieve the plugin’s raw readme.txt from the plugin repository’s version-control host, so the changelog above comes from the rendered WordPress.org page, which can lag a release by some hours.

    Unresolved: which of the two version ranges is correct, and whether a release above 2.3.24 exists that WordPress.org had not yet published at the time of writing. PickPlugins has issued no public statement we could find. There is no indication in any source that this flaw has been exploited, and it is not in CISA’s Known Exploited Vulnerabilities catalog.

  • AVideo’s statistics endpoint returns every viewer’s password hash, and the project’s own advisory says the hash logs you in

    AVideo’s statistics endpoint returns every viewer’s password hash, and the project’s own advisory says the hash logs you in

    Five more CVE records landed against the open-source video platform on Saturday afternoon, bringing the 30-day total to 46, and not one of them names a version to upgrade to.

    What happened

    Five CVE records for WWBN AVideo, the self-hosted open-source video-sharing platform, were published to the National Vulnerability Database at 1:18 p.m. UTC on Saturday, September 5, 2026. All five arrived within a second of one another. All five carry [email protected] as the source identifier, meaning VulnCheck assigned them as the CNA. Two are rated critical.

    The one that matters most is CVE-2026-86190, scored 9.1. NVD’s description reads: “WWBN AVideo contains a broken access control vulnerability in videoViewsInfo endpoints that returns complete user records including password hashes, recovery tokens, and live session identifiers to unauthenticated callers when a hash parameter is provided.”

    The project’s own advisory is more specific than the CVE record. GHSA-82q2-88mq-p44q, published by the AVideo maintainers on August 21, 2026, says the statistics endpoints serialize “the entire joined users record for every viewer, including the password hash, the password-recovery token, and the viewer’s live session identifier.” It puts a number on it: “An anonymous request therefore returns 52 fields per viewer, among them password, recoverPass, email, phone, address, birth_date, isAdmin and session_id.”

    The second critical, CVE-2026-86189 at 9.8, is a path traversal in notify.ffmpeg.json.php that lets an unauthenticated caller write a file to a path of its choosing. The authentication in front of it is a token called notifyCode. The project’s advisory, GHSA-cprx-fggj-7vpq, describes the check in one sentence: “notifyCode is tested for non-emptiness only. Its contents are never compared against anything.” AVideo mints those tokens as encryptString(time()), and accepts any string that decrypts to something non-empty β€” so any ciphertext the site has ever issued, including the video_id_hash values it publishes, satisfies the check.

    The other three published Saturday are lower-scored and still worth noting. CVE-2026-86186 (6.5) says the API “fails to enforce rate limits when clients send a bot User-Agent header,” defeating login brute-force protection. CVE-2026-86187 (5.9) says external-login account passwords are generated with rand() rather than a cryptographic generator, “producing only 31-bit integers,” and that “Attackers with access to password hashes can recover plaintext passwords in minutes.” CVE-2026-86188 (7.2) is cross-site scripting reachable by an unauthenticated caller when the YPTSocket plugin is enabled.

    The scale is hard to see from any single record. An NVD keyword search for AVideo, bounded to records published between August 6 and September 5, 2026, returns a totalResults of 46. Every one of the records visible in that result set carries VulnCheck as the source. The project’s own GitHub advisory list shows the same burst from the other side: pages of advisories dated August 27 through September 2, most of them credited to a single reporter, rajivraj.

    None of the 46 names a fixed version. AVideo’s most recent tagged release is 29.0, dated April 7, 2025 β€” seventeen months ago. NVD’s affected-version data for both criticals reads as versions 0 through 29.0 inclusive, and every GitHub advisory we read states its affected version as “current (e01e41ecc) and earlier” with “Patched versions: None.”

    The severity numbers do not agree, either. For the file-write flaw, the project rated it High at CVSS 8.2, the CVE record says Critical at 9.8, and VulnCheck’s own advisory page gives a CVSS v4.0 score of 9.3. For the data-exposure flaw the ranking inverts: the project called it Critical at 9.8, the CVE record says 9.1, and VulnCheck’s page again says 9.3. A reader checking all three sources gets three numbers per flaw, and the two flaws the maintainer scored 1.6 points apart come out identical under v4.0.

    Why it matters

    Read CVE-2026-86190 on its own and it is a bad information disclosure: an unauthenticated caller gets email addresses, phone numbers, birth dates and password hashes. Hashes are supposed to be the part you can afford to lose for a while, because cracking costs time and money.

    Two other AVideo advisories say that assumption does not hold here. GHSA-fq38-jp6c-q4cx, published by the project on September 1, 2026 and rated Critical at 9.8, states flatly: “Submitting the value of users.password as the password logs the account in. No encodedPass flag is needed; the ordinary browser login form is enough.” Its title says the rest β€” “any disclosure of users.password is a direct login with no cracking.” That advisory has no CVE identifier yet. And for accounts created through external login, CVE-2026-86187 says the underlying password is a 31-bit rand() value recoverable from its hash in minutes anyway.

    So the disclosure is not a step on the way to compromise. On the maintainer’s own account of its code, it is the compromise, and the session_id field in the same response skips the password question altogether by handing over a live administrator session. We have not tested that chain, and no one has published a combined exploit for it; what we are reporting is that three advisories written by the same project about the same codebase, taken together, describe it. Each half is the maintainer’s own statement, not an inference by a third party.

    The notifyCode defect is a different and more instructive kind of mistake. The code does real cryptography β€” it decrypts the token β€” and then treats the fact that decryption succeeded as proof that the caller was authorized. Nothing checks what came out. That is the same shape as two stories this site has run in the past two days: python-jose accepting a public key as an HMAC secret because the 2024 fix inspected the key’s format instead of its role, and Coolify logging a user in on an OAuth email match alone. In each case a security-relevant value is validated for shape and never for meaning.

    The version data deserves its own note, because it will mislead scanners. “Affected: 0 through 29.0” reads like a bounded range with a safe side above it. There is no safe side. 29.0 is the newest release AVideo has ever shipped, so the ceiling of the affected range and the current release are the same build β€” the same structure this site described in Coolify’s record earlier today, where the affected ceiling 4.3.17 is also the shipping version. A vulnerability-management tool that renders “≀ 29.0” as a range will imply an upgrade path that does not exist.

    Finally, the batch. Forty-six CVEs against one project in thirty days, from one CNA and largely one researcher, is the second such burst this week: MOOS-IvP took 33 VulnCheck-assigned CVEs at once on September 4. These bursts are good for the record and hard on defenders. They land as dozens of separate scanner findings against one asset, and the triage question stops being “which of these do I patch” and becomes “do I keep running this at all.” AVideo’s maintainers deserve some credit here: publishing your own advisories with “Patched versions: None” is more candid than the common alternative of sitting on them. Candor does not give an operator anything to install.

    What to do

    AVideo is self-hosted, so nobody will patch it for you and there is nothing to patch. Treat this as an exposure decision, not a patching one.

    • Find it. Look for AVideo installs by their /objects/ path prefix and endpoints such as notify.ffmpeg.json.php and the videoViewsInfo API. Shared hosting and marketing-department video portals are where these turn up unrecorded.
    • Take it off the public internet. With no fixed release available, network exposure is the only control you own. Put the instance behind a VPN or an authenticating proxy.
    • Block the two named endpoints at the reverse proxy if the instance must stay reachable. That is a mitigation standing in for a patch, and it addresses only the two flaws with CVEs today, not the other 44.
    • Assume every stored hash is already disclosed. Force a password reset for all accounts, invalidate all sessions, and rotate recovery tokens and stream keys. Because the hash functions as a password on this platform, a reset β€” not a “monitor for misuse” posture β€” is the containment step.
    • Do not triage on the CVE score alone. The maintainer and the CNA disagree by up to 1.6 points and in opposite directions on the two criticals; read the GitHub advisory, which is more specific than the CVE record in both cases.
    • Watch the repository’s advisory list, not its releases page. The releases page has not moved since April 2025. The advisory list moves several times a week.

    Sourcing note

    Checked against primary sources: the five NVD records for CVE-2026-86186 through CVE-2026-86190, retrieved from the NVD API on September 5, 2026; the AVideo project’s own GitHub Security Advisories GHSA-82q2-88mq-p44q and GHSA-cprx-fggj-7vpq (both published August 21, 2026) and GHSA-fq38-jp6c-q4cx (September 1, 2026); VulnCheck’s advisory pages for the two criticals; and the AVideo repository’s releases page. The 46-record count is NVD’s own totalResults for a keyword search bounded to August 6 through September 5, 2026, confirmed on two retrievals with different query forms.

    Not resolved: we could not confirm from a primary source whether AVideo has fixed any of these in unreleased code, because the repository’s tagged releases stop at 29.0 and the advisories scope affected versions by commit hash rather than version. We did not attempt to verify the hash-as-password chain against a running instance, and we are not aware of any public exploit that combines the three advisories. GHSA-fq38-jp6c-q4cx carried no CVE identifier at the time of writing. VulnCheck’s advisory pages give a CVSS v4.0 score but no disclosure timeline. No source indicates these flaws have been exploited.

  • Hummingbird’s debug-log guard checked for a class in the wrong namespace, and an unauthenticated cookie name became executable PHP

    Hummingbird’s debug-log guard checked for a class in the wrong namespace, and an unauthenticated cookie name became executable PHP

    A guard that was written, shipped, and never once executed: the header meant to make Hummingbird’s cache debug log inert was gated on a class name PHP could never resolve, and the plugin then wrote unsanitized cookie names into the file.

    What happened

    CVE-2026-83627 reached the National Vulnerability Database at 6:17 a.m. UTC on Friday, September 5, 2026, assigned by Wordfence, scored 9.8 with the vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H, and filed under CWE-94, improper control of generation of code. Its vulnStatus is Received. It carries no CISA KEV fields and no federal deadline. The affected product is Hummingbird, WPMU DEV’s page-speed and caching plugin, in all versions up to and including 3.21.0. The fix is 3.21.2. The WordPress.org listing for the free plugin reports “70,000+” active installations.

    The record is unusually specific about the mechanism, and the mechanism is worth reading in full because every step of it is ordinary.

    Hummingbird’s page-cache debug log is written to wp-content/wphb-logs/page-caching-log.php. That is a directly web-accessible file with a .php extension, which is a deliberate and common design: the file is supposed to open with a leading <?php die(); ?> header, so that anyone who requests it over the web gets nothing, while the plugin itself reads past the header. It is a standard WordPress idiom and it works fine when the header is there.

    The header was gated on class_exists( 'Filesystem' ). In Wordfence’s words, that check “can never match because class_exists() resolves string arguments in the global namespace while the class is Hummingbird\Core\Filesystem.” The string 'Filesystem' is not the class’s fully qualified name, so the test returns false every time, in every installation, for every version. When the log file was created during a front-end request, the protective header was “omitted entirely.”

    What then goes into the file is the second half. The plugin’s get_cookies() writes “the raw name of any cookie matching the wphb_cache_ prefix into that file without sanitization.” A cookie name is attacker-controlled, arrives on an anonymous request, and needs no account. Set a cookie whose name begins with wphb_cache_ and continues with PHP, make one request, then request page-caching-log.php directly. The file executes.

    Two preconditions keep this from being universal, and both belong in the first paragraph of anyone’s assessment. The site administrator must have enabled Page Caching with the Debug Log option, which Wordfence explicitly labels non-default. And the log file must have been created during a front-end request rather than an admin one. That second condition sounds like a narrow window until you read how it is reached: the plugin’s own “Clear logs” action, any cache flush, or — and this is the part that matters — the plugin’s daily log-rotation cron, which Wordfence says “can strip the protective header from an existing log file.”

    The fix shipped in changeset 3675836 to the plugin’s trunk on Tuesday, September 1, 2026, at 10:16 a.m., with the commit message “3.21.2 trunk.” It rewrites the guard so that the header is verified on every write rather than only when the file is absent: the new code computes whether the file is missing or does not already start with the guard prefix, and it returns without writing if the filesystem helper is unavailable. It does not change what get_cookies() writes. The defense is still that the file begins with die(); the change is that the plugin now checks that this is true each time instead of assuming it.

    Why it matters

    The interesting failure here is not that a check was missing. A check was written. Someone thought about the log file being web-accessible, decided it needed a guard, wrote the guard, and wrapped it in a conditional that was wrong in a way no test would catch and no code review would notice. class_exists( 'Filesystem' ) reads correctly in English. It is false in PHP, silently, forever, and the only symptom is a file that quietly lacks a header nobody was going to look at.

    This publication has now covered three variations on the same shape in one week. python-jose’s 2024 patch checked the key format rather than the key type, so a public key could still serve as an HMAC secret. Kestra’s authentication filter called endsWith on a path, which is not the same question as whether the path is an auth-exempt config route. goose’s recipe security scanner ran over every field except the two that execute commands. In each case a security control exists, is visible in the source, satisfies a reviewer reading for intent, and tests something adjacent to the thing that matters. These are not the same bug, but they fail the same way: the control’s presence is what gets audited, and its semantics are what break.

    The practical lesson is narrower than “write better tests,” because most of these would survive a unit test written by the same person who wrote the check. What catches them is asserting the outcome rather than the mechanism — not “does the guard branch run” but “does an HTTP request for this file return nothing.” A single integration test that fetched page-caching-log.php over HTTP and asserted an empty body would have failed on day one of this bug’s existence, in every version, without anyone needing to understand namespace resolution.

    The log-rotation cron deserves its own note, because it inverts the usual reasoning about non-default settings. Normally a non-default configuration is a filter that shrinks the affected population and keeps shrinking it: the fewer people who turned it on, the smaller the problem. Here, among sites that did turn Debug Log on, the vulnerable state is not something an administrator has to walk into. It arrives on a timer. A site that was protected because its log file happened to be created in an admin context becomes unprotected the next time rotation runs. “We enabled that once for troubleshooting and forgot about it” is the exact population at risk, and it is a population that will not remember to check.

    On scale, be precise rather than dramatic: 70,000-plus is WordPress.org’s active-install figure for the free plugin, it is a rounded band rather than a measurement, and the vulnerable subset is only those installations with Page Caching and Debug Log both on. Nobody knows that number, including Wordfence. There is no evidence of exploitation from anyone, and the CVE carries no KEV listing. What makes this worth acting on quickly is not that it is being exploited; it is that the fix is now public in a readable trac diff against a plugin whose source is downloadable by anyone, and the exploitation path is one cookie and two HTTP requests.

    What to do

    Update Hummingbird to 3.21.2 or later. Versions through 3.21.0 are affected; 3.21.2 is the fixed release.

    Before or immediately after updating, check whether you were in the vulnerable configuration and whether anything used it. In the Hummingbird settings, look at whether Page Caching is enabled and whether the Debug Log option under it is on. Then look on disk: if wp-content/wphb-logs/page-caching-log.php exists, open it and read the first line. If it does not begin with a PHP header that terminates execution, that file was web-readable, and its contents were served to anyone who asked. Search it for anything resembling PHP tags, and for cookie names beginning with wphb_cache_ that do not look like cache keys.

    Treat a hit there as a possible code-execution event, not as a logging oddity: check for recently modified or unfamiliar PHP files across the webroot, review your access logs for direct requests to page-caching-log.php, and rotate credentials that a web shell would have reached. Then turn the Debug Log option off. It is a troubleshooting setting, and the safest state for a diagnostic log that writes attacker-controlled strings into an executable file extension is not running.

    Sourcing note

    CVE-2026-83627 was read from the NVD API by CVE ID; the description quoted here is Wordfence’s, reproduced from that record, and the published timestamp, CVSS vector, CWE, and absence of CISA KEV fields come from the same retrieval. The fix was checked against changeset 3675836 on plugins.trac.wordpress.org, which supplied the September 1, 2026 timestamp, the commit message, and the substance of the diff. The active-install figure and the current version are WordPress.org’s own, read from the plugin’s listing page.

    Not reached: Wordfence’s own threat-intelligence page for this vulnerability returned no readable content on two attempts, so the researcher credit and Wordfence’s disclosure timeline are not reported here. WPMU DEV has published no standalone advisory that this desk located, and was not contacted. This desk did not test the vulnerability, and the exploitation description above is Wordfence’s account of it rather than an independent reproduction.