Content Security Policy for website-chatbots: Konfigurer widget, API, billeder og streaming sikkert
En praksisnær CSP til website-chatbots tillader kun de absolut nødvendige scripts, API-forbindelser, streams og billeder - uden unødvendige wildcards.

En website-chatbot i browseren består sjældent kun af en enkelt JavaScript-fil. En loader åbner widgetten, en API modtager beskeder, svar returneres som en stream, og profilbilleder eller medier ligger muligvis på et helt andet domæne. En Content Security Policy (CSP) gør disse veje synlige og begrænser dem: Browseren indlæser eller forbinder kun til det, websitet udtrykkeligt tillader.
Dette udgør et vigtigt ekstra beskyttelseslag mod Cross-Site Scripting og uventet tredjepartsindhold. En CSP reparerer dog hverken en usikker API, manglende autentificering, utilstrækkelig input-validering eller Prompt Injection. Den reducerer mulighederne for indskudt kode og begrænser rækkevidden af en fejl. Det afgørende er derfor en så lille og gennemtestet policy som muligt i stedet for en lang liste af generelt godkendte domæner.
Hvorfor chatbot-widgets kræver særlige CSP-regler
På en klassisk indholdsside er det ofte nok med ressourcer fra eget origin. En chatbot kommunikerer derimod videre efter indlæsningen. connect-src styrer blandt andet fetch(), XMLHttpRequest, EventSource, WebSocket og sendBeacon(). Det er præcis her, beskeder, streaming-svar, feedback-hændelser og eventuel telemetri kører. Mangler det rigtige origin, vises widgetten zwar, men den kan ikke svare.
Andre komponenter hører under deres egne direktiver. script-src bestemmer over widget-loaderen, img-src over avatarer og svarbilleder, style-src over stylesheets og font-src over eksterne skrifttyper. En iframe-baseret widget kræver desuden frame-src. default-src fungerer som fallback for mange ressourcetyper, der ikke er udtrykkeligt nævnt, men erstatter ikke en bevidst kortlægning.
Det vigtigste forarbejde foregår derfor ikke i en CSP-generator, men i browseren: Åbn en repræsentativ side, start en samtale, lad et langt svar streame, åbn kilder, send feedback og test fejl- og handoff-scenarier. I netværkspanelet kan du se de origins, der faktisk kontaktes. Dokumenter formålet, ressourcetypen og en ansvarlig person for hvert enkelt host.
De fire relevante dataveje: Godkend dem separat
1. Widget-script og initialisering
Hent om muligt loaderen fra en stabil, versionsstyret adresse. En tilladelse som script-src https: vil være for bred, da scripts fra et hvilket som helst HTTPS-domæne dermed bliver tilladt. Tillad i stedet det præcise CDN-origin, eller udbyd loaderen selv. Hvis integrationen kræver inline-kode, bør du bruge en nonce, der genereres på ny for hvert HTTP-svar, eller en passende hash. 'unsafe-inline' bør ikke blive en permanent hurtigløsning.
En nonce hører kun til på scripts, som server-skabelonen selv genererer. En middleware, der blindt føjer den samme nonce til ethvert eksisterende script-tag, vil også give tillid til indskudte tags. For et statisk, versionsstyret tredjepartsscript kan Subresource Integrity desuden hjælpe; ved filer, der ændres hyppigt, skal hashen dog opdateres kontrolleret.
2. API, Server-Sent Events og WebSocket
Almindelige POST-anmodninger og et svar, der streames via fetch(), kræver HTTPS-API-origin i connect-src. Server-Sent Events via EventSource hører også herunder. Til en WebSocket angiver du det konkrete wss://-origin udtrykkeligt. MDN gør opmærksom på, at 'self' ikke automatisk dækker WebSocket-skemaer i alle browsere. Der findes ikke et selvstændigt direktiv ved navn stream-src.
CSP og CORS løser forskellige opgaver. CSP bestemmer, hvor siden overhovedet må forbinde hen; CORS bestemmer på serversiden, hvilke origins der må læse et svar i browseren. En CSP-godkendelse løser derfor hverken en CORS-fejl eller et udløbet adgangstoken. En Same-Origin-proxy kan forenkle policyen, men skal stadig håndtere autentificering, rate limits, timeouts og fejlvideregivelse korrekt.
3. Billeder, avatarer og genererede medier
Tillad kun eget origin og det mediehøst, der faktisk anvendes, i img-src. data: er kun nødvendigt, hvis widgetten bruger små indlejrede billeder; blob: kun hvis browseren faktisk opretter billeder som en blob-URL. Hver ekstra kilde øger angrebsfladen. Hvis et billede først indlæses via fetch() og derefter konverteres til en blob-URL, kan både connect-src og img-src være berørt.
Test ikke kun standardavataren. Tjek forhåndsvisningsbilleder, kildescreenshots, filvedhæftninger, dark mode og fejlvisning for utilgængelige medier. URL-parametre kan bringe fortrolige oplysninger ind i CSP-rapporter; reporting-endepunkter bør derfor behandle rapporter dataminimeret og ikke opbevare dem på ubestemt tid.
4. iframe, styles, fonts og valgfrie workers
En widget, der er indlejret direkte i DOM'en, har som regel ikke brug for en fremmed frame. Så kan frame-src 'none' bevares. Hvis chatten derimod kører i en iframe, skal du udelukkende tillade dennes præcise origin. Dette skal adskilles fra frame-ancestors: Dette direktiv fastlægger på den leverede ressource, hvilke sider der må indlejre den. Widget-udbyderen skal derfor sætte det korrekte header-svar på sin iframe.
Det samme princip gælder for styles og fonts. Tillad konkrete hosts, og undgå 'unsafe-inline', så vidt integrationen tillader det. Workers eller lydfunktioner tilføjes kun, hvis produktet reelt anvender dem. En forebyggende godkendelse af blob:, hele wildcard-domæner eller vilkårlige mediekilder besværliggør fremtidige sikkerhedsaudits.
Et realistisk CSP-eksempel for en chatbot-widget
De følgende domæner er bevidst reserverede eksempeldomæner. Erstat dem med de origins, du finder i din egen netværksanalyse. Eksemplet forudsætter en ekstern loader, en HTTPS-API, en separat WebSocket til streaming og en mediehost. Det anvender ingen generelle wildcards:
Content-Security-Policy:
default-src 'self';
script-src 'self' https://cdn.chat.example 'nonce-{RANDOM}';
connect-src 'self' https://api.chat.example wss://stream.chat.example;
img-src 'self' data: https://media.chat.example;
style-src 'self' 'nonce-{RANDOM}';
font-src 'self';
frame-src 'none';
worker-src 'self';
object-src 'none';
base-uri 'self';
frame-ancestors 'self';
form-action 'self';
upgrade-insecure-requests;{RANDOM} står for en stærk værdi, der genereres på ny for hvert svar, og som er identisk i headeren og på de tilladte script- eller style-elementer. Hvis din widget bruger en iframe, erstatter du frame-src 'none' med det præcise widget-origin. Hvis den udelukkende bruger HTTPS-streaming via fetch() eller EventSource, bortfalder WebSocket-origin. Fjern enhver kilde, der ikke er brug for efter en fuldstændig funktionstest.
Policyen er et praksisnært udgangspunkt, ikke en universel skabelon. En moderne, streng CSP kan styre scripts endnu stærkere via nonces eller hashes og 'strict-dynamic'. Om det er muligt uden kompatibilitetsproblemer afhænger af, hvordan loaderen opretter yderligere scripts. Afklar denne proces med udbyderen, og test browsere, consent-tilstand samt deployment-varianter.
Fra Report-Only til håndhævet policy
Skift ikke til en ny policy uden først at have testet den. W3C-mekanismen Content-Security-Policy-Report-Only rapporterer overtrædelser uden at blokere ressourcer. På den måde opdager du glemte billedhosts, et afvigende streaming-origin eller inline-kode, før brugerne bliver berørt af det. OWASP anbefaler HTTP-headeren som den foretrukne leveringsvej; i modsætning til meta-elementet understøtter den også det fulde funktionsomfang.
- Opret inventar: Test widget-start, første besked, langt streaming-svar, kilder, billeder, feedback, handoff og samtykkeskift på flere sidetyper.
- Rul Report-Only ud: Start med den planlagte, snævre policy, og opsaml overtrædelser over en afgrænset periode. Filtrer browserudvidelser og andre ikke-reproducerbare støjsignaler fra.
- Begrund hver host: Udvid kun policyen, hvis en konkret produktfunktion kræver det pågældende origin. Undgå wildcards som reaktion på enkelte indberetninger.
- Test automatiseret: Tilføj end-to-end-tests, der sender en besked, afventer streaming og indlæser et billede. Tjek samtidig browserkonsollen for CSP-overtrædelser.
- Håndhæv og overvåg: Aktiver
Content-Security-Policy-headeren, hold parallelt øje med en endnu strengere Report-Only-variant, og sammenlign fejlrater.
En gradvis udrulning passer godt til en chatbot i Shadow Mode. For streaming-specifikke måleværdier kan artiklen om latensbudgetter og timeouts hjælpe. CSP-overtrædelser bør i den forbindelse betragtes som et selvstændigt signal: En timeout og en blokeret forbindelse kræver forskellig årsagsanalyse.
Typiske fejlkonfigurationer
- For brede kildelister:
*,https:eller store wildcard-domæner gør policyen bekvem, men svag og svær at auditere. - Kun den synlige start testes: Widgetten åbner sig, men streaming, feedback, billeder eller handoff fejler først senere.
'unsafe-inline'forbliver permanent: En midlertidig kompatibilitetshjælp erstattes ikke af nonces, hashes eller ekstern kode.- CSP forveksles med adgangskontrol: Policyen erstatter hverken rettigheder på serversiden, session-tjek eller beskyttelse mod misbrug af værktøjskald.
- Rapporter indeholder for mange data: Komplette URL'er, query-parametre eller brugerkontekst lander unødigt længe i overvågningen.
- Staging og produktion glider fra hinanden: Forskellige CDN-, API- eller WebSocket-hosts bliver først synlige efter go-live.
Selv en snæver script-src gør ikke automatisk en godkendt tredjepart sikker: Deres JavaScript kører med de rettigheder og muligheder, din side giver det. Tjek derfor leverandørskift, nye subdomæner og loader-opdateringer på samme måde som andre sikkerhedsrelevante afhængigheder. Artiklen om beskyttelse mod prompt injection supplerer denne browsergrænse med regler for RAG, værktøjer og data.
Tjekliste før go-live
- Er alle nødvendige origins fra reelle browsersessioner dokumenteret og fagligt begrundet?
- Tillader
script-srckun loaderen og kontrollerede scripts uden generel'unsafe-inline'? - Indeholder
connect-srcde præcise HTTPS-, EventSource- og eventuelle WSS-origins? - Er billede-, style-, font-, frame- og worker-kilder adskilt og defineret så snævert som muligt?
- Genereres nonces på ny for hvert svar og sættes kun på betroede elementer?
- Er samtykkeskift, lange streams, billeder, fejl, handoff samt desktop og mobile enheder blevet testet?
- Blev policyen først observeret i Report-Only og derefter håndhævet som en header?
- Behandles CSP-rapporter uden unødvendige personoplysninger eller fortrolige URL-data?
- Findes der en automatiseret regressionstest efter opdateringer af widget eller infrastruktur?
Konklusion
En god CSP for website-chatbots er ikke en samling af undtagelser, men et teknisk landkort over de tilladte veje i browseren. Adskil loader, API, streaming, billeder og iframe-ressourcer, tillad præcise origins, og indfør først policyen i Report-Only-tilstand. På den måde forbliver widgetten fully funktionel, mens uventede scripts og forbindelser får betydeligt mindre handlerum.
Kilder
Gør hjemmesidebesøg til bedre samtaler
Lancér en AI-chatbot, der er nyttig fra dag ét
Træn ChatReact med dit website, dokumenter og godkendte fakta, så besøgende får hurtigere svar, og dit team får færre gentagne forespørgsler.
Relaterede artikler
Fortsæt læsningen
Sådan tilføjer De en AI-chatbot til en hjemmeside uden at skade UX eller SEO
En udrulningsplan for at tilføje en chatbot til Deres hjemmeside, samtidig med at brugerrejsen, sidehastigheden og indholdsstrukturen bevares.

Optimering af AI-chatbot-svarstider: Latensbudget, streaming og timeouts
Hurtige chatbot-svar skabes langs hele den tekniske kæde. Sådan planlægger du latensbudgetter, streaming, timeouts, retries og sikre fallbacks.

Test AI-chatbot i Shadow Mode: Sikker overgang fra prototype til website-launch
Med Shadow Mode, klare kvalitet gates og en trinvist rollout tester website-teams AI-chatbots sikkert før den endelige launch.