Hoe CTEM er in de browserlaag uitziet: een third-party script, vijf bevindingen
Kort antwoord: Continuous Threat Exposure Management (CTEM), het door Gartner gedefinieerde framework voor continue exposure-reductie, breekt in de meeste enterprise-programma's af bij de browserlaag. c/side's live analyse van een enkele Skeepers customer-feedback widget op een grote internationale retailbank vond twee hoge en drie medium bevindingen, waaronder een servergestuurd subscript dat ontbrak in de Content Security Policy en een 360-dagen trackingcookie met scope op het auth-subdomein van de bank, ondanks nul eerdere hits in threat databases. Dit artikel koppelt elke bevinding aan de vijf CTEM-fasen en laat zien waarom PCI DSS 4.0.1 clausules 6.4.3 en 11.6.1 meer vragen dan een scriptinventaris.
Een grote internationale retailbank laadt een customer-feedback widget op haar hoofdsite. De widget zet een 360-dagen trackingcookie met scope op het volledige bankdomein, inclusief het authenticatiesubdomein. Hij injecteert dynamisch een subscript waarvan de bestandsnaam runtime door de server van de leverancier wordt bepaald, en dat subscript staat niet in de eigen Content Security Policy van de bank. De loginpagina's hebben helemaal geen CSP.
Niets daarvan is hypothetisch. Dit is wat c/side vond in een diepgaande analyse van een Skeepers / MyFeelBack script dat op een live bankomgeving draaide.
Dit artikel gebruikt die echte analyse, geanonimiseerd maar met leveranciersnamen behouden, om te laten zien hoe Continuous Threat Exposure Management (CTEM) eruitziet wanneer het echt op de browserlaag wordt toegepast, en waar de meeste programma's de cyclus open laten.
TL;DR
- CTEM, Gartners framework om exposure als een doorlopende cyclus te behandelen, heeft vijf fasen: scoping, discovery, prioritering, validatie en mobilisatie. De meeste programma's dekken de eerste twee en stoppen bij de browser.
- Een live analyse van een enkele Skeepers-widget op een internationale bank vond twee HIGH en drie MEDIUM bevindingen, waaronder een servergestuurd subscript buiten de CSP-allowlist.
- De authenticatiepagina's van de bank hadden geen CSP-header, in schijnbaar conflict met PCI DSS 4.0.1 clausule 6.4.3.
- Een 360-dagen trackingcookie was gescoped op het hele bankdomein en reisde mee met loginflows.
- De mediane third-party inclusion chain op het moderne web is drie niveaus diep, met een maximaal geobserveerde diepte van 2.285 (Web Almanac 2025).
- Magecart- en skimmeractiviteit compromitteerde meer dan 23 miljoen online transacties in 2025 (Recorded Future via Mastercard).
- Zichtbaarheid zonder enforcement is documentatie, geen bescherming.
Wat is CTEM, en waar breekt het meestal?
CTEM is Gartners framework om exposure als een continue cyclus te behandelen over vijf fasen: scoping, discovery, prioritering, validatie en mobilisatie. Het punt van die cyclus is dat exposure voortdurend verandert, dus de reactie moet ook continu zijn.
De meeste securityprogramma's hebben echte vooruitgang geboekt op de eerste drie fasen voor traditionele assets. Cloudconfiguraties worden gescand. Identity sprawl wordt in kaart gebracht. Vulnerabilities krijgen scores.
Daarna breekt de cyclus bij validatie en mobilisatie voor alles wat in de browser draait.
Browser-CTEM versus cloud-CTEM
| CTEM-fase | Cloud en identity | Browserlaag |
|---|---|---|
| Scoping | Volwassen | Vaak overgeslagen |
| Discovery | Sterke tooling | Gedeeltelijk, vooral via tag managers |
| Prioritering | Risicogescoord | Zelden gescoord |
| Validatie | Pentests, BAS | Bijna nooit getest |
| Mobilisatie | Patchen, isoleren, intrekken | De marketingafdeling mailen |
Browser-exposure wordt niet gemobiliseerd omdat het securityteam die meestal niet kan mobiliseren. Ze kunnen een script zien. Ze kunnen een ticket schrijven. Ze kunnen niet voorkomen dat het script bij de volgende pageload draait.
Dat is het gat. De walkthrough hieronder laat zien hoe dat gat er in productie uitziet.
Case study: een script, vijf CTEM-relevante bevindingen
Het script in kwestie is de primaire loader voor de Skeepers, voorheen MyFeelBack, customer-feedback widget. Het wordt gehost op cdnactor.myfeelback.com en geladen op algemene pagina's van de hoofdsite van een internationale retailbank.
Het is niet kwaadaardig. Er waren geen YARA-hits, geen vermeldingen in threat databases en geen rode vlaggen in statische analyse. Dat is precies het punt. De meeste browser-exposure komt niet van duidelijk slechte actoren. Ze komt van goedgekeurde, contractueel ingekochte derde partijen waarvan niemand het gedrag actief bestuurt.
Bevinding 1: de CSP-allowlist is incompleet
De algemene pagina's van de bank sturen een Content Security Policy die *.myfeelback.com toestaat. Tot zover normaal.
Maar de Skeepers-loader injecteert runtime een subscript vanaf room.cxr.skeepers.io, stylesheets vanaf actor.cxr.skeepers.io en een GeoIP-call naar een AWS Lambda-endpoint op c7hn3ry3r4.execute-api.us-east-1.amazonaws.com. Geen van die domeinen staat in de CSP. De widget is dus gedeeltelijk stuk in productie, of de CSP wordt omzeild op manieren die het securityteam niet heeft geautoriseerd.
Dit is het soort mismatch dat een eenmalige leveranciersreview nooit ziet. Het script levert op dag een een *.myfeelback.com URL. Het runtime-gedrag trekt zes maanden later, na een corporate rebrand, vanaf *.cxr.skeepers.io. CTEM-grade discovery moet de echte runtime calls volgen, niet het contract.
Bevinding 2: een servergestuurd subscript met bewegende hash
De loader bouwt runtime een URL met deze vorm:
https://room.cxr.skeepers.io/lib/frontend/handy/js/libraries/{themeDeployment}-libraries.js
Het deel {themeDeployment} wordt door de server van de leverancier bepaald. De hash van de loader blijft stabiel. De hash van wat hij binnenhaalt verandert wanneer Skeepers dat wil. Een statische review van de loader slaagt op maandag en mist een subscript-swap op dinsdag.
Dit is het klassieke browser supply-chain patroon. Polyfill.io werkte in 2024 op dezelfde manier: een schone primaire scriptlaag, een muteerbare tweede payload en geen integrity check vanaf de hostpagina. Zodra de tweede laag omslaat, wordt elke bezoeker van elke site die het primaire script laadt een doelwit.
CTEM-validatie betekent in deze context continu fingerprinten van de runtime-geinjecteerde code, niet alleen van de loader.
Bevinding 3: een 360-dagen trackingcookie op het apex-domein
De widget zet een cookie met de naam _MFB_ met deze eigenschappen:
- Domein: het volledige bank-apex, inclusief het authenticatiesubdomein
- Verlooptijd: 360 dagen
- Inhoud: een Base64-gecodeerde blob met een persistente random visitor ID van 11 tekens, tellers voor campagne- en deploymentbezoeken, paginabezoekgeschiedenis, kliktellers, session TTL en CSS-selectors
Tegelijk schrijft de widget 15 keys naar localStorage en synchroniseert die bij elke pageload terug naar de cookie.
Daar volgen een paar dingen uit:
- De apex-scope betekent dat de cookie meereist met requests naar het authenticatiesubdomein, ook al wordt de widget daar niet geladen.
- Een 360-dagen pseudonieme identifier op een bankomgeving vereist expliciete GDPR / CNIL-toestemming en een gedocumenteerde retentiegrond. Dat is een Record of Processing Activities (ROPA)-vraag, niet alleen een securityvraag.
- De cross-storage sync tussen cookie en
localStoragebetekent dat standaard cookies wissen de visitor ID niet reset.
Dit is precies het long-tail privacy exposure-type dat CTEM-frameworks tijdens prioritering moeten bovenhalen.
Bevinding 4: geen CSP op de authenticatiepagina's
Dit is de ernstigste bevinding. De loginflow van de bank verstuurt geen Content Security Policy-header.
Het Skeepers-script wordt daar niet geladen. Maar dat is niet het punt. Het punt is dat elk toekomstig script, een marketingtag, A/B-testingtool of gecompromitteerde leverancier, op de loginflow zou draaien zonder restrictie en met volledige DOM-toegang tot de credentialvelden.
PCI DSS 4.0.1 clausule 6.4.3 vereist een mechanisme om scripts op betaalpagina's te bevestigen en autoriseren. Clausule 11.6.1 vereist een tamperdetectiemechanisme op die pagina's. Geen van beide wordt voldaan door volledige afwezigheid van een header.
De infrastructuur bestaat. Er draait al een CSP-reporting endpoint voor de algemene site. Het is alleen niet uitgebreid naar de meest gevoelige pagina's van de property.
Bevinding 5: de survey rendert in het host-DOM
Wanneer een survey triggert, injecteert de widget #mfbIframeOverlay en #mfbIframeBlock direct in document.body. Dat klinkt onschuldig, en voor de survey zelf is het dat ook. Maar het betekent dat het dynamisch geladen subscript, het script met de bewegende hash, in dezelfde origin als de bankpagina draait. Zelfde DOM-toegang, zelfde formuliertoegang, zelfde cookietoegang.
Er wordt een keydown listener toegevoegd voor accessibility, als Tab-focus trap. Die exfiltreert vandaag niets. Maar de listener hangt aan de bovenste surveycontainer, en de code die hem bezit kan veranderen wanneer de leverancier een nieuwe theme deployment pusht. CTEM-prioritering zou dit moeten markeren als een afhankelijkheid van vertrouwen in het releaseproces van de leverancier.
Wat de analyse kostte, en wat ze vond
Ter context voor de CTEM-discovery en validatie zelf:
| Metriek | Waarde |
|---|---|
| Geanalyseerde scripts | 2 (primaire loader + subscript) |
| Aangeroepen tools | 20+ over script, infra, threat en gedrag |
| Totale runtime | 281,9 seconden |
| Risicobevindingen | 8 (2 HIGH, 3 MEDIUM, 3 INFO) |
| Bestaande threat-DB hits | 0 |
| YARA-matches | 0 |
Nul bestaande threat indicators. Twee HIGH-bevindingen. Dat is de asymmetrie waarvoor CTEM ontworpen is: de meest voorkomende browser-exposure is geen bekend-slecht script. Het is een goedgekeurd script dat dingen doet die nooit expliciet geautoriseerd zijn.
Waarom crawlers en traditionele scanners dit niet vinden
Een redelijke vraag is waarom geen van de bestaande tools van de bank deze bevindingen liet zien. Het antwoord is dat bijna niets in de standaard security stack de pagina uitvoert zoals een echte gebruiker dat doet.
Kijk naar wat een typische scanner ziet:
- Web application scanners (DAST) crawlen URLs en inspecteren responses. Ze laden de pagina niet in een echte browser, draaien JavaScript niet en wachten niet tot runtime-geinjecteerde scripts hun tweede payloads ophalen. De Skeepers-loader geeft 200 OK met geldige JS. Klaar.
- Zoekmachine- en SEO-crawlers renderen met een headless browser, maar scoren third-party scripts niet op securitygedrag. Ze geven om content, niet om cookies.
- Statische analyse (SAST) en SCA kijken naar code in je repo. Het Skeepers-script staat niet in je repo. Het wordt runtime geladen vanaf de CDN van iemand anders.
- CSP report-only mode kan violations detecteren, maar alleen voor domeinen waarvan je al weet dat ze relevant zijn. Het waarschuwt niet voor runtime-geinjecteerde subscripts waarvan URLs server-side na pageload worden beslist.
- Vulnerability scanners matchen CVEs tegen software-inventarissen. Er is geen CVE voor "de marketingwidget van je leverancier zet een 360-dagen cookie op je auth-subdomein."
- Penetratietests zijn punt-in-tijd. De hash van de Skeepers-loader had geen observatiehistorie in de 90-dagen window. De hash van het subscript verandert wanneer de leverancier een nieuw thema pusht. Een pentest in maart vertelt niet wat er in oktober laadt.
De banksite heeft CSP-infrastructuur, een CSP-reporting endpoint en een securityteam dat weet wat het doet. Niets daarvan ving deze bevindingen, omdat geen van die tools de runtime browseromgeving continu bekijkt.
Dit is de structurele reden dat de browser in de CTEM-blinde vlek blijft. De exposure zit niet in code die iemand scant. Ze zit in code die laadt, muteert en draait op de machine van de gebruiker, in een context die eindigt wanneer de tab sluit. Dit vinden vereist runtime-observatie, niet repo- of netwerkobservatie.
Waarom visibility-only tools de cyclus niet sluiten
De Skeepers-walkthrough is het type output dat een visibility-only tool kan produceren. Het moeilijke deel komt daarna.
| Aanpak | Ontdekt scripts | Scoort risico | Detecteert verandering | Stopt uitvoering |
|---|---|---|---|---|
| Tag managers | Ja | Nee | Gedeeltelijk | Nee |
| Alleen CSP | Nee | Nee | Gedeeltelijk | Ja, maar grof |
| Browsersecurity met visibility eerst | Ja | Ja | Ja | Nee |
| Browsersecurity met enforcement eerst | Ja | Ja | Ja | Ja |
Zonder de laatste kolom heeft het securityteam maar een mobilisatiepad: een ticket naar het team dat de leveranciersrelatie bezit, meestal marketing of CX. Dat ticket concurreert met productwerk. De leverancier pusht een nieuw subscript voordat het ticket gesloten is. De cyclus herhaalt zich.
Dit is de operationele reden dat CTEM vastloopt bij de browser, zelfs in goed uitgeruste ondernemingen.
Waarom de bredere cijfers securityleiders moeten zorgen baren
De Skeepers-walkthrough is een script op een site. Het totaalbeeld is veel groter.
- De mediane third-party inclusion chain op het moderne web is 3 niveaus diep, met een maximaal geobserveerde diepte van 2.285 (Web Almanac 2025).
- Skimmer- en Magecart-achtige aanvallen compromitteerden meer dan 23 miljoen online transacties in 2025 (Recorded Future via Mastercard).
- De meeste CTEM-tooling behandelt deze laag als iemand anders zijn probleem.
Een bank die twee Skeepers-scripts laadt is een klein geval. Een e-commerce checkout die 80 tot 200 third-party scripts laadt is normaal. Exposure schaalt met scriptcount, inclusion-chain diepte en het tempo waarmee leveranciers wijzigingen pushen.
cside mappen op de CTEM-cyclus met deze case
Zo ziet elke CTEM-fase eruit voor dit ene script wanneer het cside-platform de runtime control-laag is.
| CTEM-fase | Wat dit in de browser betekent | Skeepers-voorbeeld |
|---|---|---|
| Scoping | Bepalen welke sites en pagina's in scope zijn | Alle banksubdomeinen, met extra scherpte op de authflow |
| Discovery | Alle first-party, third-party en fourth-party scripts inventariseren | Loader + runtime subscript + GeoIP Lambda + 3 CSS-endpoints |
| Prioritering | Scripts scoren op datatoegang en gedrag | 360-dagen cookie op auth-subdomein, servergestuurd subscript: HIGH |
| Validatie | Testen wat scripts echt doen, niet wat ze claimen | CSP-gat bevestigen, cookiescope bevestigen, subscript fingerprinten |
| Mobilisatie | Uitvoering stoppen, beperken of toestaan | Widget beperken tot niet-auth pagina's, hash van subscript pinnen, alerten op verandering |
De screenshots die veel teams terugsturen zeggen hetzelfde zodra cside is uitgerold. Ze wisten dat het third-party landschap groot was. Ze wisten niet dat het 16.000 scripts in een typische retailweek kon zijn. Ze wisten niet hoeveel daarvan PCI-review nodig hadden. Ze hadden geen snel pad van "we vonden een probleem" naar "het probleem kan niet draaien."
Voor e-commerce specifiek is dit de verdedigingslijn tegen Magecart- en web-skimmingbescherming, campagnes die blijven werken precies omdat het script blijft draaien.
Wat je van een browser exposure tool moet vragen
Als je tools evalueert en het CTEM-frame wilt behouden, zijn de vragen concreet:
- Ontdekt de tool scripts die runtime laden, niet alleen bij de eerste pageload?
- Volgt de tool de dependency chain tot fourth-party loads?
- Detecteert de tool wanneer de hash van een eerder schoon script verandert?
- Vertelt de tool wat elk script leest uit DOM, cookies en storage?
- Kan de tool een script in productie blokkeren of beperken zonder de site opnieuw te deployen?
- Mapt het bewijs naar PCI DSS 6.4.3 en 11.6.1?
- Hoe lang is het pad van detectie naar enforcement? Minuten, uren of een sprint?
Als het antwoord op de laatste drie iets anders is dan "ja, snel, ja", doet de tool CTEM-discovery zonder CTEM-mobilisatie.
Het frame dat telt
CTEM werkt omdat het exposure als continu behandelt. De browser past alleen in dat frame als de reactie ook continu is. Kwartaal-audits van scripts passen niet bij het tempo waarmee third-party code verandert. Tickets naar marketing passen niet bij de snelheid van een Magecart-skimmer.
De Skeepers-case is mild. Geen kwaadwillende actor, een reputabele leverancier, een bekend SaaS-patroon. Toch leverde hij twee HIGH-bevindingen op bij een grote internationale bank, waaronder een die direct mapt op PCI DSS 4.0.1 6.4.3.
Als een goedaardige leverancier bij een zorgvuldige klant zoveel exposure produceert, is de vraag niet of de browserlaag CTEM-dekking nodig heeft. De vraag is hoe lang ondernemingen haar buiten scope blijven behandelen.
Om je eigen exposure door dezelfde lens te zien, geeft browser script monitoring op een live property je de discovery-, prioritering- en enforcementcyclus in minder dan een uur.
Als je ook een visibility-led platform afweegt tegen een enforcement-led platform, loopt de Reflectiz vs cside vergelijking de trade-offs naast elkaar door.








