Browser og frontend-sikkerhed
XSS og sikkerhedsheaders: beskyt webappen dér, hvor data bliver til en side
XSS opstår, når data, som skulle vises som tekst, får lov at blive fortolket som kode i en brugers browser. Sikker rendering er den vigtigste beskyttelse. En Content Security Policy og andre relevante HTTP-svarheaders kan begrænse skaden og afsløre usikre indlæsninger, men de kan ikke reparere en farlig kodevej alene.
Hvor kan XSS komme ind i en fungerende app?
Data bliver ikke pålidelige, fordi de allerede ligger i jeres database. Navne, kommentarer, importerede beskrivelser, filmetadata, URL-parametre og svar fra en integration kan stadig indeholde tegn eller markup, som browseren kan fortolke. Kortlæg derfor både kilden og det sted, hvor værdien bliver vist.
| Data | Hvor vises den? | Sikker standard | Særlig risiko |
|---|---|---|---|
| Navn eller kommentar | Tekst i side eller tabel | Frameworkets almindelige tekst-rendering | Rå HTML eller DOM-indsættelse |
| Formateret tekst | Beskrivelse eller artikel | Sanitér med en vedligeholdt tilladelsesliste | Events, scripts og farlige URL-protokoller |
| Link fra import eller API | href, billede eller omdirigering | Tillad bevidste protokoller og destinationer | javascript:, data-URL eller åben omdirigering |
| JSON eller fejlsvar | API-respons eller fejlvisning | Korrekt content type og sikker tekstvisning | Svar leveres som HTML eller indsættes råt |
En gemt værdi kan ramme mange brugere og administrationen igen og igen. Derfor bør test også omfatte data, der bliver gemt, eksporteret, genindlæst og vist i en anden rolle end den, der oprettede dem.
Bevar frameworkets sikre tekst-rendering
Moderne frontend-frameworks hjælper normalt ved at kode særlige tegn, når værdier vises som almindelig tekst. Beskyttelsen forsvinder, hvis appen vælger en rå HTML-funktion, skriver direkte til innerHTML eller bygger script, CSS og URL'er ved at sætte ubetroede strenge sammen.
- Vis tekst som tekst. Brug frameworkets normale binding eller DOM-egenskaber som
textContentfrem for rå HTML. - Find omvejene. Søg efter blandt andet
innerHTML,outerHTML,document.write, rå HTML-funktioner og strenge, der bliver til kode. - Sanitér nødvendig formateret tekst. Hvis brugere reelt skal kunne skrive formateret HTML, så brug et vedligeholdt saniteringsbibliotek med en afgrænset tilladelsesliste og opdatér det løbende.
- Ændr ikke efter sanitering. Senere strengmanipulation eller et bibliotek, der omskriver markup, kan gøre resultatet usikkert igen.
Behandl links, filer og tredjepartsindhold som særskilte kontekster
Det samme tekststykke kræver forskellige regler alt efter, om det står i et afsnit, en HTML-attribut, en URL, CSS eller JavaScript. Undgå derfor en hjemmelavet “rens alt”-funktion. Brug den beskyttelse, der passer til den konkrete destination.
- Begræns brugerleverede links til de URL-protokoller og destinationer, som funktionen faktisk kræver.
- Brug den korrekte
Content-Typepå HTML, JSON, scripts, billeder og downloads; suppler medX-Content-Type-Options: nosniff. - Lad ikke en tredjeparts widget få mere adgang end nødvendigt. Hver ekstern scriptkilde bliver en del af appens browsermæssige tillidsgrænse.
- Vis ikke serverfejl, stack traces eller ubetroede API-svar som HTML. Giv brugeren en stabil tekstbesked og gem tekniske detaljer i beskyttede logs.
Uploads har også egne regler for type, lagring og download. De er behandlet i den separate guide om sikker filupload og download.
Brug CSP som sikkerhedsnet – ikke som plaster
En Content Security Policy fortæller browseren, hvilke kilder der må levere scripts, styles, billeder, forbindelser og andet indhold. Den kan også begrænse formularers destinationer, blokere plugins og forhindre, at siden bliver indlejret til clickjacking. OWASP anbefaler CSP som et ekstra lag oven på sikker rendering, output encoding og sanitering – ikke som den eneste XSS-beskyttelse.
Illustrativ report-only-politik – skal tilpasses appens faktiske kilder
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; connect-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; form-action 'self'Eksemplet tillader kun egne scripts og forbindelser. Det vil derfor registrere brud for eksempelvis analyse, skrifter, betalingswidgets eller API'er på andre domæner. Tilføj kun en kilde, når I ved, hvilken funktion der kræver den. Undgå at “løse” rapporter med brede tilladelser som *, unsafe-inline eller unsafe-eval uden at forstå den tabte beskyttelse.
Rul politikken ud uden at gøre produktionen ubrugelig
- Kortlæg de nuværende kilder. Gennemgå HTML, netværkskald, tredjepartsscripts, styles, billeder, formularer, frames og forbindelser i de kritiske brugerrejser.
- Brug report-only.
Content-Security-Policy-Report-Onlyhåndhæver ikke politikken, men kan vise overtrædelser i browserens konsol og sende rapporter til et konfigureret endpoint. - Sortér støj fra rigtige brud. Browserudvidelser og urelaterede kilder kan skabe rapporter. Bekræft problemet i et kontrolleret browserforløb før en tilladelse udvides.
- Håndhæv en afprøvet politik. Skift til
Content-Security-Policy, når login, betaling, redigering, upload og andre kritiske forløb er testet i de relevante browsere. - Overvåg efter ændringer. Nye widgets, analyseværktøjer og buildændringer kan kræve en bevidst opdatering; en bred permanent undtagelse bør ikke være standarden.
Nonces skal være uforudsigelige og forskellige for hvert HTTP-svar. De kræver derfor dynamisk HTML eller en platformfunktion, der kan indsætte værdien i både header og relevante script-tags. En statisk app kan i stedet bruge en politik, der passer til dens byggede filer, eller en dokumenteret hostingfunktion til dynamiske nonces.
Vælg headers efter appens funktion og hosting
Der findes ikke én headerblok, som passer til alle apps. En app, der skal kunne indlejres hos kunder, har for eksempel andre krav end et internt administrationssystem. Beslut formålet for hver header og kontrollér den faktiske live-respons.
- Content-Security-Policy
- Afgrænser indholdskilder og kan med
frame-ancestorsstyre, hvem der må indlejre siden. - X-Content-Type-Options
nosniffbeder browseren respektere den angivne MIME-type frem for at gætte.- Referrer-Policy
- Styrer hvor meget af den aktuelle adresse der sendes videre, når browseren navigerer eller henter indhold.
- Permissions-Policy
- Begrænser browserfunktioner som kamera, mikrofon og geolocation, når appen ikke behøver dem.
- Strict-Transport-Security
- Kan tvinge fremtidige besøg over HTTPS. Kontrollér certifikater, underdomæner, hostingens egne standarder og en sikker tilbagevej, før lang levetid eller
includeSubDomainsvælges.
Netlify kan sætte headers via blandt andet _headers eller netlify.toml. Vercel bruger blandt andet vercel.json, Firebase Hosting firebase.json, og Azure Static Web Apps staticwebapp.config.json. Andre backends og reverse proxies har deres egne mekanismer. Følg dokumentationen til den platform og version, appen allerede bruger.
Test både kodevejen og det faktiske live-svar
En konfigurationsfil beviser ikke, at CDN, rewrite, funktion eller proxy leverer den forventede header. Test den udgivne adresse og alle relevante dokumenttyper.
- Kontrollér HTTP-svarheaders på den faktiske appside, login, fejlside og andre svar, der gengiver HTML.
- Kør de kritiske brugerrejser med report-only aktiv og gennemgå browserens CSP-rapporter og konsol.
- Prøv gemt tekst med HTML-tegn, ugyldige URL-protokoller og formateret tekst, som saniteringen skal fjerne, i et isoleret testmiljø.
- Bekræft at appen ikke kan indlejres, hvis
frame-ancestors 'none'er den valgte regel, eller kun kan indlejres af de aftalte origins. - Gentag testen efter nye tredjepartsscripts, analyseværktøjer, editorer, uploads eller hostingændringer.
curl -I https://jeres-app.example/ viser HTTP-svarheaders, men browserens DevTools er stadig nødvendig for at se, om politikken blokerer eller rapporterer noget under rigtig brug.Typiske fejl
- Alt HTML fjernes ved input: Legitime tegn går tabt, mens den samme værdi stadig kan være farlig i en URL- eller scriptkontekst.
- Rå HTML vælges for at få formatering: Ubetroet markup bliver kode uden en vedligeholdt saniteringsregel.
- CSP bliver eneste forsvar: Den usikre rendering består, og en bred undtagelse kan åbne angrebsvejen igen.
- Politikken kopieres fra et andet site: Nødvendige funktioner bryder, eller unødvendige domæner får tillid.
- Report-only bliver permanent: Overtrædelser registreres, men browseren blokerer dem aldrig.
- Alle fejl løses med unsafe-inline: En central begrænsning mod inline script bliver sat ud af kraft.
- Headeren findes kun lokalt: CDN eller hosting leverer et andet svar i produktion.
- HSTS sættes aggressivt uden plan: Certifikat- eller underdomænefejl kan gøre legitime tjenester utilgængelige.
Tjekliste før medarbejdere eller kunder får adgang
- ☐ Alle steder, hvor formular-, database-, URL-, fil- og integrationsdata vises i browseren, er kortlagt.
- ☐ Almindelig tekst vises gennem frameworkets sikre standard eller en tilsvarende tekst-API.
- ☐ Rå HTML-funktioner og usikre DOM-sinks er fjernet eller begrundet og beskyttet.
- ☐ Nødvendig formateret tekst saniteres med en afgrænset, vedligeholdt løsning.
- ☐ Links, omdirigeringer og ressource-URL'er accepterer kun de nødvendige protokoller og destinationer.
- ☐ HTML, JSON, scripts, filer og fejl svarer med en bevidst og korrekt content type.
- ☐ En CSP er tilpasset appens faktiske scripts, styles, billeder, forbindelser, formularer og frames.
- ☐ CSP er afprøvet i report-only på de kritiske brugerrejser før håndhævelse.
- ☐ Brede undtagelser som wildcard, unsafe-inline og unsafe-eval er fjernet eller dokumenteret med ejer og plan.
- ☐ Clickjacking, MIME-sniffing, referrerdata og unødvendige browserfunktioner er vurderet.
- ☐ HSTS er kun strammet efter kontrol af HTTPS, certifikater, underdomæner og hostingens standarder.
- ☐ De forventede headers er bekræftet på den faktiske live-side og relevante fejlsvar.
- ☐ Browserkonsol og CSP-rapporter overvåges efter nye widgets, editorer, analyse- og hostingændringer.
Officielle kilder
Frameworks, hostingplatforme og browserunderstøttelse ændrer sig. Kontrollér altid den officielle dokumentation til appens konkrete stack, før en politik håndhæves i produktion.
- OWASP: forebyg XSS med sikker rendering, encoding og sanitering
- OWASP: Content Security Policy som ekstra beskyttelseslag
- MDN: Content Security Policy, direktiver og report-only
- OWASP: sikkerhedsheaders og deres begrænsninger
- Netlify: Content Security Policy og custom headers
- Vercel: egne HTTP-svarheaders i vercel.json
- Firebase Hosting: egne HTTP-svarheaders i firebase.json
- Azure Static Web Apps: globalHeaders og route-headers
Når webappen virker, men browsergrænsen ikke er gennemgået
Hvis medarbejdere eller kunder snart skal bruge appen, kan Startklar hjælpe med at kortlægge usikre renderingsveje, tilpasse CSP og headers til den nuværende hosting og afprøve de kritiske forløb uden at låse løsningen til en bestemt teknologistak.
Se Startklar for AI-byggede apps