{"id":97,"date":"2026-06-17T17:00:07","date_gmt":"2026-06-17T17:00:07","guid":{"rendered":"https:\/\/shattered.io\/no\/2026\/06\/17\/helmet-js-nodejs-sikkerhetshoder\/"},"modified":"2026-06-17T17:01:31","modified_gmt":"2026-06-17T17:01:31","slug":"helmet-js-nodejs-sikkerhetshoder","status":"publish","type":"post","link":"https:\/\/shattered.io\/no\/helmet-js-nodejs-sikkerhetshoder\/","title":{"rendered":"Helmet.js i Node.js: Sikkerhetshoder i 12 Steg [2026]"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Helmet.js setter 11 sikkerhetshoder i Express p\u00e5 \u00e9n kodelinje. Uten dem sender applikasjonen din informasjon om server-teknologi, tillater iframe-inlasting fra tredjeparter og mangler beskyttelse mot MIME-sniffing-angrep. Pakken lastes ned over 2 millioner ganger per uke og er anbefalt direkte av <a href=\"https:\/\/nodejs.org\/en\/blog\/vulnerability\/june-2026-security-releases\" rel=\"noopener noreferrer\" target=\"_blank\">Node.js-sikkerhetsteamet<\/a>. Denne guiden tar deg gjennom et komplett oppsett i 12 steg med Helmet.js 8.2.0.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"hva-er-helmet-js-og-hvorfor-trenger-du-det\">Hva er Helmet.js og hvorfor trenger du det?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Helmet.js er en Express-mellomvare som setter HTTP-sikkerhetshoder automatisk. Express leverer ingen sikkerhetshoder som standard, noe som betyr at svar fra en ny Express-applikasjon avsl\u00f8rer server-teknologi via <code>X-Powered-By: Express<\/code> og mangler alle de header-baserte forsvarslinjene som moderne nettlesere forventer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">HTTP-sikkerhetshoder er instruksjoner fra serveren til nettleseren om hvordan siden skal h\u00e5ndteres sikkerhetsmessig. De definerer hvilke ressurser nettleseren har lov til \u00e5 laste, om siden kan vises i en iframe, om HTTPS skal kreves for fremtidige bes\u00f8k, og mye mer. Disse hodene er ikke opsjonale i 2026. OWASP lister manglende sikkerhetshoder som en av de mest utbredte webapplikasjonss\u00e5rbarhetene, og EU-direktivet NIS2 krever av alle norske virksomheter over en viss st\u00f8rrelse at de implementerer tilstrekkelige tekniske sikkerhetstiltak.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En angriper som skanner etter s\u00e5rbare Express-apper bruker akkurat manglende hoder som et signal. Manglende <code>X-Frame-Options<\/code> \u00e5pner for clickjacking. Manglende <code>Content-Security-Policy<\/code> betyr at skadelige skript kan injiseres via XSS. Manglende <code>X-Content-Type-Options<\/code> lar nettleseren gjette MIME-typen og kj\u00f8re eksekverbart innhold den ikke skulle kj\u00f8rt. Tilstedev\u00e6relsen av <code>X-Powered-By: Express<\/code> bekrefter teknologi-stakken for automatiserte skanningsprogrammer som s\u00f8ker etter kjente Express-s\u00e5rbarheter.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Helmet l\u00f8ser alle disse problemene p\u00e5 \u00e9n gang. Pakken grupperer 13 individuelle sikkerhetsmoduler. Hvert modul setter ett eller flere HTTP-hoder. Du aktiverer alle med <code>app.use(helmet())<\/code> eller konfigurerer dem enkeltvis etter behov. Helmet har over 9.400 stjerner p\u00e5 GitHub og er med i de offisielle Express-sikkerhetsretningslinjene.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Hvem er dette for:<\/strong> Alle som bygger REST-APIer eller webapplikasjoner med Node.js og Express. Enten du lager en hobbyapp eller en produksjonstjeneste med norske bedriftsdata og brukerkontoer, gjelder de samme kravene. Guiden forutsetter at du kjenner til grunnleggende Express-routing og npm.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"http-sikkerhetshoder-forklart\">HTTP-sikkerhetshoder forklart<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00f8r vi setter opp Helmet, er det nyttig \u00e5 forst\u00e5 hva HTTP-sikkerhetshoder faktisk gj\u00f8r og hvorfor nettlesere respekterer dem.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">N\u00e5r nettleseren din bes\u00f8ker en nettside, sender serveren tilbake et HTTP-svar. Dette svaret inneholder to deler: hoder og kropp. Kroppen er innholdet (HTML, JSON, osv.). Hodene er metadata som sier noe om innholdet og hvordan det skal behandles. Sikkerhetshoder er hoder som spesifikt instruerer nettleseren om sikkerhetsrelatert oppf\u00f8rsel.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nettlesere fra alle store leverand\u00f8rer (Chrome, Firefox, Safari, Edge) har implementert st\u00f8tte for disse hodene som del av webstandarden. Serveren trenger ikke gj\u00f8re noe spesielt utover \u00e5 sende riktige hoder. Nettleseren leser dem og h\u00e5ndhever dem automatisk for brukeren.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Problemet er at dette er opt-in: serveren M\u00c5 aktivt sende hodene. En server som ikke sender <code>X-Frame-Options<\/code> gir nettleseren ingen instruksjon om iframe-h\u00e5ndtering, og nettleseren velger da \u00e5 tillate framing fra alle domener. Helmet l\u00f8ser dette ved \u00e5 sette alle viktige hoder som standard, slik at du aktivt M\u00c5 velge bort dem, ikke aktivt velge dem til.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Tabellen nedenfor viser angrepskategorier som header-mangler \u00e5pner for, og hvilken del av OWASP Top 10 de faller under:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Angrepskategori<\/th><th>OWASP Top 10 kategori<\/th><th>Manglende hode<\/th><th>Konsekvens<\/th><\/tr><\/thead><tbody><tr><td>Cross-Site Scripting (XSS)<\/td><td>A03: Injection<\/td><td>Content-Security-Policy<\/td><td>Injeksjon og kj\u00f8ring av skadelige skript<\/td><\/tr><tr><td>Clickjacking<\/td><td>A05: Security Misconfiguration<\/td><td>X-Frame-Options<\/td><td>Brukere lures til \u00e5 klikke p\u00e5 skjulte elementer<\/td><\/tr><tr><td>MIME-sniffing<\/td><td>A05: Security Misconfiguration<\/td><td>X-Content-Type-Options<\/td><td>Nettleser kj\u00f8rer filer med feil MIME-type<\/td><\/tr><tr><td>SSL-stripping<\/td><td>A02: Cryptographic Failures<\/td><td>Strict-Transport-Security<\/td><td>Nedgradering fra HTTPS til HTTP<\/td><\/tr><tr><td>Informasjonslekkasje<\/td><td>A05: Security Misconfiguration<\/td><td>X-Powered-By (fjernet)<\/td><td>Teknologi-stack eksponert for angripere<\/td><\/tr><tr><td>Referrer-lekkasje<\/td><td>A02: Cryptographic Failures<\/td><td>Referrer-Policy<\/td><td>Sensitive URL-parametere lekker til tredjeparter<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"forutsetninger\">Forutsetninger<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00f8r du starter, kontroller at f\u00f8lgende er p\u00e5 plass:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Node.js 22.x eller 24.x<\/strong> (LTS-versjoner st\u00f8ttet per juni 2026). Sjekk med <code>node --version<\/code>.<\/li>\n<li><strong>npm 10.x eller nyere<\/strong>. Sjekk med <code>npm --version<\/code>.<\/li>\n<li><strong>Express.js 4.x eller 5.x<\/strong>. Helmet 8.2.0 st\u00f8tter begge versjonene.<\/li>\n<li>Grunnleggende kunnskap om JavaScript og asynkron programmering i Node.js.<\/li>\n<li>Et terminalvindu med tilgang til prosjektmappen din.<\/li>\n<li>En HTTP-klient for testing, for eksempel <code>curl<\/code> eller Postman.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Komponent<\/th><th>Minimumsversjon<\/th><th>Anbefalt versjon<\/th><th>Form\u00e5l<\/th><\/tr><\/thead><tbody><tr><td>Node.js<\/td><td>18.x<\/td><td>22.x LTS<\/td><td>Kj\u00f8retidsmilj\u00f8<\/td><\/tr><tr><td>Express<\/td><td>4.18<\/td><td>5.x<\/td><td>Web-rammeverk<\/td><\/tr><tr><td>Helmet<\/td><td>7.x<\/td><td>8.2.0<\/td><td>Sikkerhetshoder<\/td><\/tr><tr><td>npm<\/td><td>8.x<\/td><td>10.x<\/td><td>Pakkebehandler<\/td><\/tr><tr><td>curl<\/td><td>7.x<\/td><td>8.x<\/td><td>Testing av hoder<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"steg-1-opprett-prosjektstruktur\">Steg 1: Opprett prosjektstruktur<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Start med et rent prosjekt. Dette gir deg full kontroll over avhengighetene og hjelper deg \u00e5 forst\u00e5 hva Helmet faktisk legger til.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir helmet-demo && cd helmet-demo\nnpm init -y\nmkdir src<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Opprett filen <code>src\/app.js<\/code> som utgangspunkt. Du bygger den ut steg for steg gjennom guiden. Guiden bruker CommonJS (<code>require<\/code>) for kompatibilitet med b\u00e5de Express 4.x og 5.x. Vil du bruke ES-moduler, legger du til <code>\"type\": \"module\"<\/code> i <code>package.json<\/code> og bytter <code>require()<\/code> til <code>import<\/code>-syntaks.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Prosjektstrukturen ser slik ut etter dette steget:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helmet-demo\/\n\u251c\u2500\u2500 src\/\n\u2502   \u2514\u2500\u2500 app.js\n\u251c\u2500\u2500 package.json\n\u2514\u2500\u2500 node_modules\/<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"steg-2-installer-helmet-js-8-2-0-og-express\">Steg 2: Installer Helmet.js 8.2.0 og Express<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Installer Helmet og Express med npm. <code>nodemon<\/code> er et utviklingsverkt\u00f8y som automatisk starter serveren p\u00e5 nytt ved kodeendringer:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>npm install express helmet\nnpm install --save-dev nodemon<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Legg til startskript i <code>package.json<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"name\": \"helmet-demo\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Helmet.js sikkerhetshoder demo\",\n  \"main\": \"src\/app.js\",\n  \"scripts\": {\n    \"start\": \"node src\/app.js\",\n    \"dev\": \"nodemon src\/app.js\"\n  },\n  \"dependencies\": {\n    \"express\": \"^5.0.0\",\n    \"helmet\": \"^8.2.0\"\n  },\n  \"devDependencies\": {\n    \"nodemon\": \"^3.1.0\"\n  }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Bekreft at Helmet 8.2.0 er installert:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>npm list helmet\n# Forventet output:\n# helmet-demo@1.0.0\n# \u2514\u2500\u2500 helmet@8.2.0<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Sjekk at ingen kjente s\u00e5rbarheter finnes i avhengighetene dine allerede fra start:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>npm audit\n# Ideelt svar:\n# found 0 vulnerabilities<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"steg-3-grunnleggende-helmet-oppsett\">Steg 3: Grunnleggende Helmet-oppsett<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Legg til Helmet som mellomvare tidlig i mellomvare-stabelen din. Rekkef\u00f8lge er avgj\u00f8rende i Express: Helmet m\u00e5 st\u00e5 f\u00f8r ruter og annen mellomvare som sender svar, fordi hoder ikke kan legges til etter at svaret er sendt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Opprett <code>src\/app.js<\/code> med f\u00f8lgende innhold:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const express = require('express');\nconst helmet = require('helmet');\n\nconst app = express();\n\n\/\/ Helmet M\u00c5 st\u00e5 \u00f8verst i mellomvare-stabelen\napp.use(helmet());\n\napp.get('\/', (req, res) => {\n  res.json({ melding: 'API kj\u00f8rer med Helmet-beskyttelse' });\n});\n\nconst PORT = process.env.PORT || 3000;\napp.listen(PORT, () => {\n  console.log(`Server kj\u00f8rer p\u00e5 port ${PORT}`);\n});\n\nmodule.exports = app;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Start serveren og test hodene med curl:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>npm run dev\n\n# I et nytt terminalvindu:\ncurl -I http:\/\/localhost:3000\/\n\n# Forventet output:\nHTTP\/1.1 200 OK\nContent-Security-Policy: default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests\nCross-Origin-Opener-Policy: same-origin\nCross-Origin-Resource-Policy: same-origin\nOrigin-Agent-Cluster: ?1\nReferrer-Policy: no-referrer\nStrict-Transport-Security: max-age=15552000; includeSubDomains\nX-Content-Type-Options: nosniff\nX-DNS-Prefetch-Control: off\nX-Download-Options: noopen\nX-Frame-Options: SAMEORIGIN\nX-Permitted-Cross-Domain-Policies: none\nX-XSS-Protection: 0<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Du ser n\u00e5 11 sikkerhetshoder satt automatisk. Legg merke til at <code>X-Powered-By: Express<\/code> er fjernet. Helmet sletter dette hodet fordi det r\u00f8per teknologi-stakken for angripere. <code>X-XSS-Protection<\/code> er satt til <code>0<\/code>, alts\u00e5 deaktivert. Dette er bevisst: det gamle nettleser-XSS-filteret skapte egne sikkerhetss\u00e5rbarheter i visse nettlesere og er i dag fullstendig erstattet av <code>Content-Security-Policy<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Sammenlign med en app uten Helmet. Start en tom Express-server uten Helmet og test hodene:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Uten Helmet:\nHTTP\/1.1 200 OK\nX-Powered-By: Express\nContent-Type: application\/json; charset=utf-8\nContent-Length: 42\nDate: Tue, 17 Jun 2026 12:00:00 GMT\nConnection: keep-alive\n\n# Med Helmet:\nHTTP\/1.1 200 OK\nContent-Security-Policy: [lang streng...]\nCross-Origin-Opener-Policy: same-origin\n# ... 10 flere sikkerhetshoder\n# X-Powered-By er IKKE med<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"steg-4-forsta-alle-standardhodene-i-helmet-8-2-0\">Steg 4: Forst\u00e5 alle standardhodene i Helmet 8.2.0<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Helmet 8.2.0 setter f\u00f8lgende hoder som standard. Det er viktig \u00e5 forst\u00e5 hva hvert hode gj\u00f8r og hvorfor standardverdien er valgt, slik at du kan ta gode beslutninger om tilpasning for din applikasjon.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>HTTP-hode<\/th><th>Standardverdi<\/th><th>Angrep blokkert<\/th><\/tr><\/thead><tbody><tr><td>Content-Security-Policy<\/td><td>default-src &#8216;self&#8217;; (lang streng)<\/td><td>XSS, data-injeksjon, ressursinjeksjon<\/td><\/tr><tr><td>Cross-Origin-Opener-Policy<\/td><td>same-origin<\/td><td>Spectre-baserte sidekanalangrep<\/td><\/tr><tr><td>Cross-Origin-Resource-Policy<\/td><td>same-origin<\/td><td>Cross-origin ressurslekkasje<\/td><\/tr><tr><td>Origin-Agent-Cluster<\/td><td>?1<\/td><td>Prosesisolasjon p\u00e5 tvers av opphav<\/td><\/tr><tr><td>Referrer-Policy<\/td><td>no-referrer<\/td><td>URL-lekkasje via Referer-hode<\/td><\/tr><tr><td>Strict-Transport-Security<\/td><td>max-age=15552000; includeSubDomains<\/td><td>SSL-stripping, nedgraderingsangrep<\/td><\/tr><tr><td>X-Content-Type-Options<\/td><td>nosniff<\/td><td>MIME-sniffing-angrep<\/td><\/tr><tr><td>X-DNS-Prefetch-Control<\/td><td>off<\/td><td>DNS-basert informasjonslekkasje<\/td><\/tr><tr><td>X-Download-Options<\/td><td>noopen<\/td><td>Kj\u00f8ring av nedlastede filer i IE<\/td><\/tr><tr><td>X-Frame-Options<\/td><td>SAMEORIGIN<\/td><td>Clickjacking<\/td><\/tr><tr><td>X-Permitted-Cross-Domain-Policies<\/td><td>none<\/td><td>Adobe Flash\/PDF cross-domain tilgang<\/td><\/tr><tr><td>X-Powered-By<\/td><td>(fjernet)<\/td><td>Teknologi-fingeravtrykk<\/td><\/tr><tr><td>X-XSS-Protection<\/td><td>0 (deaktivert)<\/td><td>Gammel XSS-filter deaktivert, erstattet av CSP<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Viktig merknad om X-XSS-Protection: 0.<\/strong> Det kan virke kontraintuitivt \u00e5 deaktivere et XSS-beskyttelse-hode, men det er riktig valg. Det gamle filteret i Internet Explorer og tidlige versjoner av Chrome og Safari introduserte egne reflekterte XSS-s\u00e5rbarheter via &#8220;XSS Auditor&#8221;-funksjonen. Moderne nettlesere har allerede fjernet denne funksjonaliteten. \u00c5 sette <code>X-XSS-Protection: 0<\/code> hindrer eldre nettlesere i \u00e5 aktivere den problematiske filteret, mens moderne nettlesere ignorerer hodet helt. CSP er den rette erstatningen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Se den <a href=\"https:\/\/helmetjs.github.io\/\" rel=\"noopener noreferrer\" target=\"_blank\">offisielle Helmet.js-dokumentasjonen<\/a> for fullstendig liste over konfigurasjonsalternativer for hvert enkelt hode.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"steg-5-konfigurer-content-security-policy-csp\">Steg 5: Konfigurer Content-Security-Policy (CSP)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Content-Security-Policy er det kraftigste hodet Helmet setter. Det forteller nettleseren n\u00f8yaktig hvilke ressurser den har lov til \u00e5 laste. En streng CSP stopper de fleste XSS-angrep selv om angriperen lykkes med \u00e5 injisere skadelig HTML i siden din.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Slik fungerer det i praksis: Anta at en angriper finner en SQL-injeksjonss\u00e5rbarhet i kommentarfeltet ditt og injiserer <code>&lt;script src=\"https:\/\/angriper.no\/skadelig.js\"&gt;&lt;\/script&gt;<\/code>. Uten CSP kj\u00f8rer nettleseren dette skriptet. Med CSP og <code>scriptSrc: [\"'self'\"]<\/code> nekter nettleseren \u00e5 laste skriptet fordi <code>angriper.no<\/code> ikke er p\u00e5 tilliste, og angrepet stopper der.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Standard CSP fra Helmet blokkerer alle ekstern-ressurser med <code>default-src 'self'<\/code>. For en typisk webapplikasjon med Google Fonts, CDN-skript og bilder fra eksterne tjenester, trenger du \u00e5 tilpasse dette:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>app.use(\n  helmet({\n    contentSecurityPolicy: {\n      directives: {\n        defaultSrc: [\"'self'\"],\n        scriptSrc: [\"'self'\", \"https:\/\/cdn.jsdelivr.net\"],\n        styleSrc: [\"'self'\", \"https:\", \"'unsafe-inline'\"],\n        imgSrc: [\"'self'\", \"data:\", \"https:\"],\n        fontSrc: [\"'self'\", \"https:\/\/fonts.gstatic.com\"],\n        connectSrc: [\"'self'\", \"https:\/\/api.dinapp.no\"],\n        frameSrc: [\"'none'\"],\n        objectSrc: [\"'none'\"],\n        baseUri: [\"'self'\"],\n        formAction: [\"'self'\"],\n        upgradeInsecureRequests: [],\n      },\n    },\n  })\n);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Direktivene du trenger \u00e5 kjenne til:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>defaultSrc<\/strong>: Fallback for alle ressurstyper som ikke har eget direktiv. Sett alltid denne til minst <code>'self'<\/code>.<\/li>\n<li><strong>scriptSrc<\/strong>: Tillatte opphav for JavaScript-filer. <code>'self'<\/code> betyr kun samme domene. Legg til spesifikke CDN-er du bruker.<\/li>\n<li><strong>styleSrc<\/strong>: Tillatte opphav for CSS. <code>'unsafe-inline'<\/code> er n\u00f8dvendig for mange CSS-rammeverk, men bruk nonce i stedet der det er mulig.<\/li>\n<li><strong>imgSrc<\/strong>: Tillatte opphav for bilder. <code>data:<\/code> tillater base64-innebygde bilder som brukes av mange UI-biblioteker.<\/li>\n<li><strong>fontSrc<\/strong>: Tillatte opphav for skriftfiler. Google Fonts bruker <code>fonts.gstatic.com<\/code> for selve fontfilene og <code>fonts.googleapis.com<\/code> for CSS-pekere.<\/li>\n<li><strong>connectSrc<\/strong>: Tillatte opphav for fetch, XHR og WebSocket-tilkoblinger. Legg til alle API-endepunkter applikasjonen kaller.<\/li>\n<li><strong>frameSrc<\/strong>: Kontrollerer hvilke domener som kan lastes i iframes i din side. <code>'none'<\/code> blokkerer alt.<\/li>\n<li><strong>objectSrc<\/strong>: Tillatte opphav for <code>&lt;object&gt;<\/code>, <code>&lt;embed&gt;<\/code> og <code>&lt;applet&gt;<\/code>-elementer. Sett til <code>'none'<\/code> for alle moderne applikasjoner.<\/li>\n<li><strong>baseUri<\/strong>: Begrenser verdier i <code>&lt;base&gt;<\/code>-elementet. Sett til <code>'self'<\/code> for \u00e5 hindre base-tag-injeksjon.<\/li>\n<li><strong>formAction<\/strong>: Begrenser URL-er som skjemaer kan sendes til. Viktig for \u00e5 hindre skjema-hijacking via XSS.<\/li>\n<li><strong>upgradeInsecureRequests<\/strong>: Ber nettleseren oppgradere HTTP-lenker til HTTPS automatisk. Aktiverer med tom array.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Se <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Headers\/Content-Security-Policy\" rel=\"noopener noreferrer\" target=\"_blank\">MDN CSP-dokumentasjonen<\/a> for fullstendig liste over direktiver og gyldige verdier.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"steg-6-konfigurer-strict-transport-security-hsts\">Steg 6: Konfigurer Strict-Transport-Security (HSTS)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">HSTS forteller nettleseren at den alltid skal bruke HTTPS for ditt domene, selv om brukeren skriver <code>http:\/\/<\/code> manuelt. Uten HSTS kan en aktiv nettverksangriper (for eksempel p\u00e5 en offentlig wifi-hotspot) gjennomf\u00f8re et SSL-stripping-angrep: de ser HTTP-foresp\u00f8rselen fra brukeren, kobler til din HTTPS-server p\u00e5 vegne av brukeren, og videresender trafikken ukryptert tilbake til brukeren. Brukeren ser en usikret tilkobling uten at nettleseren advarer, fordi HTTP er det de ba om.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">HSTS l\u00f8ser dette ved \u00e5 cache instruksjonen i nettleseren. Etter f\u00f8rste HTTPS-bes\u00f8k med HSTS-hodet, vil nettleseren aldri mer fors\u00f8ke HTTP-tilkobling til dette domenet i l\u00f8pet av <code>max-age<\/code>-perioden, selv om brukeren aktivt skriver <code>http:\/\/<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Helmet setter <code>max-age=15552000<\/code> (180 dager) og <code>includeSubDomains<\/code> som standard. For produksjon anbefaler <a href=\"https:\/\/owasp.org\/www-project-secure-headers\/\" rel=\"noopener noreferrer\" target=\"_blank\">OWASP Secure Headers Project<\/a> en <code>max-age<\/code> p\u00e5 minimum ett \u00e5r (31536000 sekunder) og \u00e5 inkludere <code>preload<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>app.use(\n  helmet({\n    strictTransportSecurity: {\n      maxAge: 31536000,        \/\/ 1 \u00e5r i sekunder\n      includeSubDomains: true, \/\/ Gjelder alle underdomener\n      preload: true,           \/\/ Tillat opptak i nettlesernes HSTS preload-lister\n    },\n  })\n);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>preload: true<\/code> betyr at du kan s\u00f8ke om \u00e5 f\u00e5 domenet ditt inn i nettlesernes HSTS preload-liste. Denne listen er innebygd i Chrome, Firefox, Safari og Edge. Domener p\u00e5 listen er hardkodet til HTTPS i alle nye nettleserinstallasjoner, selv f\u00f8r f\u00f8rste bes\u00f8k. Dette eliminerer &#8220;first visit&#8221;-problemet der HSTS ikke beskytter brukere som aldri har bes\u00f8kt siden din via HTTPS.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Aktiver ikke HSTS med <code>preload: true<\/code> p\u00e5 testmilj\u00f8er eller domener du ikke kontrollerer fullt ut. N\u00e5r et domene er i preload-listen, tvinger alle nettlesere HTTPS. Det kan ta m\u00e5neder \u00e5 bli fjernet fra listen. Sett HSTS kun p\u00e5 produksjonsdomenet, og kun etter at du har bekreftet at HTTPS fungerer for alle sider og underdomener.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"steg-7-x-frame-options-og-clickjacking-beskyttelse\">Steg 7: X-Frame-Options og clickjacking-beskyttelse<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Clickjacking-angrep fungerer ved \u00e5 legge din side i en usynlig iframe p\u00e5 en angriper-kontrollert side. Angriperen setter iframens opasitet til null (usynlig) og plasserer den over et lokke-element. N\u00e5r brukeren tror de klikker p\u00e5 for eksempel en &#8220;Vinn en iPhone&#8221;-knapp, klikker de faktisk p\u00e5 din applikasjons grensesnitt under. Angripere bruker dette til \u00e5 stjele klikk p\u00e5 bekreftelsesknapper for betalinger, kontosletting, tillatelse til kamera\/mikrofon, og deling av sensitiv informasjon.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Helmet setter <code>X-Frame-Options: SAMEORIGIN<\/code> som standard, som betyr at kun sider fra samme opphav kan laste inn siden din i en iframe. For de fleste applikasjoner b\u00f8r du sette dette til <code>DENY<\/code> for \u00e5 hindre all inlasting i iframes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>app.use(\n  helmet({\n    frameguard: {\n      action: 'deny', \/\/ Ingen kan frame siden din\n      \/\/ Alternativ: 'sameorigin' (standard) - kun eget domene kan frame\n    },\n    contentSecurityPolicy: {\n      directives: {\n        \/\/ frame-ancestors erstatter X-Frame-Options i moderne nettlesere\n        frameAncestors: [\"'none'\"],\n        defaultSrc: [\"'self'\"],\n        objectSrc: [\"'none'\"],\n      },\n    },\n  })\n);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Merk at <code>X-Frame-Options<\/code> er et eldre hode som ikke st\u00f8tter hvitelisting av spesifikke domener. Vil du tillate framing kun fra et spesifikt partner-domene, bruk <code>frame-ancestors<\/code>-direktivet i CSP: <code>frameAncestors: [\"https:\/\/partner.no\"]<\/code>. Bruk begge hodene for bred nettleser-kompatibilitet ned til eldre versjoner av Internet Explorer og Safari.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"steg-8-x-content-type-options-og-cross-origin-sikkerhet\">Steg 8: X-Content-Type-Options og Cross-Origin-sikkerhet<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">MIME-sniffing skjer n\u00e5r nettleseren ignorerer den deklarerte <code>Content-Type<\/code> og pr\u00f8ver \u00e5 gjette filtypen basert p\u00e5 innholdet. En angriper kan laste opp en fil med endelsen <code>.jpg<\/code>, men med JavaScript-innhold. Eldre nettlesere uten MIME-sniffing-beskyttelse kj\u00f8rer denne filen som JavaScript. Helmet setter <code>X-Content-Type-Options: nosniff<\/code> automatisk.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">S\u00f8rg alltid for at Express sender korrekte <code>Content-Type<\/code>-hoder. Express setter <code>application\/json<\/code> automatisk for <code>res.json()<\/code> og <code>text\/html<\/code> for <code>res.send()<\/code> med strenger. Unng\u00e5 \u00e5 sende r\u00e5data uten eksplisitt Content-Type.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To nyere hoder i Helmet gir beskyttelse mot sofistikerte sidekanalangrep basert p\u00e5 Spectre-prosessor-s\u00e5rbarheten:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Cross-Origin-Resource-Policy: same-origin<\/strong> hindrer andre nettsteder i \u00e5 laste ressursene dine (bilder, skript, data) via <code>fetch<\/code> eller <code>XMLHttpRequest<\/code>. Uten dette hodet kan en ondsinnet nettside laste inn bilder fra din autentiserte applikasjon og bruke Spectre-timing-angrep for \u00e5 lese piksel-dataene fra nettleserminnet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Cross-Origin-Opener-Policy: same-origin<\/strong> isolerer nettleservinduet ditt fra andre vinduer og tabs. Det hindrer angripere i \u00e5 holde en referanse til vinduet ditt etter navigasjon, noe som er en forutsetning for visse timer-baserte sidekanalangrep og window.opener-baserte angrep.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>app.use(\n  helmet({\n    noSniff: true,  \/\/ Standard, trenger ikke sette eksplisitt\n    crossOriginResourcePolicy: {\n      policy: 'same-origin', \/\/ Alternativ: 'cross-origin' for \u00e5pne ressurser\n    },\n    crossOriginOpenerPolicy: {\n      policy: 'same-origin', \/\/ Alternativ: 'same-origin-allow-popups' for popup-apper\n    },\n  })\n);<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"steg-9-referrer-policy-og-informasjonslekkasje\">Steg 9: Referrer-Policy og informasjonslekkasje<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Nettleseren sender som standard <code>Referer<\/code>-hodet med full URL n\u00e5r brukeren klikker p\u00e5 en lenke eller sender en foresp\u00f8rsel. Dette kan lekke sensitive URL-parametere til tredjepartstjenester. Et praktisk eksempel: brukeren klikker p\u00e5 en lenke fra en side med URL <code>https:\/\/dinapp.no\/tilbakestill-passord?token=abc123<\/code>. Dersom siden inkluderer en tredjepartsfont, script eller sporingspiksel, mottar tredjepartens server dette token via <code>Referer<\/code>-hodet, og en angriper som kontrollerer den tjenesten kan bruke tokenet til \u00e5 tilbakestille brukerens passord.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Helmet setter <code>no-referrer<\/code> som standard. For applikasjoner som trenger Referrer-informasjon for analyseverkt\u00f8y (for \u00e5 spore hvilke sider brukere kommer fra), bruk <code>strict-origin-when-cross-origin<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>app.use(\n  helmet({\n    referrerPolicy: {\n      \/\/ 'no-referrer' (standard): Send ingen referrer-info til noen\n      \/\/ 'strict-origin': Send kun domene (ikke sti) til andre opphav\n      \/\/ 'strict-origin-when-cross-origin': Full URL til samme opphav,\n      \/\/   kun domene til andre opphav via HTTPS\n      \/\/ 'origin-when-cross-origin': Full URL internt, kun domene eksternt\n      policy: 'strict-origin-when-cross-origin',\n    },\n  })\n);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Velg politikk basert p\u00e5 sensitiviteten til URL-parametere i applikasjonen din. For bankapplikasjoner, helsetjenester og apper med engangstokener i URL-er: bruk alltid <code>no-referrer<\/code> eller <code>strict-origin<\/code>. For e-handelssider med analyse-behov: <code>strict-origin-when-cross-origin<\/code> er en god balanse.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"steg-10-nonce-basert-csp-for-inline-skript\">Steg 10: Nonce-basert CSP for inline-skript<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Mange applikasjoner trenger inline-JavaScript i HTML-sider, for eksempel for \u00e5 injisere konfigurasjonsdata fra serveren: applikasjonsnavn, bruker-ID, funksjonsflagg og liknende. Med en streng CSP som blokkerer <code>'unsafe-inline'<\/code>, feiler disse skriptene. L\u00f8sningen er nonce-basert CSP.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En CSP-nonce er en tilfeldig base64-streng som genereres av serveren for hvert HTTP-svar. Serveren setter <code>'nonce-ABC123'<\/code> i CSP-hodet, der <code>ABC123<\/code> er noncen. I HTML-en legger du <code>nonce=\"ABC123\"<\/code> p\u00e5 <code>&lt;script&gt;<\/code>&#8211; og <code>&lt;style&gt;<\/code>-elementer. Nettleseren tillater kun kj\u00f8ring av elementer der nonce-attributtet matcher CSP-hodesverdien. En angriper som injiserer <code>&lt;script&gt;ondsinnet()&lt;\/script&gt;<\/code> f\u00e5r ikke skriptet til \u00e5 kj\u00f8re fordi de ikke kjenner noncen for dette spesifikke svaret.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const crypto = require('crypto');\nconst express = require('express');\nconst helmet = require('helmet');\n\nconst app = express();\n\n\/\/ Generer unik nonce for hvert svar\napp.use((req, res, next) => {\n  res.locals.cspNonce = crypto.randomBytes(16).toString('base64');\n  next();\n});\n\n\/\/ Bruk nonce i CSP - ny Helmet-instans per svar\napp.use((req, res, next) => {\n  return helmet({\n    contentSecurityPolicy: {\n      directives: {\n        defaultSrc: [\"'self'\"],\n        scriptSrc: [\"'self'\", `'nonce-${res.locals.cspNonce}'`],\n        styleSrc: [\"'self'\", `'nonce-${res.locals.cspNonce}'`, \"https:\"],\n        objectSrc: [\"'none'\"],\n        baseUri: [\"'self'\"],\n        upgradeInsecureRequests: [],\n      },\n    },\n  })(req, res, next);\n});\n\n\/\/ HTML-rute som bruker nonce i skript og stil\napp.get('\/', (req, res) => {\n  const brukerKonfig = { versjon: '1.0.0', env: 'produksjon' };\n\n  res.send(`\n    <!DOCTYPE html>\n    <html lang=\"no\">\n      <head>\n        <meta charset=\"UTF-8\">\n        <title>Sikker app<\/title>\n        <style nonce=\"${res.locals.cspNonce}\">\n          body { font-family: sans-serif; padding: 2rem; background: #f5f5f5; }\n          h1 { color: #2c3e50; }\n        <\/style>\n      <\/head>\n      <body>\n        <h1>Sikker Node.js-app med Helmet.js<\/h1>\n        <p>Applikasjonen kj\u00f8rer med full Helmet-beskyttelse.<\/p>\n        <script nonce=\"${res.locals.cspNonce}\">\n          const konfig = ${JSON.stringify(brukerKonfig)};\n          console.log('Appversjon:', konfig.versjon);\n          console.log('Milj\u00f8:', konfig.env);\n        <\/script>\n      <\/body>\n    <\/html>\n  `);\n});\n\napp.listen(3000);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Nonce-verdien skal v\u00e6re unik for hvert HTTP-svar og aldri gjenbrukes. <code>crypto.randomBytes(16)<\/code> gir 128 bits entropi, mer enn nok til \u00e5 gj\u00f8re brute-force-gjetting praktisk umulig. Merk at dette betyr at du ikke kan bruke <code>app.use(helmet(...))<\/code> \u00e9n gang globalt med nonce-verdier, fordi nonce-verdien er ukjent p\u00e5 det tidspunktet. L\u00f8sningen er \u00e5 opprette en ny Helmet-instans per svar via en mellomvare-fabrikk, som vist i kodeeksempelet over.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"steg-11-rutebasert-overstyring-av-helmet-konfigurasjon\">Steg 11: Rutebasert overstyring av Helmet-konfigurasjon<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ulike ruter kan trenge ulike sikkerhetshoder. Et offentlig API som serverer data til tredjeparts klienter trenger en annen CORP-innstilling enn private ruter. Et dashboard som laster inn tredjeparts widgets trenger bredere CSP-regler enn en innloggingsside.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Express sin mellomvare-kjeding gj\u00f8r dette mulig. Registrer en global Helmet-konfigurasjon for de fleste ruter, og overstyr den for spesifikke ruter:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const express = require('express');\nconst helmet = require('helmet');\n\nconst app = express();\n\n\/\/ Global Helmet-konfigurasjon for alle ruter\napp.use(helmet({\n  contentSecurityPolicy: {\n    directives: {\n      defaultSrc: [\"'self'\"],\n      scriptSrc: [\"'self'\"],\n      objectSrc: [\"'none'\"],\n    },\n  },\n  frameguard: { action: 'deny' },\n}));\n\n\/\/ Dashboard-rute som trenger ekstern widget-CDN\nconst dashboardHelmet = helmet({\n  contentSecurityPolicy: {\n    directives: {\n      defaultSrc: [\"'self'\"],\n      scriptSrc: [\"'self'\", \"https:\/\/cdn.widget-leverandor.no\"],\n      frameSrc: [\"https:\/\/widget-leverandor.no\"],\n      imgSrc: [\"'self'\", \"https:\/\/widget-leverandor.no\", \"data:\"],\n      objectSrc: [\"'none'\"],\n    },\n  },\n  frameguard: { action: 'sameorigin' }, \/\/ Tillat framing fra eget domene\n});\n\n\/\/ Helmet-instanser i rute-definisjoner kj\u00f8res ETTER global Helmet\n\/\/ Det siste hodet vinner - test alltid med curl -I\napp.get('\/dashboard', dashboardHelmet, (req, res) => {\n  res.json({ side: 'dashboard', tillatteWidgets: true });\n});\n\n\/\/ Offentlig API-rute der andre domener skal hente data\nconst offentligApiHelmet = helmet({\n  crossOriginResourcePolicy: {\n    policy: 'cross-origin', \/\/ Tillat cross-origin tilgang til denne ressursen\n  },\n});\n\napp.get('\/api\/v1\/offentlig', offentligApiHelmet, (req, res) => {\n  res.json({ data: 'tilgjengelig for alle opphav' });\n});\n\n\/\/ Private API-ruter bruker global Helmet (same-origin CORP som standard)\napp.get('\/api\/v1\/privat', (req, res) => {\n  res.json({ brukerdata: 'kun tilgjengelig fra eget opphav' });\n});<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"steg-12-test-og-verifiser-alle-sikkerhetshoder\">Steg 12: Test og verifiser alle sikkerhetshoder<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Testing er like viktig som konfigurasjon. Feil konfigurasjon som passerer usett er verre enn ingen konfigurasjon, fordi den gir falsk trygghet. Det finnes tre testmetoder: manuell med curl, automatisert med kode, og nettbaserte skannere.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Metode 1: Manuell test med curl<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Vis alle svar-hoder\ncurl -I http:\/\/localhost:3000\/\n\n# Filtrer de viktigste sikkerhetshoder\ncurl -s -I http:\/\/localhost:3000\/ | grep -iE \"(content-security|x-frame|strict-transport|x-content-type|referrer|cross-origin)\"\n\n# Bekreft at X-Powered-By er fjernet (ingen output = fjernet)\ncurl -s -I http:\/\/localhost:3000\/ | grep -i \"x-powered-by\"\n\n# Test at X-XSS-Protection er satt til 0\ncurl -s -I http:\/\/localhost:3000\/ | grep -i \"x-xss-protection\"\n# X-XSS-Protection: 0\n\n# Test HSTS i produksjon (krever HTTPS)\ncurl -s -I https:\/\/dinapp.no\/ | grep -i \"strict-transport-security\"\n# Strict-Transport-Security: max-age=31536000; includeSubDomains; preload<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Metode 2: Automatisert test i kode<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const assert = require('assert');\nconst http = require('http');\nconst app = require('.\/src\/app');\n\nlet server;\n\nbefore((done) => {\n  server = app.listen(3001, done);\n});\n\nafter((done) => {\n  server.close(done);\n});\n\nasync function testSikkerhetshoder() {\n  return new Promise((resolve, reject) => {\n    http.get('http:\/\/localhost:3001\/', (res) => {\n      const hoder = res.headers;\n\n      \/\/ CSP skal v\u00e6re satt\n      assert.ok(hoder['content-security-policy'], 'FEIL: CSP mangler');\n      assert.ok(\n        hoder['content-security-policy'].includes(\"default-src 'self'\"),\n        'FEIL: CSP mangler default-src self'\n      );\n\n      \/\/ HSTS skal v\u00e6re satt\n      assert.ok(hoder['strict-transport-security'], 'FEIL: HSTS mangler');\n\n      \/\/ X-Powered-By skal IKKE v\u00e6re satt\n      assert.ok(!hoder['x-powered-by'], 'FEIL: X-Powered-By er ikke fjernet');\n\n      \/\/ X-Frame-Options skal v\u00e6re satt\n      assert.ok(hoder['x-frame-options'], 'FEIL: X-Frame-Options mangler');\n\n      \/\/ X-Content-Type-Options skal v\u00e6re nosniff\n      assert.strictEqual(\n        hoder['x-content-type-options'],\n        'nosniff',\n        'FEIL: X-Content-Type-Options er ikke nosniff'\n      );\n\n      \/\/ Referrer-Policy skal v\u00e6re satt\n      assert.ok(hoder['referrer-policy'], 'FEIL: Referrer-Policy mangler');\n\n      \/\/ Cross-Origin-Resource-Policy skal v\u00e6re satt\n      assert.ok(hoder['cross-origin-resource-policy'], 'FEIL: CORP mangler');\n\n      console.log('Alle sikkerhetshoder verifisert \u2713');\n      resolve();\n    }).on('error', reject);\n  });\n}\n\ntestSikkerhetshoder().catch((err) => {\n  console.error('Sikkerhetstest feilet:', err.message);\n  process.exit(1);\n});<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Metode 3: Nettbasert skanner.<\/strong> For produksjonstesting: skann nettadressen din med securityheaders.com. Tjenesten gir en karakter fra A+ til F. En ny Express-app uten Helmet scorer typisk F. Med korrekt Helmet-konfigurasjon scorer du A eller A+. Mozilla Observatory (observatory.mozilla.org) er et annet godt alternativ som sjekker enda flere sikkerhetsindikatorer.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"komplett-prosjekt-produksjonsklar-sikker-express-app\">Komplett prosjekt: Produksjonsklar sikker Express-app<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Her er et komplett, produksjonsklart eksempel som kombinerer alle stegene. Denne koden er egnet som utgangspunkt for alle nye Express-prosjekter med norske brukere eller virksomheter underlagt NIS2\/Digitalsikkerhetsloven.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>'use strict';\n\nconst crypto = require('crypto');\nconst express = require('express');\nconst helmet = require('helmet');\n\nconst app = express();\nconst isProd = process.env.NODE_ENV === 'production';\n\n\/\/ Grense p\u00e5 foresp\u00f8rsels-kropper for \u00e5 hindre DoS\napp.use(express.json({ limit: '10kb' }));\napp.use(express.urlencoded({ extended: true, limit: '10kb' }));\n\n\/\/ Generer CSP-nonce for hvert svar\napp.use((req, res, next) => {\n  res.locals.cspNonce = crypto.randomBytes(16).toString('base64');\n  next();\n});\n\n\/\/ Helmet-konfigurasjon\napp.use((req, res, next) => {\n  return helmet({\n    contentSecurityPolicy: {\n      directives: {\n        defaultSrc: [\"'self'\"],\n        scriptSrc: [\"'self'\", `'nonce-${res.locals.cspNonce}'`],\n        styleSrc: [\"'self'\", `'nonce-${res.locals.cspNonce}'`, \"https:\"],\n        imgSrc: [\"'self'\", \"data:\", \"https:\"],\n        fontSrc: [\"'self'\", \"https:\", \"data:\"],\n        connectSrc: [\"'self'\"],\n        frameSrc: [\"'none'\"],\n        objectSrc: [\"'none'\"],\n        baseUri: [\"'self'\"],\n        formAction: [\"'self'\"],\n        frameAncestors: [\"'none'\"],\n        upgradeInsecureRequests: isProd ? [] : null,\n        \/\/ Samle brudd-rapporter i produksjon:\n        ...(isProd && { reportUri: ['\/api\/csp-rapport'] }),\n      },\n      reportOnly: !isProd, \/\/ Test CSP i rapport-modus i utvikling\n    },\n\n    \/\/ HSTS kun i produksjon\n    strictTransportSecurity: isProd\n      ? { maxAge: 31536000, includeSubDomains: true, preload: true }\n      : false,\n\n    frameguard: { action: 'deny' },\n    crossOriginOpenerPolicy: { policy: 'same-origin' },\n    crossOriginResourcePolicy: { policy: 'same-origin' },\n    referrerPolicy: { policy: 'strict-origin-when-cross-origin' },\n    noSniff: true,\n    dnsPrefetchControl: { allow: false },\n    hidePoweredBy: true,\n  })(req, res, next);\n});\n\n\/\/ Helse-endepunkt\napp.get('\/helse', (req, res) => {\n  res.json({ status: 'ok', tidspunkt: new Date().toISOString() });\n});\n\n\/\/ API-endepunkt\napp.get('\/api\/v1\/data', (req, res) => {\n  res.json({\n    melding: 'Sikret med Helmet.js 8.2.0',\n    miljo: process.env.NODE_ENV || 'utvikling',\n  });\n});\n\n\/\/ Motta CSP-brudd-rapporter\nif (isProd) {\n  app.post(\n    '\/api\/csp-rapport',\n    express.json({ type: 'application\/csp-report' }),\n    (req, res) => {\n      console.warn('CSP-brudd:', JSON.stringify(req.body));\n      res.status(204).end();\n    }\n  );\n}\n\n\/\/ Global feilh\u00e5ndtering - ingen stack trace til klienten\napp.use((err, req, res, next) => {\n  console.error(err.stack);\n  res.status(500).json({ feil: 'Intern serverfeil' });\n});\n\nconst PORT = process.env.PORT || 3000;\napp.listen(PORT, () => {\n  console.log(`Server kj\u00f8rer p\u00e5 port ${PORT} [${process.env.NODE_ENV || 'utvikling'}]`);\n});\n\nmodule.exports = app;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"helmet-js-og-owasp-sikkerhetskontrollist\">Helmet.js og OWASP: sikkerhetskontrollist<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">OWASP Security Headers Project definerer et standardsett med sikkerhetshoder og anbefaler konfigurasjonsverdier for hvert. Tabellen nedenfor viser hvordan Helmets standardkonfigurasjon dekker OWASP-anbefalingene, og hva du b\u00f8r justere for full samsvar.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>OWASP-anbefaling<\/th><th>Helmet standard<\/th><th>Behov for justering?<\/th><th>Anbefalt justering<\/th><\/tr><\/thead><tbody><tr><td>CSP med strict-dynamic eller nonce<\/td><td>Grunnleggende CSP<\/td><td>Ja<\/td><td>Bruk nonce-basert CSP (steg 10)<\/td><\/tr><tr><td>HSTS max-age &gt;= 1 \u00e5r<\/td><td>180 dager (15552000)<\/td><td>Ja i produksjon<\/td><td>Sett maxAge: 31536000<\/td><\/tr><tr><td>HSTS preload<\/td><td>Ikke satt som standard<\/td><td>Ja for produksjon<\/td><td>Legg til preload: true<\/td><\/tr><tr><td>X-Frame-Options DENY<\/td><td>SAMEORIGIN<\/td><td>For de fleste apper<\/td><td>Sett action: &#8216;deny&#8217;<\/td><\/tr><tr><td>Referrer-Policy strict-origin<\/td><td>no-referrer<\/td><td>Valgfritt<\/td><td>no-referrer er strengere, OK<\/td><\/tr><tr><td>CORP same-origin<\/td><td>same-origin<\/td><td>Nei<\/td><td>Standard er korrekt<\/td><\/tr><tr><td>Fjern X-Powered-By<\/td><td>Fjernet automatisk<\/td><td>Nei<\/td><td>Standard er korrekt<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">For norske virksomheter underlagt NIS2 gjelder kravene i Digitalsikkerhetsloven om \u00e5 implementere egnede tekniske tiltak for \u00e5 beskytte nettverks- og informasjonssystemer. Korrekt satte HTTP-sikkerhetshoder er et grunnleggende og veldokumentert tiltak som er lett \u00e5 verifisere og auditere.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"vanlige-feil-og-fallgruver\">Vanlige feil og fallgruver<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Disse feilene dukker opp igjen og igjen i produksjons-implementasjoner av Helmet:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Feil 1: Helmet etter ruter i mellomvare-stabelen.<\/strong> Express kj\u00f8rer mellomvare i den rekkef\u00f8lgen du registrerer den. Registrerer du <code>app.use(helmet())<\/code> etter <code>app.use(router)<\/code>, setter ikke Helmet hoder p\u00e5 svar fra ruteren. Plasser alltid Helmet \u00f8verst i mellomvare-stabelen, rett etter parsing av kropp og logging. Kontroller med curl at hodene faktisk finnes i svarene fra ruter-endepunktene dine, ikke bare fra rot-ruten.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Feil 2: CSP bryter tredjepartsintegrasjoner.<\/strong> Den vanligste \u00e5rsaken til at Helmet &#8220;\u00f8delegger&#8221; ting er en for streng CSP. Kartlegg alle eksterne ressurser applikasjonen laster (skript, stiler, fonter, bilder, API-kall, WebSocket-tilkoblinger) og legg dem til i CSP-direktivene. Bruk nettleserens konsoll under utvikling for \u00e5 se CSP-brudd i sanntid.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Feil 3: HSTS p\u00e5 testdomener.<\/strong> Aktiverer du HSTS med h\u00f8y <code>max-age<\/code> p\u00e5 et testdomene, l\u00e5ser du dette domenet til HTTPS i alle nettlesere som bes\u00f8ker det. Bruk betingelser: aktiver HSTS kun i produksjon via <code>process.env.NODE_ENV === 'production'<\/code>. Har du gjort denne feilen, kan du nullstille ved \u00e5 sette <code>max-age=0<\/code> og la brukere bes\u00f8ke siden via HTTPS med det hodet, men dette tar tid.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Feil 4: Gjenbruk av CSP-nonce.<\/strong> Nonce-verdien M\u00c5 genereres p\u00e5 nytt for hvert HTTP-svar. Lagrer du nonce som en global variabel eller i express-sesjon og gjenbruker den for alle svar, kan en angriper stjele nonce-verdien fra ett svar og bruke den til \u00e5 kj\u00f8re injiserte skript i et annet svar. Bruk alltid <code>crypto.randomBytes()<\/code> per foresp\u00f8rsel.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Feil 5: CORP blokkerer offentlig API.<\/strong> <code>Cross-Origin-Resource-Policy: same-origin<\/code> er riktig for private ressurser, men bryter offentlige API-er som skal kalles fra andre domener. Sett <code>crossOriginResourcePolicy: { policy: 'cross-origin' }<\/code> for API-endepunkter som skal v\u00e6re \u00e5pne for alle opphav.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Feil 6: For bred scriptSrc med unsafe-eval.<\/strong> Mange setter <code>'unsafe-eval'<\/code> i <code>scriptSrc<\/code> fordi et bibliotek krever det (typisk eldre versjoner av Angular eller template engines). <code>'unsafe-eval'<\/code> tillater bruk av <code>eval()<\/code>, <code>Function()<\/code>, <code>setTimeout<\/code>\/<code>setInterval<\/code> med strenger, og liknende. Dette er en av de farligste CSP-direktiv-verdiene fordi den \u00e5pner for kodeinjeksjon. Oppgrader biblioteket eller finn et alternativ fremfor \u00e5 akseptere <code>'unsafe-eval'<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"feilsoking-8-symptomer-med-losninger\">Feils\u00f8king: 8 symptomer med l\u00f8sninger<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Symptom<\/th><th>\u00c5rsak<\/th><th>L\u00f8sning<\/th><\/tr><\/thead><tbody><tr><td>Google Fonts lastes ikke inn<\/td><td>fontSrc mangler fonts.gstatic.com og fonts.googleapis.com<\/td><td>Legg til begge domenene i fontSrc og styleSrc<\/td><\/tr><tr><td>Bilder fra CDN vises ikke<\/td><td>imgSrc mangler CDN-domenet<\/td><td>Legg CDN-domenet til imgSrc<\/td><\/tr><tr><td>Inline-skript blokkert av CSP<\/td><td>CSP mangler nonce eller &#8216;unsafe-inline&#8217;<\/td><td>Bruk nonce-basert CSP fra steg 10<\/td><\/tr><tr><td>CORS-feil etter Helmet<\/td><td>CORP-hode blokkerer cross-origin-kall<\/td><td>Sett crossOriginResourcePolicy: &#8216;cross-origin&#8217; for \u00e5pne endepunkter<\/td><\/tr><tr><td>Innlogging via iframe feiler<\/td><td>X-Frame-Options DENY blokkerer innlogging i widget<\/td><td>Sett frameguard: { action: &#8216;sameorigin&#8217; } for den ruten<\/td><\/tr><tr><td>HSTS l\u00e5ser ut testmilj\u00f8 p\u00e5 HTTP<\/td><td>HSTS aktivert i ikke-produksjonsmilj\u00f8<\/td><td>Betinget aktivering: process.env.NODE_ENV === &#8216;production&#8217;<\/td><\/tr><tr><td>PDF-innlasting via Adobe feiler<\/td><td>X-Permitted-Cross-Domain-Policies: none<\/td><td>Sett permittedCrossDomainPolicies: { permittedPolicies: &#8216;master-only&#8217; }<\/td><\/tr><tr><td>WebSocket-tilkobling feiler<\/td><td>connectSrc mangler wss:\/\/<\/td><td>Legg til &#8220;wss:\/\/din-server.no&#8221; i connectSrc-direktivet<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">N\u00e5r du feils\u00f8ker CSP-problemer, \u00e5pne nettleserens utviklerverkt\u00f8y (F12) og se i konsollen. Nettleseren gir presise feilmeldinger som forteller n\u00f8yaktig hvilken ressurs som ble blokkert:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Typisk CSP-feilmelding i Chrome-konsollen:\nRefused to load the script 'https:\/\/eksempel.no\/skript.js' because it violates\nthe following Content Security Policy directive: \"script-src 'self'\".\nNote that 'script-src-elem' was not explicitly set, so 'script-src' is used as fallback.\n\n# L\u00f8sning: Legg til domenet i scriptSrc-direktivet:\nscriptSrc: [\"'self'\", \"https:\/\/eksempel.no\"],\n\n# CSP-brudd for font:\nRefused to load the font 'https:\/\/fonts.gstatic.com\/s\/roboto\/v30\/...' because\nit violates the following Content Security Policy directive: \"font-src 'self'\".\n\n# L\u00f8sning:\nfontSrc: [\"'self'\", \"https:\/\/fonts.gstatic.com\"],<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"avanserte-tips-for-produksjonsmiljoer\">Avanserte tips for produksjonsmilj\u00f8er<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>1. CSP-rapportering i produksjon.<\/strong> Bruk <code>report-uri<\/code> eller <code>report-to<\/code>-direktivet for \u00e5 samle inn CSP-brudd-rapporter fra ekte brukere. Dette gir synlighet i injeksjonsfors\u00f8k og konfigurasjonsfeil du aldri ser i testmilj\u00f8et. En angriper som pr\u00f8ver XSS vil generere brudd-rapporter som du kan bruke til \u00e5 oppdage og respondere p\u00e5 angrepsfors\u00f8k:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>contentSecurityPolicy: {\n  directives: {\n    defaultSrc: [\"'self'\"],\n    reportUri: ['\/api\/csp-rapport'], \/\/ Motta brudd-rapporter\n  },\n  reportOnly: !isProd, \/\/ I utvikling: kun rapporter, ikke blokker\n},\n\n\/\/ Endepunkt for \u00e5 motta og logge brudd-rapporter\napp.post('\/api\/csp-rapport',\n  express.json({ type: 'application\/csp-report' }),\n  (req, res) => {\n    const rapport = req.body['csp-report'];\n    if (rapport) {\n      console.warn('CSP-brudd oppdaget:', {\n        blokkertUri: rapport['blocked-uri'],\n        bruddDirectiv: rapport['violated-directive'],\n        kildeFil: rapport['source-file'],\n        linjenummer: rapport['line-number'],\n      });\n      \/\/ Send til logg-system (f.eks. Elasticsearch, Datadog)\n    }\n    res.status(204).end();\n  }\n);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>2. Bruk CSP i report-only modus ved overgang til ny CSP.<\/strong> N\u00e5r du strammer inn CSP-reglene p\u00e5 et eksisterende system, skru p\u00e5 <code>reportOnly: true<\/code> i to til fire uker. Analyser brudd-rapportene, legg til legitime kilder i direktivene, og skru deretter av report-only modus. Dette unng\u00e5r produksjonsbrudd for reelle brukere.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>3. Kombiner Helmet med rate limiting.<\/strong> Helmet beskytter mot header-baserte angrep, men ikke mot brute-force eller DoS. Kombiner alltid med rate limiting p\u00e5 autentiserings-endepunkter. Se v\u00e5r guide om <a href=\"\/https-tls-13-nodejs\/\">HTTPS og TLS 1.3 i Node.js<\/a> for konfigurering av sikker transportlag.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>4. Automatisk oppdatering av Helmet.<\/strong> Helmet-teamet oppdaterer standardverdier basert p\u00e5 endringer i nettleser-st\u00f8tte og nye sikkerhetsstandarder. Kj\u00f8r <code>npm outdated<\/code> ukentlig og oppdater Helmet ved nye versjoner. Bruk Dependabot eller Renovate for automatiske oppdaterings-PR-er. Les changelog ved oppgradering fra 7.x til 8.x: det ble endringer i standardverdier for CORP og COOP. Se <a href=\"https:\/\/github.com\/helmetjs\/helmet\" rel=\"noopener noreferrer\" target=\"_blank\">Helmet GitHub-repositoriet<\/a> for full changelog.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>5. Kombiner med passordhashing p\u00e5 database-laget.<\/strong> Helmet gir nettverkslag-beskyttelse. Passordhashing p\u00e5 database-laget er like viktig. Les mer i v\u00e5r guide om <a href=\"\/scrypt-passordhashing-nodejs\/\">scrypt Passordhashing i Node.js<\/a> for moderne, minnehard passordhashing.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>6. Deployment-sjekkliste.<\/strong> G\u00e5 gjennom disse punktene f\u00f8r du setter Helmet i produksjon:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Bekreft med curl at alle 11 sikkerhetshoder er satt p\u00e5 alle endepunkter.<\/li>\n<li>Verifiser at <code>X-Powered-By<\/code> er fjernet.<\/li>\n<li>Test at CSP ikke blokkerer noe som brukerne trenger (fonter, bilder, API-kall).<\/li>\n<li>Aktiver CSP i report-only modus i minst \u00e9n uke i produksjon og analyser rapporter.<\/li>\n<li>Bekreft at HSTS kun er aktivert for produksjonsdomenet med gyldig HTTPS-sertifikat.<\/li>\n<li>Sjekk securityheaders.com og s\u00f8rg for A eller A+ karakter.<\/li>\n<li>Dokumenter CSP-reglene og begrunn alle ikke-standard direktiver.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"relatert-dekning\">Relatert dekning<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Utdyp sikkerhetskunnskapen din med disse artiklene fra shattered.io:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"\/https-tls-13-nodejs\/\">HTTPS og TLS 1.3 i Node.js: 12 steg [2026]<\/a> &#8211; Krypter transportlaget med TLS 1.3 og sett opp sertifikater.<\/li>\n<li><a href=\"\/scrypt-passordhashing-nodejs\/\">scrypt Passordhashing i Node.js: 11 steg [2026]<\/a> &#8211; Sikker passordhashing med minneharde algoritmer.<\/li>\n<li><a href=\"\/ssh-nokkel-linux\/\">SSH-n\u00f8kkel i Linux: sikker innlogging i 10 steg [2026]<\/a> &#8211; Konfigurer SSH-n\u00f8kkelbasert autentisering p\u00e5 Linux.<\/li>\n<li><a href=\"\/wireguard-vpn-linux\/\">WireGuard VPN p\u00e5 Linux: 12 steg, 1472 Mbps [2026]<\/a> &#8211; Sett opp kryptert VPN-tunnel med WireGuard.<\/li>\n<li><a href=\"\/passordsikkerhet\/\">Passordsikkerhet: sterke passord, hashing og tofaktor<\/a> &#8211; Grunnleggende passordsikkerhet forklart.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"ofte-stilte-sporsmal\">Ofte stilte sp\u00f8rsm\u00e5l<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Trenger jeg Helmet.js hvis jeg bruker en omvendt proxy som Nginx?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ja. Nginx kan sette noen statiske sikkerhetshoder via <code>add_header<\/code>-direktiver, men Helmet gir granul\u00e6r kontroll per rute i Express og st\u00f8tter dynamiske verdier som nonce-basert CSP. CSP-regler med nonce krever generering per svar, noe Nginx ikke kan gj\u00f8re uten Lua-moduler og mye ekstra konfigurasjon. Den vanlige praksisen er \u00e5 bruke Nginx for HSTS og grunnleggende statiske hoder, og Helmet for CSP og applikasjonsspesifikke hoder der dynamikk er n\u00f8dvendig.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Er Helmet.js kompatibelt med Express 5?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ja. Helmet 8.2.0 st\u00f8tter b\u00e5de Express 4.x og 5.x. Mellomvare-API-et er identisk. Oppgrader Express og Helmet separat og kj\u00f8r testene etter hvert steg for \u00e5 minimere risiko.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Hva med Fastify i stedet for Express?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Helmet er skrevet for Express. For Fastify bruker du <code>@fastify\/helmet<\/code>, som er en offisiell wrapper rundt Helmet med Fastify-kompatibelt API. Installasjon med <code>npm install @fastify\/helmet<\/code> og registrering med <code>await fastify.register(require('@fastify\/helmet'))<\/code>. Konfigurasjonssyntaksen er nesten identisk med Express-varianten.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Kan Helmet erstatte en Web Application Firewall (WAF)?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nei. Helmet setter sikkerhetshoder som p\u00e5virker nettleser-oppf\u00f8rsel for utg\u00e5ende svar. En WAF filtrerer innkommende trafikk og blokkerer angrep p\u00e5 nettverkslaget, for eksempel SQL-injeksjon, path traversal og volumetriske angrep. De to l\u00f8sningene utfyller hverandre og adresserer ulike angrepsvektorer. For produksjon bruker du begge.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Virker Helmet for REST-APIer uten nettleser-klienter?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Delvis. CSP og X-Frame-Options gir lite verdi for maskin-til-maskin-APIer uten nettleser-klient. Men HSTS, X-Content-Type-Options og CORP gir fortsatt verdi. Fjern hoder som ikke er relevante med for eksempel <code>contentSecurityPolicy: false<\/code> og <code>frameguard: false<\/code> for rene API-servere uten nettleser-klienter.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>P\u00e5virker Helmet ytelsen merkbart?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Negligerbart. Helmet setter hoder i JavaScript-minnet, uten I\/O-operasjoner eller tunge beregninger (med unntak av nonce-generering med <code>crypto.randomBytes(16)<\/code>). Overhead er under 0,1 millisekund per foresp\u00f8rsel p\u00e5 typisk servermaskinvare. Ytelsesp\u00e5virkning er ikke en grunn til \u00e5 utelate Helmet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Hvilket hode gir mest sikkerhet?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Content-Security-Policy. En korrekt konfigurert CSP stopper de aller fleste XSS-angrep, selv om angriperen klarer \u00e5 injisere skadelig HTML. XSS er konsekvent blant de 10 mest utbredte s\u00e5rbarhetstypene if\u00f8lge <a href=\"https:\/\/owasp.org\/www-project-secure-headers\/\" rel=\"noopener noreferrer\" target=\"_blank\">OWASP Secure Headers Project<\/a>. CSP er den mest effektive header-baserte forsvarslinjen mot denne trusselen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Hva er et godt utgangspunkt for en ny CSP?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Start med Helmets standard, aktiver <code>reportOnly: true<\/code>, og deploy til et testmilj\u00f8 med reell trafikk. La brudd-rapportene samle seg i en til to uker. Analyser dem, legg til legitime domener og ressurser i CSP-direktivene dine, og test igjen. Gjenta til ingen nye legitime brudd dukker opp, og skru deretter av report-only modus for \u00e5 aktivere faktisk blokkering.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Finnes det et verkt\u00f8y for \u00e5 automatisk generere CSP for eksisterende apper?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ja. <code>csp-header<\/code>-npm-pakken og nettleserutvidelsen &#8220;CSP Evaluator&#8221; fra Google kan hjelpe med \u00e5 identifisere n\u00f8dvendige direktiver. Den beste metoden er likevel \u00e5 aktivere <code>reportOnly: true<\/code> i Helmet og la brudd-rapportene fra ekte brukere fortelle deg n\u00f8yaktig hvilke ressurser applikasjonen laster. Dette gir den mest n\u00f8yaktige CSP for akkurat din applikasjon og dine brukeres nettlesere.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Helmet.js setter 11 sikkerhetshoder i Express p\u00e5 \u00e9n kodelinje. Uten dem sender applikasjonen din informasjon om server-teknologi, tillater iframe-inlasting fra tredjeparter og mangler beskyttelse mot MIME-sniffing-angrep. Pakken lastes ned over\u2026<\/p>\n","protected":false},"author":4,"featured_media":98,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-97","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-security"],"_links":{"self":[{"href":"https:\/\/shattered.io\/no\/wp-json\/wp\/v2\/posts\/97","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/shattered.io\/no\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/shattered.io\/no\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/shattered.io\/no\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/shattered.io\/no\/wp-json\/wp\/v2\/comments?post=97"}],"version-history":[{"count":1,"href":"https:\/\/shattered.io\/no\/wp-json\/wp\/v2\/posts\/97\/revisions"}],"predecessor-version":[{"id":99,"href":"https:\/\/shattered.io\/no\/wp-json\/wp\/v2\/posts\/97\/revisions\/99"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/shattered.io\/no\/wp-json\/wp\/v2\/media\/98"}],"wp:attachment":[{"href":"https:\/\/shattered.io\/no\/wp-json\/wp\/v2\/media?parent=97"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/shattered.io\/no\/wp-json\/wp\/v2\/categories?post=97"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/shattered.io\/no\/wp-json\/wp\/v2\/tags?post=97"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}