Back to Intelligence

Brevo Supply Chain Attack: Compromised API Key and Malicious Cloudflare Worker Injected Skimmers Into 100,000 Websites — Detection and Remediation Guide

SA
Security Arsenal Team
September 19, 2026
12 min read

A supply chain compromise at Brevo — the email marketing and CRM platform formerly known as Sendinblue — has resulted in malicious script injection across roughly 100,000 websites. According to SecurityWeek's reporting, attackers leveraged a compromised API key to deploy a rogue Cloudflare Worker, which then injected malicious JavaScript into web properties served through Cloudflare. The injected code behaves like a classic web skimmer: it executes in visitors' browsers, capable of harvesting payment card data, credentials, and session tokens before the traffic ever touches your origin server.

This is a defender's nightmare scenario for three reasons. First, the malicious logic executes at the CDN edge, not on your infrastructure — your endpoint agents, WAF on the origin, and file integrity monitoring see nothing. Second, the injection path was a legitimate third-party integration that most organizations treat as trusted. Third, the blast radius (~100,000 sites) means many affected organizations don't even know they're affected yet.

If your organization uses Brevo for marketing automation, transactional email, or CRM — or if any of your sites sit behind Cloudflare with third-party integrations — treat this as an active incident until proven otherwise.

Technical Analysis

Attack Chain

From a defender's perspective, the attack unfolds in four stages:

  1. Credential Theft: Attackers obtained a valid Brevo API key. The reporting indicates the key itself was the initial access vector — no software vulnerability in the traditional CVE sense. This is credential compromise, not exploitation of a code flaw. No CVE has been assigned to this campaign.

  2. Abuse of Trusted Integration: With the stolen key, the attackers operated with the full privileges granted to that key. This is the critical lesson: API keys are bearer credentials — possession equals authorization. Any key scoped with write access to customer-facing infrastructure is a standing privilege escalation waiting to happen.

  3. Cloudflare Worker Deployment: The attackers deployed a malicious Cloudflare Worker. Workers are serverless functions that execute at Cloudflare's edge, in the request/response path before content reaches the end user. Because Workers can read and rewrite HTTP response bodies, a malicious Worker can inject arbitrary <script> tags into every HTML page served — without modifying a single file on the origin web server.

  4. Client-Side Payload Execution: The injected script loads in victim browsers. Typical Magecart-style behavior follows: hooking form submissions on checkout/login pages, exfiltrating data to attacker-controlled endpoints via fetch() or image beacons, often with domain lookalikes to evade casual inspection.

Why This Technique Is Dangerous

  • Edge-side injection is invisible to origin monitoring. File integrity monitoring (FIM), EDR, and host-based logging on your web servers will show nothing — the origin serves clean content.
  • Workers inherit trust. Requests are served from your own domain over valid TLS, so SOP, CSP (if misconfigured), and user trust all work in the attacker's favor.
  • Supply chain amplification. One compromised vendor key poisoned ~100,000 downstream properties. This mirrors the structural risk we've seen across the CDN and tag-management ecosystem in 2025 and into 2026 — third-party JavaScript remains one of the least controlled attack surfaces in most environments.

Exploitation Status

This is confirmed active exploitation in the wild at massive scale (~100,000 affected websites). This is not theoretical. There is no CISA KEV entry because no CVE exists — this is a credential/technique-based campaign, which means there is no patch to deploy. Detection and remediation are entirely behavioral and configuration-driven.

Detection & Response

The detection surface for this attack splits into three areas: (1) Cloudflare control-plane auditing — who created or modified Workers and routes; (2) client-side/content inspection — detecting unexpected script references in served pages; (3) network telemetry — egress to unfamiliar script-hosting or exfiltration domains from user sessions.

Sigma Rules

These rules target the observable behaviors: unauthorized Worker deployment via the Cloudflare API, and suspicious modification of JavaScript assets (for cases where injection occurs at the origin rather than the edge).

YAML
---
title: Cloudflare Worker Deployment or Route Modification via API
tid: 3f8a2c41-9b6e-4d15-a7c2-8e1f5a9b3d04
status: experimental
description: Detects API-driven creation or modification of Cloudflare Workers or Worker routes, the technique used in the Brevo supply chain attack to inject malicious scripts at the CDN edge.
references:
  - https://www.securityweek.com/brevo-supply-chain-attack-injects-malware-into-100000-websites/
  - https://attack.mitre.org/techniques/T1195/002/
author: Security Arsenal
date: 2026/02/20
tags:
  - attack.initial_access
  - attack.t1195.002
logsource:
  category: webserver
  product: cloudflare
detection:
  selection:
    cs-uri-stem|contains:
      - '/workers/scripts'
      - '/workers/domains'
      - '/workers/routes'
      - '/subdomain'
    cs-method:
      - 'PUT'
      - 'POST'
  condition: selection
falsepositives:
  - Legitimate CI/CD pipelines deploying Workers — correlate with change tickets and known deployer service tokens
level: high
---
title: Suspicious Modification of JavaScript Assets in Web Root
tid: 7c1d9e52-4a3b-4f08-b2e6-5d7a1c9f4e21
status: experimental
description: Detects creation or modification of .js files in web content directories outside of deployment windows, a common artifact of script injection and web skimming campaigns like the Brevo supply chain attack.
references:
  - https://www.securityweek.com/brevo-supply-chain-attack-injects-malware-into-100000-websites/
  - https://attack.mitre.org/techniques/T1189/
author: Security Arsenal
date: 2026/02/20
tags:
  - attack.persistence
  - attack.t1505
logsource:
  category: file_event
  product: windows
detection:
  selection:
    TargetFilename|endswith: '.js'
    TargetFilename|contains:
      - '\inetpub\'
      - '\wwwroot\'
      - '\htdocs\'
      - '\wp-content\'
      - '\public_html\'
  filter_deployers:
    Image|endswith:
      - '\msdeploy.exe'
      - '\w3wp.exe'
      - '\node.exe'
  condition: selection and not filter_deployers
falsepositives:
  - CMS plugin updates and manual developer edits — baseline against deployment schedules
level: medium
---
title: Outbound HTTP Requests to Cloudflare API Worker Endpoints from Non-Build Systems
tid: 9e4b7a13-2f6c-4d89-a1b5-6c3e8f2a7b19
status: experimental
description: Detects script interpreters and command-line tools making API calls to Cloudflare Workers management endpoints, potentially indicating an attacker using a stolen API key to deploy malicious Workers.
references:
  - https://www.securityweek.com/brevo-supply-chain-attack-injects-malware-into-100000-websites/
  - https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/02/20
tags:
  - attack.command_and_control
  - attack.t1071.001
logsource:
  category: process_creation
  product: windows
detection:
  selection:
    CommandLine|contains:
      - 'api.cloudflare.com/client/v4/accounts'
      - '/workers/scripts'
      - '/workers/routes'
    Image|endswith:
      - '\powershell.exe'
      - '\pwsh.exe'
      - '\curl.exe'
      - '\cmd.exe'
  condition: selection
falsepositives:
  - Infrastructure-as-code and automation accounts managing Cloudflare — restrict to known automation hosts
level: high

KQL — Microsoft Sentinel / Defender

If you ingest Cloudflare audit logs (available via Logpush) into Sentinel, this query surfaces unauthorized Worker lifecycle events. The second query hunts for user sessions pulling scripts from newly seen external domains — a strong skimmer signal when correlated against your known third-party script inventory.

KQL — Microsoft Sentinel / Defender
// Hunt 1: Cloudflare Worker creation/modification events from audit logs ingested via Logpush
// Map fields to your table schema; Cloudflare audit logs typically land in a custom table (e.g., CloudflareAudit_CL)
CloudflareAudit_CL
| where TimeGenerated > ago(30d)
| where ResourceType_s =~ "workers.script" or ResourceType_s =~ "workers.route" or ResourceType_s =~ "workers.domain"
| where ActionType_s in ("create", "update", "delete", "write")
| project TimeGenerated, ActorEmail_s, ActorIP_s, ActionType_s, ResourceType_s, ResourceID_s, NewValue_s
| order by TimeGenerated desc
// Baseline: alert when ActorEmail or ActorIP is NOT in your known deployer allowlist

// Hunt 2: Newly observed external script domains in proxy/firewall logs (last 7 days vs prior 30-day baseline)
let known_domains = CommonSecurityLog
| where TimeGenerated between (ago(37d) .. ago(7d))
| where RequestURL has ".js"
| summarize by tostring(extract(@"https?://([^/]+)", 1, RequestURL));
CommonSecurityLog
| where TimeGenerated > ago(7d)
| where RequestURL has ".js"
| extend ScriptDomain = tostring(extract(@"https?://([^/]+)", 1, RequestURL))
| where ScriptDomain !in (known_domains)
| where ScriptDomain !endswith ".cloudflare.com" and ScriptDomain !endswith ".googleapis.com" and ScriptDomain !endswith ".jsdelivr.net" and ScriptDomain !endswith ".cloudfront.net" and ScriptDomain !endswith ".unpkg.com"
| summarize FirstSeen = min(TimeGenerated), Requests = count(), DistinctUsers = dcount(SourceIP) by ScriptDomain, DeviceAction
| order by FirstSeen desc

Velociraptor VQL

For endpoint forensics on web servers (to rule out origin-side injection) and for identifying modified JavaScript assets within the campaign window:

VQL — Velociraptor
-- Hunt for JavaScript files in web content directories modified in the last 30 days
-- Adjust the glob path to your web root (IIS, nginx, Apache, WordPress, etc.)
LET web_roots = (
    'C:/inetpub/wwwroot/**/*.js',
    'C:/inetpub/**/*.js',
    'D:/websites/**/*.js'
)

SELECT FullPath, Size, Mtime, Atime, 
       read_file(filename=FullPath, length=2048) AS HeadBytes,
       if(condition=HeadBytes =~ 'eval\\(|atob\\(|fromCharCode|document\\.createElement\\(.script', 
          then='SUSPICIOUS_OBFUSATION', else='clean_head') AS Heuristic
FROM foreach(row=web_roots, query={
    SELECT FullPath, Size, Mtime, Atime FROM glob(globs=_value)
    WHERE Mtime > now() - 2592000
})
ORDER BY Mtime DESC

Remediation & Verification Script

The following script verifies whether your Cloudflare zones have unexpected Workers or routes deployed, and audits recent Worker-related activity. Run it with a read-only API token scoped to the zones under investigation.

Bash / Shell
#!/usr/bin/env bash
# Brevo Supply Chain Attack - Cloudflare Worker Integrity Audit
# Requires: curl, jq. Set CF_TOKEN (read-scoped API token) before running.
set -euo pipefail

CF_API="https://api.cloudflare.com/client/v4"
CF_TOKEN="${CF_TOKEN:?Set CF_TOKEN environment variable}"
AUTH="Authorization: Bearer ${CF_TOKEN}"
REPORT="worker_audit_$(date +%Y%m%d).txt"

echo "=== Cloudflare Worker Integrity Audit $(date) ===" | tee "$REPORT"

# Enumerate all accounts and zones visible to this token
accounts=$(curl -s -H "$AUTH" "$CF_API/accounts" | jq -r '.result[].id')

for acct in $accounts; do
  echo "[+] Account: $acct" | tee -a "$REPORT"

  # List all Workers scripts — review each against your known deployment inventory
  echo "  --- Workers Scripts ---" | tee -a "$REPORT"
  curl -s -H "$AUTH" "$CF_API/accounts/$acct/workers/scripts" \
    | jq -r '.result[]? | "    script: \(.id)  modified: \(.modified_on)"' | tee -a "$REPORT"

  # List Worker domains and routes
  echo "  --- Worker Domains ---" | tee -a "$REPORT"
  curl -s -H "$AUTH" "$CF_API/accounts/$acct/workers/domains" \
    | jq -r '.result[]? | "    domain: \(.hostname)  service: \(.service)"' | tee -a "$REPORT"

done

zones=$(curl -s -H "$AUTH" "$CF_API/zones?per_page=50" | jq -r '.result[].id')
for zone in $zones; do
  zname=$(curl -s -H "$AUTH" "$CF_API/zones/$zone" | jq -r '.result.name')
  echo "[+] Zone: $zname ($zone)" | tee -a "$REPORT"
  echo "  --- Worker Routes ---" | tee -a "$REPORT"
  curl -s -H "$AUTH" "$CF_API/zones/$zone/workers/routes" \
    | jq -r '.result[]? | "    route: \(.pattern)  script: \(.script)"' | tee -a "$REPORT"
done

echo ""
echo "[!] ACTION REQUIRED: Compare every script/domain/route above against your change management records."
echo "[!] Any unrecognized Worker should be deleted immediately and treated as an active compromise."

# Scan served pages for unexpected external script references
# Replace example.com with your domains
echo "=== External Script Reference Scan ===" | tee -a "$REPORT"
for site in "example.com"; do
  echo "[+] Fetching https://$site and extracting script sources..." | tee -a "$REPORT"
  curl -sL "https://$site" | grep -oE '<script[^>]+src="[^"]+"' \
    | grep -oE 'https?://[^"]+' | sort -u | tee -a "$REPORT"
done

Remediation

There is no patch for this attack — remediation is credential hygiene, control-plane auditing, and third-party script governance. Execute in this order:

Immediate (0-24 hours):

  1. Rotate all Brevo API keys. In the Brevo console (SMTP & API > API Keys), delete existing keys and generate new ones. Assume any key created before the disclosure date is compromised. Review Brevo's account security logs for anomalous key usage.
  2. Audit Cloudflare Workers across every account and zone using the script above. Delete any Worker, route, or Worker domain you cannot trace to an authorized change. Check Cloudflare Audit Logs (Manage Account > Audit Log, or via Logpush) for the full history of Worker creation/modification events, including actor IP and email.
  3. Inspect served pages, not origin files. Fetch your pages through Cloudflare (as a user would) and diff the HTML against what your origin serves. Any discrepancy in <script> tags is edge-side injection. Check checkout, login, and account pages first — skimmers target them preferentially.
  4. Hunt for downstream victim impact. If you find a malicious Worker, assume client-side data theft occurred from the deployment date forward. Determine what data the injected script could have accessed (payment fields, credentials, PII) and engage your breach counsel — PCI-DSS and state breach notification obligations may apply.

Short-term (24-72 hours):

  1. Enforce least-privilege on all third-party API keys. Inventory every vendor integration with API access to your infrastructure. Scope each key to the minimum permissions required; where the vendor supports IP allowlisting on keys, enable it.
  2. Enable Cloudflare Audit Log alerting. Configure Logpush to stream audit logs to your SIEM and alert on Worker lifecycle events (workers.script, workers.route create/update/delete) from unrecognized actors.
  3. Deploy Content Security Policy with strict script sources. A correctly scoped script-src directive blocks execution of scripts from unauthorized origins. Pair with report-uri/report-to so violations generate telemetry. For payment pages, PCI-DSS 4.0 requirements 6.4.3 and 11.6.1 already mandate script integrity management and change detection on payment pages — if you're PCI-scoped and not compliant here, this incident is your forcing function.
  4. Implement Subresource Integrity (SRI) on all third-party scripts you intentionally load, so tampered CDN-hosted scripts fail to execute.

Strategic (this quarter):

  1. Build a third-party script inventory. You cannot defend scripts you don't know about. Catalog every external JavaScript source across your web properties, assign an owner to each, and review quarterly. Alert when new script origins appear.
  2. Move API keys out of long-lived static credentials where possible — prefer short-lived OAuth tokens, workload identity, or keys fronted by a secrets manager with automatic rotation.
  3. Tabletop this scenario. A compromised marketing/SaaS vendor deploying code into your request path is no longer hypothetical. Your IR plan needs a runbook for third-party script compromise: who can pull a Worker, who can force a cache purge, who owns vendor communication.

This campaign is the 2026 iteration of a lesson the industry keeps re-learning: your supply chain's credentials are your credentials. The ~100,000 affected sites did nothing wrong on their own infrastructure — they trusted a vendor's API key, and that trust was exploited at the edge, beyond the reach of conventional endpoint and server-side controls. Audit your Workers now.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.