Content Security Policy za web chatbotove: sigurno odobrite widget, API, slike i streaming
Praktični CSP za web chatbotove dopušta samo stvarno potrebne skripte, API veze, streamove i slike – bez nepotrebnih zamjenskih znakova (wildcards).

Web chatbot u pregledniku rijetko se sastoji samo od jedne JavaScript datoteke. Učitavač (loader) otvara widget, API prima poruke, odgovori pristižu u obliku streama, a profilne slike ili mediji mogu se nalaziti na drugoj domeni. Content Security Policy (CSP) čini te putove vidljivima i ograničava ih: preglednik učitava ili spaja samo ono što web stranica izričito dopušta.
To je važan drugi sloj zaštite od Cross-Site Scriptinga i neočekivanog sadržaja trećih strana. Međutim, CSP ne popravlja nesiguran API, nedostajuću autentifikaciju, lošu validaciju unosa ili prompt injection. On smanjuje mogućnosti ubacivanja zlonamjernog koda i ograničava radijus štete u slučaju pogreške. Zbog toga je ključna što manja, testirana politika umesto dugog popisa općenito odobrenih domena.
Zašto chatbot widgeti trebaju posebna CSP pravila
Kod klasične stranice sa sadržajem često su dovoljni resursi s vlastitog izvora (origin). Chatbot, s druge strane, nastavlja komunikaciju i nakon učitavanja. Direktiva connect-src između ostalog upravlja s fetch(), XMLHttpRequest, EventSource, WebSocket i sendBeacon(). Upravo ovdje prolaze poruke, streaming odgovori, događaji povratnih informacija i po potrebi telemetrija. Ako nedostaje točan izvor, widget će se pojaviti, ali neće moći odgovoriti.
Ostale komponente spadaju pod vlastite direktive. script-src odlučuje o učitavaču widgeta, img-src o avatarima i slikama u odgovorima, style-src o stilskim tablicama (stylesheets), a font-src o vanjskim fontovima. Widget baziran na iframe-u dodatno treba frame-src. default-src služi kao rezervna opcija za mnoge vrste resursa koje nisu izričito navedene, ali ne zamjenjuje promišljeni inventar resursa.
Stoga se najvažniji pripremni rad ne odvija u CSP generatoru, već u pregledniku: otvorite reprezentativnu stranicu, započnite razgovor, pustite dugački odgovor da se streama, otvorite izvore, pošaljite povratne informacije i testirajte slučajeve pogrešaka i preusmjeravanja (handoff). U mrežnom panelu vidjet ćete izvore koji se stvarno pozivaju. Za svaki host dokumentirajte svrhu, vrstu resursa i odgovornu osobu.
Odvojeno odobrite četiri relevantna podatkovna puta
1. Skripta widgeta i inicijalizacija
Nabavite učitavač po mogućnosti sa stabilne, verzionirane adrese. Odobrenje poput script-src https: bilo bi preširoko jer bi time postale dopuštene skripte s bilo koje HTTPS domene. Umjesto toga, dopustite točan CDN izvor ili sami poslužite učitavač. Ako integracija zahtijeva inline kod, upotrijebite nonce generiran iznova po svakom HTTP odgovoru ili odgovarajući hash. 'unsafe-inline' ne bi trebao postati brzo trajno rješenje.
Nonce pripada samo skriptama koje predložak na poslužitelju sam generira. Middleware koji slijepo dodaje isti nonce svakoj postojećoj script oznaci dao bi povjerenje i ubacenim oznakama. Za statičku, verzioniranu skriptu treće strane Subresource Integrity može dodatno pomoći; međutim, kod datoteka koje se često mijenjaju, hash se mora kontrolirano ažurirati.
2. API, Server-Sent Events i WebSocket
Normalni POST zahtjevi i odgovor streaman putem fetch() zahtijevaju HTTPS API izvor u connect-src. Server-Sent Events putem EventSource-a također spadaju pod to. Za WebSocket izričito unesite konkretan wss:// izvor. MDN napominje da 'self' ne obuhvaća automatski WebSocket sheme u svim preglednicima. Posebna direktiva pod nazivom stream-src ne postoji.
CSP i CORS rješavaju različite zadatke. CSP određuje kamo se stranica uopće smije spajati; CORS s poslužiteljske strane određuje koji izvori smiju čitati odgovor u pregledniku. Stoga odobrenje u CSP-u ne rješava CORS pogrešku niti isteklu pristupnu token-potvrdu. Same-Origin proxy može pojednostaviti politiku, ali i dalje mora ispravno obraditi autentifikaciju, ograničenja brzine (rate limits), isteke vremena i prosljeđivanje pogrešaka.
3. Slike, avatari i generirani mediji
U img-src dopustite samo vlastiti izvor i medijski izvor koji se stvarno koristi. data: je potreban samo ako widget koristi male ugrađene slike; blob: samo ako preglednik stvarno generira slike kao Blob URL. Svaki dodatni izvor povećava površinu napada. Ako se slika prvo učita putem fetch(), a zatim pretvori u Blob URL, to može utjecati i na connect-src i na img-src.
Nemojte testirati samo standardni avatar. Provjerite pretpregledne slike, snimke zaslona izvora, privitke datoteka, tamni način rada (dark mode) i prikaz pogrešaka za nedostupne medije. URL parametri mogu prenijeti povjerljive informacije u CSP izvješća; stoga bi izvještajne krajnje točke trebale obrađivati izvješća uz štednju podataka i ne čuvati ih bezograničeno.
4. iframe, stilovi, fontovi i opcionalni workeri
Widget koji je izravno ugrađen u DOM obično ne treba strani okvir. U tom slučaju frame-src 'none' može ostati. Ako se chat pak odvija u iframe-u, dopustite isključivo njegov točan izvor. Od toga treba razlikovati frame-ancestors: ova direktiva na isporučenom resursu određuje koje ga stranice smiju ugraditi. Pružatelj widgeta je stoga mora odgovarajuće postaviti na svom iframe odgovoru.
Isto načelo vrijedi za stilove i fontove. Dopustite konkretne hostove i izbjegavajte 'unsafe-inline' u mjeri u kojoj to integracija dopušta. Workeri ili audio funkcije dodaju se samo ako ih proizvod stvarno koristi. Preventivno odobrenje blob:, cijelih zamjenskih domena ili proizvoljnih medijskih izvora otežava kasnije revizije.
Realističan primjer CSP-a za chatbot widget
Sljedeće domene su namjerno rezervirane primjer-domene. Zamijenite ih izvorima iz vlastite analize mreže. Primjer pretpostavlja vanjski učitavač, HTTPS API, odvojeni WebSocket za streaming i host za medije. Ne koristi općenite zamjenske znakove (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} predstavlja jaku vrijednost generiranu iznova po svakom odgovoru, koja je identična u zaglavlju i u dopuštenim elementima skripte odnosno stila. Ako vaš widget koristi iframe, zamijenite frame-src 'none' točnim izvorom widgeta. Ako koristi isključivo HTTPS streaming putem fetch() ili EventSource-a, WebSocket izvor se uklanja. Uklonite svaki izvor koji nije potreban nakon potpunog funkcionalnog testiranja.
Politika je praktična polazna točka, a ne univerzalni predložak. Moderna stroga CSP politika može još jače kontrolirati skripte putem nonce-a ili hasheva i 'strict-dynamic'. Je li to moguće bez problema s kompatibilnošću ovisi o tome kako učitavač generira daljnje skripte. Razjasnite taj proces s pružateljem usluge i testirajte preglednike, način pristanka (consent mode) i varijante uvođenja (deployment).
Od načina samo za izvještavanje (Report-Only) do prisilne politike
Nemojte aktivirati novu politiku bez prethodne provjere. W3C mehanizam Content-Security-Policy-Report-Only prijavljuje kršenja bez blokiranja resursa. Tako ćete prepoznati zaboravljene hostove slika, odstupajući izvor streaminga ili inline kod prije nego što to utječe na korisnike. OWASP preporučuje HTTP zaglavlje kao preferirani način isporuke; za razliku od meta-elementa, ono podržava i puni opseg funkcija.
- Izradite inventar: Testirajte pokretanje widgeta, prvu poruku, dugačak streaming odgovor, izvore, slike, povratne informacije, preusmjeravanje i promjenu pristanka na više vrsta stranica.
- Uvedite Report-Only: Započnite s planiranom strogom politikom i prikupljajte kršenja u ograničenom vremenskom razdoblju. Filtrirajte proširenja preglednika i druge nereproducibilne šumove.
- Obrazložite svaki host: Proširite politiku samo ako konkretna funkcija proizvoda zahtijeva taj izvor. Izbjegavajte zamjenske znakove (wildcards) kao reakciju na pojedinačne prijave.
- Automatski testirajte: Dopunite end-to-end testove koji šalju poruku, čekaju streaming i učitavaju sliku. Istovremeno provjeravajte konzolu preglednika na CSP kršenja.
- Prisilno primijenite i promatrajte: Aktivirajte zaglavlje
Content-Security-Policy, paralelno pratite još strožu Report-Only varijantu i usporedite stope pogrešaka. Close
Postupno uvođenje dobro se uklapa u chatbot u Shadow Mode-u. Za mjerenja specifična za streaming pomaže članak o proračunima latencije i isteku vremena (timeouts). Pritom bi se CSP kršenja trebala smatrati zasebnim signalom: istekao timeout i blokirana veza zahtijevaju različitu analizu uzroka.
Uobičajene pogrešne konfiguracije
- Preširoki popisi izvora:
*,https:ili velike zamjenske domene čine politiku udobnom, ali slabom i teškom za provjeru. - Testira se samo vidljivi početak: Widget se otvara, ali streaming, povratne informacije, slike ili preusmjeravanje otkazuju tek kasnije.
'unsafe-inline'ostaje trajno: Kratkoročna pomoć za kompatibilnost ne zamjenjuje se nonce-ovima, hashevima ili vanjskim kodom.- CSP se miješa s kontrolom pristupa: Politika ne zamjenjuje poslužiteljska prava, provjeru sesije niti zaštitu od zlouporabe alata.
- Izvješća sadrže previše podataka: Potpuni URL-ovi, parametri upita ili korisnički kontekst nepotrebno dugo završavaju u nadzornom sustavu.
- Razlike između Staginga i Produkcije: Različiti CDN, API ili WebSocket hostovi postaju vidljivi tek nakon puštanja u rad (go-live).
Čak ni strogi script-src ne čini odobrenog trećeg pružatelja automatski sigurnim: njegov JavaScript radi s mogućnostima koje mu vaša stranica daje. Stoga provjeravajte promjene pružatelja usluga, nove poddomene i ažuriranja učitavača kao i druge sigurnosno relevantne ovisnosti. Članak o zaštiti od prompt injectiona nadopunjuje ovu granicu preglednika pravilima za RAG, alate i podatke.
Kontrolni popis prije puštanja u rad (Go-live)
- Jesu li svi potrebni izvori dokumentirani i stručno obrazloženi iz stvarnih sesija preglednika?
- Dopušta li
script-srcsamo učitavač i kontrolirane skripte, bez općenitog'unsafe-inline'? - Sadrži li
connect-srctočne HTTPS, EventSource i po potrebi WSS izvore? - Jesu li izvori slika, stilova, fontova, okvira i workera odvojeni i definirani što je moguće strože?
- Generiraju li se nonce-ovi iznova po odgovoru i postavljaju samo na pouzdane elemente?
- Jesu li testirane promjene pristanka, dugački streamovi, slike, pogreške, preusmjeravanje te stolna računala i mobilni uređaji?
- Je li politika prvo promatrana u načinu Report-Only, a zatim primijenjena prisilno kao zaglavlje?
- Obrađuju li se CSP izvješća bez nepotrebnih osobnih ili povjerljivih URL podataka?
- Postoji li automatski test regresije nakon ažuriranja widgeta ili infrastrukture?
Zaključak
Dobar CSP za web chatbotove nije zbirka iznimaka, već tehnička karta dopuštenih putova u pregledniku. Odvojite učitavač, API, streaming, slike i iframe resurse, dopustite točne izvore i prvo uvedite politiku u načinu samo za izvještavanje (Report-Only). Tako widget ostaje funkcionalan, dok neočekivane skripte i veze dobivaju znatno manje prostora za djelovanje.
Izvori
Pretvorite posjete web-stranici u bolje razgovore
Pokrenite AI chatbota koji je koristan od prvog dana
Natrenirajte ChatReact vašom web-stranicom, dokumentima i potvrđenim činjenicama kako bi posjetitelji dobili brže odgovore, a vaš tim manje ponovljenih zahtjeva.
Povezani članci
Nastavite čitati
Kako dodati AI chatbota na web-stranicu bez narušavanja UX-a ili SEO-a
Plan uvođenja za dodavanje chatbota na vašu web-stranicu uz očuvanje korisničkog puta, brzine učitavanja i strukture sadržaja.

Optimizacija vremena odziva AI chatbota: Budžet latencije, streaming i timeouti
Brzi odgovori chatbota nastaju duž cijelog tehničkog lanca. Saznajte kako planirati budžete latencije, streaming, timeoute, ponovne pokušaje i sigurne fallback opcije.

Testiranje AI chatbota u Shadow Mode-u: Sigurno od prototipa do lansiranja na web stranici
Uz Shadow Mode, jasna kontrolna vrata kvalitete i stupnjeviti rollout, timovi web stranica sigurno testiraju AI chatbotove prije produkcijskog lansiranja.