What happened
Brevo's published incident write-up gives the root cause in one sentence: a long-lived Cloudflare API key with full account permissions was stored in application source code and was obtained by the attacker. Brevo says the key was first misused in late August 2026, and that it found no injection of malicious content into customer-facing pages before September 14.
Brevo's timeline for September 14 (UTC): at 14:23 the attacker created a hostname for script delivery; at 14:28 a Worker was deployed and tested on low-traffic domains; at 14:42 it was routed to brevo.com, with impact starting at 15:01; at 16:07 it was updated to target the embedded JavaScript files and sibforms.com. Brevo opened a security incident at 19:33, removed the Worker at 20:30 and confirmed clean pages and scripts at 20:42. Sansec, which reported the attack publicly, puts the malicious window on customer-facing scripts at roughly 16:05 to 20:13 UTC.
Sansec names the affected customer-facing files as cdn.brevo.com/js/sdk-loader.js,
cdn.brevo.com/js/brevo-conversations.js and the Conversations widget host, plus
hosted signup and unsubscribe forms on sibforms.com. Payloads were served from several
cdn*.sendibt1.com hostnames, a domain Sansec describes as Brevo-owned, and Sansec
notes that a certificate for cdn.sendibt1.com was created on August 25, 2026, which
fits Brevo's own "late August" date for the first misuse of the key.
The payload had two branches. Ordinary visitors got a fake Cloudflare check followed by ClickFix instructions (press Win+R, paste, run). On WordPress sites where an administrator was logged in, the script tried to upload a malicious plugin that Sansec describes as a persistent backdoor. Brevo's write-up says the Worker rewrote responses at the edge and removed security headers such as Content-Security-Policy, so its origin servers and files stayed unmodified the whole time. Anyone comparing origin files to a known-good copy would have found nothing.
This was Brevo's second incident that week. SecurityWeek reports that on September 10 attackers abused a SAML single sign-on weakness to compromise 138 Brevo customer accounts, exporting contacts from 43 and sending phishing from 6; cryptocurrency wallet maker Trezor was among them, and BleepingComputer reports Trezor saying the resulting phishing reached 347,000 of its users' email addresses. The two incidents are described separately by Brevo and the reporting outlets.
Why it matters if you run public infrastructure
If your pages include a vendor's script tag, that vendor's edge configuration is part of your attack surface. Brevo customers did nothing wrong and changed nothing, and their visitors were still served malware on their own pages. The same is true of every chat widget, form embed, analytics tag and tag manager on your site: each one is a standing grant of script execution to somebody else's infrastructure, and in this case to whoever held one API key.
Three details make this incident worth studying. First, the compromise sat at the CDN layer, not in a repository or on a server, so integrity checks against origin files and source control saw nothing. Second, the loader-script pattern (a small script that pulls in more code) is exactly the pattern that Subresource Integrity cannot pin, because the vendor changes the file on purpose. Third, the attacker's preparation left a public trace weeks earlier: new hostnames and a certificate in late August. Brevo was the party positioned to see that, not its customers.
For card-accepting sites, PCI DSS 4.0 requirement 6.4.3 already asks for an inventory and authorization of every script on payment pages. This is the scenario it was written for.
What to check this week
- If you embed Brevo forms, chat or the SDK: follow Brevo's guidance. Anyone
who ran the pasted command should treat that computer as compromised. WordPress administrators
should look for plugins installed on September 14 (Sansec suggests searching access logs for
POST requests to
/wp-admin/update.php?action=upload-pluginthat day). Users who logged in through brevo.com should change passwords and review API keys. - List every third-party script host your pages load. Not the ones you remember adding: the ones actually referenced in the markup today, including checkout, login and account pages.
- Decide, per script, whether it needs to run on sensitive pages. A marketing chat widget on the payment page is a risk you can remove instead of manage.
- Use Subresource Integrity where the file is pinned, and self-host libraries that do not change. For loader scripts that cannot be pinned, a Content-Security-Policy that lists exactly which script hosts may load is the control that can cut off a second stage fetched from another host. Whether it would have blocked every part of this payload depends on how the injected code fetched it, which the published write-ups do not fully describe.
- Audit your own long-lived API keys, especially CDN and DNS provider tokens. Brevo's fix was short-lived, narrowly scoped tokens and alerting on Cloudflare audit events. The same fix applies to anyone whose CDN account can rewrite what their visitors receive.
How Attack Surface Scan covers this
The page crawl records every third-party script host referenced by your pages, which gives you
the supply-chain inventory described in Web page and
privacy checks, and raises web.third-party-script-no-sri for scripts loaded from
another domain without an integrity hash. A missing Content-Security-Policy is raised as
headers.missing-csp (see the headers
guide and the CSP builder).
What it would not have done: the crawl reads markup and headers and never executes JavaScript, so it would not have seen a vendor's script turn malicious during a five-hour window. It also only scans hosts under domains you have verified, so it watches your pages, not Brevo's CDN. The part of this story it maps to directly is on the vendor's side: certificate transparency for your own domains is read every 15 minutes, and new hostnames join the inventory and change feed (see Certificates), which is how a hostname and certificate created by someone holding your CDN key weeks in advance can become visible to the team that owns the domain. A certificate from a CA outside your authorized list also goes to the unknown-certificate queue; one issued by a CA you already use would show up as a new name, not as an unknown issuer.
Sources
- Brevo status page: incident write-up (September 14, 2026)
- Sansec: Brevo supply chain attack hits 100k+ sites with WordPress backdoors and ClickFix malware
- BleepingComputer: Brevo supply-chain attack injected ClickFix scripts on customer sites
- SecurityWeek: Brevo supply chain attack injects malware into 100,000 websites