Brevo: a stolen, hardcoded Cloudflare API key let an attacker inject ClickFix malware and a WordPress backdoor plugin via a CDN-edge Worker into up to 100,000 customer sites, defeating origin-side integrity checks
Brevo's own integrity checks never saw the tampering because the attacker rewrote pages at Cloudflare's edge, not on Brevo's servers
Defender actions
- Audit the bytes actually served by every third-party embedded widget or SDK script your organization uses (external synthetic monitoring, or Subresource Integrity pinning where the vendor supports it) since an edge-level compromise of the vendor's CDN account will not show up in the vendor's own origin-side integrity checks.
Analysis
Brevo (CRM/email-marketing platform, formerly Sendinblue) confirmed in a 2026-09-17 post-mortem that an attacker used a long-lived Cloudflare API key with full account permissions, hardcoded in Brevo's application source code, to create a malicious Cloudflare Worker on Brevo's own account, first misused as early as late August 2026 (Brevo, 2026-09-17). Brevo's own stated impact window ran 15:01 to 20:30 UTC on 2026-09-14 (5 hours 29 minutes), during which the Worker rewrote HTTP responses at the CDN edge on brevo.com and related domains, stripping security headers such as Content-Security-Policy; from 16:07 UTC the Worker additionally appended a malicious loader to three JavaScript files, the Brevo forms script, the Conversations widget and the SDK loader, that customers embed directly on their own sites, and extended the tampering to sibforms.com (Brevo, 2026-09-17). Because the edge rewrite never touched an origin file, Brevo's own standard integrity checks did not detect the change (Brevo, 2026-09-17). Visitors saw a fake Cloudflare human-verification page instructing them to press Win+R, paste and press Enter, a ClickFix lure that ran an attacker-supplied clipboard command to download Windows malware (Brevo, 2026-09-17), and did not activate for crawlers, developers or automated scanners (Sansec, 2026-09-16). On WordPress sites embedding an affected widget, a logged-in administrator's browser silently installed a plugin impersonating "Web Media Optimizer" that hides itself from the plugin list, persists via the must-use-plugins directory, beacons to an attacker server for a Base64-encoded next-stage JavaScript URL, caches the last-valid URL as a fallback, and carries a hardcoded authentication key that lets the attacker generate a valid WordPress-administrator login session without the account password (BleepingComputer, 2026-09-17). Sansec independently corroborated the root cause before Brevo's own confirmation, matching Last-Modified timestamps across injected and clean asset versions and finding an SSL certificate for the attacker's infrastructure issued 2026-08-25, pinning the attacker's access to at least that date (Sansec, 2026-09-16); Sansec estimates the affected embedded-script exposure reached up to 100,000 sites (Sansec, 2026-09-16), an upper-bound count of sites embedding the affected components, not a confirmed count of sites whose visitors received the payload. Brevo's post-mortem does not mention a separate SSO-hijacking incident it disclosed on 2026-09-10 that BleepingComputer reports led to a phishing campaign against Trezor customers, and BleepingComputer states Brevo did not respond to its question about whether the two incidents were connected (BleepingComputer, 2026-09-17).
Triage: a legitimate Brevo or Sendinblue widget script served from its normal CDN path is expected; the discriminator here is behavioral, not path-based; a fake human-verification overlay instructing a clipboard-paste-and-run action is never legitimate CDN content, and any WordPress site should treat a plugin absent from its own admin plugin list, yet present in the must-use-plugins directory, as compromised.
Cited evidence
A long-lived Cloudflare API key with full account permissions was stored in application source code and was obtained by the attacker. With it, they could create Workers, routes and DNS records on Brevo's zones without triggering an alert.
Because the Worker rewrote responses at the edge and removed security headers such as Content-Security-Policy, our origin servers and files remained unmodified and standard integrity checks did not detect the change.
The plugin also stores a backup copy of the last valid JavaScript URL so it can continue loading malicious code if the remote server becomes unavailable.
the plugin contains a hardcoded authentication key that allows attackers to generate a valid login session for a WordPress administrator account without knowing the account password.
Sources3
AI-generated · no human review · this permalink is the shareable record for the finding · verify operationally critical claims against the linked primary source.