Content Security Policy verkkosivuston chatboteille: Widgetin, API:n, kuvien ja streamauksen turvallinen salliminen
Käytännönläheinen CSP verkkosivuston chatboteille sallii vain todella tarvitut skriptit, API-yhteydet, streamit ja kuvat – ilman tarpeettomia villikortteja.

Verkkosivuston chatbot koostuu selaimessa harvoin vain yhdestä JavaScript-tiedostosta. Loader avaa widgetin, API ottaa viestejä vastaan, vastaukset palaavat streamina ja profiilikuvat tai muu media voivat sijaita toisella domainilla. Content Security Policy (CSP) tekee nämä reitit näkyviksi ja rajaa niitä: selain lataa resursseja tai muodostaa yhteyksiä vain sinne, minkä verkkosivusto on nimenomaisesti sallinut.
Tämä on tärkeä toinen suojakerros Cross-Site Scriptingiä ja odottamatonta kolmannen osapuolen sisältöä vastaan. CSP ei kuitenkaan korjaa turvatonta APIa, puuttuvaa autentikointia, heikkoa syötteiden validointia tai prompt injection -riskiä. Se vähentää injektoidun koodin toimintamahdollisuuksia ja rajaa virheen vaikutusaluetta. Siksi ratkaisevaa on mahdollisimman pieni ja testattu käytäntö, ei pitkä lista yleisesti sallittuja domaineja.
Miksi chatbot-widgetit tarvitsevat omat CSP-sääntönsä
Perinteisellä sisältösivulla riittävät usein saman originin resurssit. Chatbot taas jatkaa yhteydenpitoa latautumisen jälkeen. connect-src ohjaa muun muassa fetch()-kutsuja, XMLHttpRequestia, EventSourcea, WebSocketia ja sendBeacon()-kutsuja. Juuri tätä kautta kulkevat viestit, streaming-vastaukset, palautetapahtumat ja tarvittaessa telemetria. Jos oikea origin puuttuu, widget voi kyllä ilmestyä näkyviin mutta ei pysty vastaamaan.
Muihin osiin sovelletaan omia direktiivejään. script-src ratkaisee widget-loaderin, img-src avatarit ja vastauskuvat, style-src tyylitiedostot ja font-src ulkoiset fontit. iframe-pohjainen widget tarvitsee lisäksi direktiivin frame-src. default-src toimii varana monille resurssityypeille, joita ei ole nimetty erikseen, mutta se ei korvaa tietoista inventaariota.
Tärkein esityö ei siksi tapahdu CSP-generaattorissa vaan selaimessa: avaa edustava sivu, aloita keskustelu, anna pitkän vastauksen streamata, avaa lähteitä, lähetä palautetta ja testaa virhe- sekä handoff-tilanteet. Network-paneelista näet originet, joihin todellisuudessa otetaan yhteyttä. Dokumentoi jokaisesta hostista tarkoitus, resurssityyppi ja vastuuhenkilö.
Neljä olennaista datareittiä sallitaan erikseen
1. Widget-skripti ja alustus
Lataa loader mieluiten vakaasta ja versioidusta osoitteesta. Sallinta kuten script-src https: olisi liian laaja, koska se sallisi skriptit miltä tahansa HTTPS-domainilta. Salli sen sijaan tarkka CDN-origin tai tarjoile loader itse. Jos integraatio tarvitsee inline-koodia, käytä jokaiselle HTTP-vastaukselle erikseen luotua nonce-arvoa tai sopivaa hashia. 'unsafe-inline' ei saa jäädä nopeaksi pysyväksi ratkaisuksi.
Nonce kuuluu vain skripteihin, jotka palvelinpuolen template tuottaa itse. Middleware, joka lisää saman noncen sokeasti jokaiseen olemassa olevaan script-tagiin, antaisi luottamuksen myös mukaan ujutetuille tageille. Staattisen ja versioidun kolmannen osapuolen skriptin kohdalla Subresource Integrity voi lisäksi auttaa; usein muuttuvien tiedostojen hash on kuitenkin päivitettävä hallitusti.
2. API, Server-Sent Events ja WebSocket
Tavalliset POST-pyynnöt ja fetch()-kutsulla streamattu vastaus tarvitsevat HTTPS-API-originin direktiivissä connect-src. EventSourcen kautta toteutetut Server-Sent Events kuuluvat myös sen piiriin. WebSocketia varten lisää tarkka wss://-origin nimenomaisesti. MDN huomauttaa, ettei 'self' kata WebSocket-skeemoja automaattisesti kaikissa selaimissa. Erillistä direktiiviä nimeltä stream-src ei ole.
CSP ja CORS ratkaisevat eri ongelmia. CSP määrittää, minne sivu saa ylipäätään muodostaa yhteyden; CORS määrittää palvelinpuolella, mitkä originit saavat lukea vastauksen selaimessa. CSP-sallinta ei siis korjaa CORS-virhettä eikä vanhentunutta käyttöoikeustokenia. Same-Origin-proxy voi yksinkertaistaa käytäntöä, mutta sen täytyy silti käsitellä autentikointi, rate limitit, aikakatkaisut ja virheiden välitys oikein.
3. Kuvat, avatarit ja luotu media
Salli direktiivissä img-src vain oma origin ja oikeasti käytetty media-origin. data: tarvitaan vain, jos widget käyttää pieniä upotettuja kuvia; blob: vain, jos selain todella luo kuvia Blob-URL-osoitteina. Jokainen lisälähde kasvattaa hyökkäyspintaa. Jos kuva ladataan ensin fetch()-kutsulla ja muunnetaan sen jälkeen Blob-URLiksi, vaikutus voi koskea sekä connect-src- että img-src-direktiiviä.
Älä testaa pelkkää oletusavataria. Tarkista esikatselukuvat, lähdekuvakaappaukset, liitetiedostot, Dark Mode ja virhenäkymät tilanteissa, joissa media ei ole saatavilla. URL-parametrit voivat viedä luottamuksellista tietoa CSP-raportteihin; raportointipäätepisteiden tulisi siksi käsitellä raportteja tietoa säästäen eikä säilyttää niitä rajattomasti.
4. iframe, tyylit, fontit ja valinnaiset Workerit
Suoraan DOMiin upotettu widget ei yleensä tarvitse vierasta framea. Silloin frame-src 'none' voi jäädä käyttöön. Jos chat taas toimii iframessa, salli vain sen tarkka origin. Tästä on erotettava frame-ancestors: direktiivi määrittää toimitetussa resurssissa, mitkä sivut saavat upottaa sen. Widget-palveluntarjoajan on siksi asetettava se iframe-vastauksessaan oikein.
Tyyleissä ja fonteissa pätee sama periaate. Salli konkreettiset hostit ja vältä arvoa 'unsafe-inline' niin pitkälle kuin integraatio sallii. Workerit tai äänitoiminnot lisätään vain, jos tuote todella käyttää niitä. Ennakkoon tehty sallinta blob:-osoitteille, kokonaisille wildcard-domaineille tai mille tahansa medialähteille vaikeuttaa myöhempiä auditointeja.
Realistinen CSP-esimerkki chatbot-widgetille
Seuraavat domainit ovat tarkoituksella varattuja esimerkkidomaineja. Korvaa ne oman verkkoanalyysisi origineilla. Esimerkissä oletetaan ulkoinen loader, HTTPS-API, erillinen WebSocket streamingia varten ja mediahosti. Se ei käytä yleisiä wildcardeja:
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} tarkoittaa vahvaa arvoa, joka luodaan uudelleen jokaista vastausta varten ja joka on sama headerissa sekä sallituissa script- tai style-elementeissä. Jos widget käyttää iframea, korvaa frame-src 'none' tarkalla widget-originilla. Jos se käyttää pelkkää HTTPS-streamingia fetch()-kutsun tai EventSourcen kautta, WebSocket-origin jää pois. Poista jokainen lähde, jota ei tarvita täydellisen toimintatestin jälkeen.
Käytäntö on käytännöllinen lähtökohta, ei yleispätevä malli. Moderni tiukka CSP voi ohjata skriptejä vielä vahvemmin nonceilla tai hasheilla ja direktiivillä 'strict-dynamic'. Se, onnistuuko tämä ilman yhteensopivuusongelmia, riippuu siitä, miten loader luo muita skriptejä. Selvitä tämä kulku palveluntarjoajan kanssa ja testaa selaimet, consent-tila ja deployment-muunnelmat.
Report-Only-tilasta pakotettuun käytäntöön
Älä kytke uutta käytäntöä suoraan pakottavaksi ilman testausta. W3C:n mekanismi Content-Security-Policy-Report-Only ilmoittaa rikkomuksista ilman, että resursseja estetään. Näin huomaat unohtuneet kuvahostit, poikkeavan streaming-originin tai inline-koodin ennen kuin käyttäjät kärsivät siitä. OWASP suosittelee HTTP-headeria ensisijaiseksi toimitustavaksi; toisin kuin meta-elementti, se tukee myös koko toiminnallisuutta.
- Luo inventaario: Testaa widgetin käynnistys, ensimmäinen viesti, pitkä streaming-vastaus, lähteet, kuvat, palaute, handoff ja consent-muutokset useilla sivutyypeillä.
- Ota Report-Only käyttöön: Aloita suunnitellulla tiukalla käytännöllä ja kerää rikkomuksia rajatun ajan. Suodata pois selainlaajennukset ja muut häiriösignaalit, joita ei voi toistaa.
- Perustele jokainen host: Laajenna käytäntöä vain, jos konkreettinen tuoteominaisuus tarvitsee kyseistä originia. Vältä wildcardeja yksittäisten ilmoitusten nopeana vastauksena.
- Testaa automatisoidusti: Lisää end-to-end-testejä, jotka lähettävät viestin, odottavat streamingin ja lataavat kuvan. Tarkista samalla selaimen konsoli CSP-rikkomusten varalta.
- Pakota ja seuraa: Aktivoi
Content-Security-Policy-header, pidä rinnalla silmällä vielä tiukempaa Report-Only-versiota ja vertaa virheprosentteja.
Vaiheittainen käyttöönotto sopii hyvin yhteen Shadow Mode -chatbotin kanssa. Streaming-kohtaisiin mittareihin auttaa artikkeli latenssibudjeteista ja aikakatkaisuista. CSP-rikkomuksia kannattaa käsitellä omana signaalinaan: timeout ja estetty yhteys tarvitsevat eri syyanalyysin.
Tyypilliset virheelliset määritykset
- Liian laajat lähdeluettelot:
*,https:tai suuret wildcard-domainit tekevät käytännöstä mukavan, mutta heikon ja vaikeasti tarkistettavan. - Testataan vain näkyvä käynnistys: Widget avautuu, mutta streaming, palaute, kuvat tai handoff epäonnistuvat vasta myöhemmin.
'unsafe-inline'jää pysyväksi: Lyhytaikaista yhteensopivuusapua ei korvata nonceilla, hasheilla tai ulkoisella koodilla.- CSP sekoitetaan käyttöoikeuksien hallintaan: Käytäntö ei korvaa palvelinpuolen oikeuksia, session tarkistusta eikä suojaa väärinkäytöksiltä tool-kutsuissa.
- Raportit sisältävät liikaa dataa: Täydelliset URLit, query-parametrit tai käyttäjäkonteksti päätyvät monitoringiin tarpeettoman pitkäksi aikaa.
- Staging ja tuotanto ajautuvat erilleen: Eri CDN-, API- tai WebSocket-hostit huomataan vasta go-liven jälkeen.
Edes tiukka script-src ei tee sallitusta kolmannen osapuolen toimittajasta automaattisesti turvallista: sen JavaScript toimii niillä mahdollisuuksilla, jotka sivusi antaa sille. Tarkista siksi toimittajavaihdokset, uudet subdomainit ja loader-päivitykset samalla vakavuudella kuin muut turvallisuuteen vaikuttavat riippuvuudet. Artikkeli prompt injection -suojauksesta täydentää tätä selainrajaa RAGin, työkalujen ja datan säännöillä.
Tarkistuslista ennen go-liveä
- Onko kaikki tarvittavat originit dokumentoitu oikeista selainistunnoista ja perusteltu toiminnallisesti?
- Salliiko
script-srcvain loaderin ja hallitut skriptit ilman yleistä'unsafe-inline'-sallintaa? - Sisältääkö
connect-srctarkat HTTPS-, EventSource- ja tarvittaessa WSS-originit? - Onko kuva-, tyyli-, fontti-, frame- ja Worker-lähteet erotettu toisistaan ja määritelty mahdollisimman tiukasti?
- Luodaanko noncet uudelleen jokaista vastausta varten ja asetetaanko ne vain luotettuihin elementteihin?
- Onko consent-muutokset, pitkät streamit, kuvat, virheet, handoff sekä työpöytä ja mobiililaitteet testattu?
- Onko käytäntöä ensin seurattu Report-Only-tilassa ja pakotettu sen jälkeen headerina?
- Käsitelläänkö CSP-raportit ilman tarpeettomia henkilötietoja tai luottamuksellisia URL-tietoja?
- Onko widget- tai infrastruktuuripäivitysten jälkeen käytössä automatisoitu regressiotesti?
Yhteenveto
Hyvä CSP verkkosivuston chatbotille ei ole poikkeusten kokoelma vaan tekninen kartta sallituista selainreiteistä. Erottele loader, API, streaming, kuvat ja iframe-resurssit, salli tarkat originit ja ota käytäntö ensin käyttöön Report-Only-tilassa. Näin widget pysyy toimivana, mutta odottamattomille skripteille ja yhteyksille jää selvästi vähemmän liikkumavaraa.
Lähteet
Muuta verkkosivukäynnit paremmiksi keskusteluiksi
Julkaise AI-chatbot, joka on hyödyllinen heti alusta alkaen
Kouluta ChatReact sivustosi, dokumenttien ja hyväksyttyjen faktojen avulla, jotta kävijät saavat nopeammat vastaukset ja tiimisi saa vähemmän toistuvia kyselyitä.
Aiheet, jotka saattavat kiinnostaa
Jatka lukemista
Kuinka lisätä tekoälychatbot verkkosivustolle ilman, että se vahingoittaa käyttökokemusta tai hakukoneoptimointia
Käyttöönoton suunnitelma chatbotin lisäämiseen verkkosivustolle siten, että käyttäjäpolku, sivunopeus ja sisältörakenne säilyvät hyvänä.

Tekoäly-chatbotin vastausaikojen optimointi: Viivebudjetti, suoratoisto ja aikakatkaisut
Nopeat chatbotin vastaukset syntyvät koko teknisessä ketjussa. Näin suunnittelet viivebudjetit, suoratoiston, aikakatkaisut, uudelleenyritykset ja turvalliset varajärjestelmät.

Tekoäly-chatbotin testaaminen Shadow Mode -tilassa: Turvallisesti prototyypistä verkkosivuston julkaisuun
Shadow Mode -tilan, selkeiden laatuporttien ja vaiheittaisen julkaisun avulla verkkosivutiimit testaavat tekoäly-chatbotit turvallisesti ennen tuotantoon siirtymistä.