I removed a Brevo integration from a corporate website where it had been installed for years. We no longer used it. Its code had remained in the site.

During another check, I found an expired domain on a list of permitted sources. Looking it up showed it for sale at 50 dollars. The configuration still named a domain that somebody else could acquire.

These two discoveries, in a context I am keeping anonymous, do not demonstrate a compromise. They establish two remnants of earlier decisions: third-party code retained without a use, and a permission covering an expired domain. Their significance depends on what the browser or application can still do with them.

Closing a tool’s account does not remove its script

Loading an external script follows a specific chain: the browser receives a website page, finds the script’s address in it, then requests code from that address. While the reference remains active in the page, the browser can make that request. The marketing team no longer using the tool does not change the page’s contents.

The Brevo incident of 14 September 2026 documents what can pass through that chain. Brevo’s report describes a compromised Cloudflare API key followed by malicious code injected into content delivered to visitors, including scripts embedded on customer sites. The original files were not modified.

I learned about the incident after removing our integration. That places the removal neither before nor after the attack, and I have no evidence establishing a compromise of our website.

Verifying the removal of such a script requires evidence from the pages and browser requests: the reference is absent from the affected pages and navigation no longer loads it. Nobody signing in to the provider’s dashboard does not answer that check.

A permitted domain is not necessarily a loaded domain

A Content Security Policy, or CSP, can restrict the sources of certain resources. An entry grants permission. It does not, by itself, create a request to the domain.

Examining the risk requires distinguishing two cases. These are illustrative configurations, not a reconstruction of the company’s setup.

Configuration Consequence
Domain permitted, no resource requested Permission exists but causes no loading by itself
Domain permitted and a script requested there The browser can request the script from the domain’s current holder, subject to other controls

In the second case, acquiring the domain may allow the content supplied at that address to be changed. In the first, a loading path or another flaw is still needed to use the permission. The directive also determines what is permitted: permission for an image does not grant permission for JavaScript. The script-src documentation describes that control.

The screenshot of my lookup shows a purchase and renewal price of 50 dollars. It shows neither a loaded resource nor an attack, and says nothing about the domain’s current availability. It records the reason for reviewing the entry.

An application’s icon does not describe its permissions

I have also encountered hundreds of accumulated applications in Microsoft 365 and HubSpot, including unused ones. Their number does not establish how many retain access to data.

A simple demonstration compares two fictional permissions. “Read the signed-in account’s name” and “read its contacts” could sit behind two installed applications. The latter requires examining which contacts are accessible and the scope of the grant. Attributing that same contact access to the former would be incorrect.

A review therefore needs to retain the actual permissions found, the identity they apply to and the use that justifies them. Microsoft describes how to review and revoke application permissions. A list of names or a screenshot of icons cannot replace that information.

Removal needs an observable result

For these three types of removal, the expected results need checking in different places.

Removed object Expected verification
Website script Reference removed and no loading on the affected pages
Domain permitted in the CSP Entry absent from the policy actually served, with retained resources still working
Application permission Grant revoked, followed by verification of the relevant access according to the service and its revocation delays

Removal can also break an active use. Before revoking a permission, the process using it needs to be identified. Afterwards, both that process and the removed access need checking. Crossing an application’s name out in a spreadsheet establishes neither result.

Three findings require different follow-up work

The Brevo integration no longer had a use and was removed. The expired domain appeared in a trust configuration and required examination of possible loading paths. The accumulated applications needed their permissions read before their access could be characterised.

Grouping them as “unused tools” would have hidden those differences. One was code to remove from a site, another was a permission to review, and the others were sets of rights to examine application by application.

The security debt described here lies in decisions left unfinished after a use ended. It belongs among the five faces of technical debt, with a particular constraint: a forgotten permission does not become harmless because it generates no support tickets.

Resources for this article

Continue reading

The five faces of technical debt

The website responds, but the invoices never arrive