{"id":13477,"date":"2026-10-08T07:35:00","date_gmt":"2026-10-08T05:35:00","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/?p=13477"},"modified":"2026-09-25T09:45:53","modified_gmt":"2026-09-25T07:45:53","slug":"http-security-headers-explained-which-ones-protect-and-which-are-merely","status":"publish","type":"post","link":"https:\/\/www.lukaswojcik.com\/blog\/en\/it-networks\/tutorials-en-it-networks\/http-security-headers-explained-which-ones-protect-and-which-are-merely\/","title":{"rendered":"HTTP Security Headers Explained: Which Ones Protect and Which Are Merely Present"},"content":{"rendered":"<p>Every page a server sends comes with a set of headers &#8211; lines that travel ahead of the content and tell the browser how to treat what follows. A handful of them are about safety.<\/p>\n<p>They are easy to check and easy to check wrongly. Counting which headers are present takes a second and produces a number that looks like a result. The number says almost nothing, because a header can be present, correctly spelled, and completely without effect.<\/p>\n<figure class=\"lw-diagram\">\n<img decoding=\"async\" src=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/diagrams\/security-header-en.png\" width=\"1120\" height=\"580\" loading=\"lazy\" alt=\"Four security headers from one response, each with its value and what it actually achieves: two work, two cancel themselves out\"><figcaption>All four are present. Two of them protect nothing.<\/figcaption><\/figure>\n<h2>What the security headers are<\/h2>\n<p>Four of them carry most of the weight, and each answers a different question.<\/p>\n<p><strong>Content-Security-Policy<\/strong> lists where the page is allowed to load code from. Anything not on the list is refused by the browser, which is the main defence against injected scripts.<\/p>\n<p><strong>Strict-Transport-Security<\/strong> tells the browser to use the encrypted connection from now on and never the plain one &#8211; including when a link, a bookmark or a typed address says otherwise.<\/p>\n<p><strong>X-Frame-Options<\/strong> decides whether the page may be embedded in a frame on someone else&#8217;s site, which is what stops a visitor from clicking on something invisible.<\/p>\n<p><strong>Referrer-Policy<\/strong> decides how much of the current address is passed on when a visitor follows a link away from the page.<\/p>\n<p>A fifth, <strong>Permissions-Policy<\/strong>, switches off browser features the page does not need &#8211; camera, microphone, location. It is the least common of the five and the least likely to break anything.<\/p>\n<h2>The rule that unsafe-inline cancels<\/h2>\n<p>Content-Security-Policy is the strongest of the five and the one most often defeated by its own value.<\/p>\n<p>The threat it exists for is an injected script: something a visitor typed, or an attacker planted, ends up in the page and runs as if it belonged there. CSP prevents this by naming the sources the browser may execute code from, and a script written directly into the page has no source to name.<\/p>\n<p>Which is precisely what <code>'unsafe-inline'<\/code> permits again. The word is in the value for a reason &#8211; it says what it does &#8211; and it is there because a page full of small inline scripts stops working without it. Adding it is the fastest way to make a broken page work again, and it gives back the exact permission the policy was written to withhold.<\/p>\n<p>A policy containing <code>'unsafe-inline'<\/code> still blocks a few things: code loaded from foreign addresses, for instance. Against the attack CSP is mainly for, it does close to nothing.<\/p>\n<p><code>'unsafe-eval'<\/code> is the same story for a narrower case, and a <code>default-src<\/code> of <code>*<\/code> is the same story without any pretence.<\/p>\n<h2>How long an HSTS lifetime has to be<\/h2>\n<p>Strict-Transport-Security has one number that decides everything: <code>max-age<\/code>, in seconds.<\/p>\n<p>It says how long the browser should remember the instruction. Until it expires, a plain unencrypted request to that domain is never sent &#8211; the browser rewrites it before it leaves the machine. That is the whole protection, and it only holds for as long as the memory lasts.<\/p>\n<p>A <code>max-age<\/code> of 300 remembers for five minutes. Formally correct, present in every check that counts names, and useless for a visitor returning the next day. The usual recommendation is a year, written as <code>31536000<\/code>.<\/p>\n<p>Two additions matter. <code>includeSubDomains<\/code> extends the rule to every subdomain, which closes the gap where a forgotten test system on the same domain gets reached unencrypted. And <code>preload<\/code> asks for the domain to be built into browsers directly, so the protection covers the very first visit too &#8211; the one moment where HSTS otherwise cannot help, because nothing has been remembered yet.<\/p>\n<p>That last step deserves a warning: entries are hard to remove and removal takes months to reach browsers. It suits a domain whose encryption is settled, not one still being sorted out.<\/p>\n<figure class=\"lw-illu\">\n<img decoding=\"async\" src=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/illustrationen\/illu-security-header.webp\" width=\"1120\" height=\"580\" loading=\"lazy\" alt=\"Four upright panels of equal size: two solid, two only outlines\"><br \/>\n<\/figure>\n<h2>When two headers govern the same thing<\/h2>\n<p>Framing is regulated twice, by two headers of different ages, and the rule for which one wins surprises people.<\/p>\n<p>X-Frame-Options is the older one, understood everywhere, and offers <code>DENY<\/code> or <code>SAMEORIGIN<\/code>. CSP has <code>frame-ancestors<\/code>, which does the same job with a list of addresses instead of two fixed choices.<\/p>\n<p>When both are present, <code>frame-ancestors<\/code> wins and X-Frame-Options is ignored entirely. Not merged, not combined &#8211; ignored. A page with <code>X-Frame-Options: DENY<\/code> and a CSP containing <code>frame-ancestors *<\/code> can be framed by anyone, and the stricter of the two headers has no say.<\/p>\n<p>This is the failure that hides best, because both headers are present, both are spelled correctly, and a check that counts names reports two protections where there is one.<\/p>\n<h2>What travels along with every click<\/h2>\n<p>Referrer-Policy is the quietest of the five and the one with the most everyday consequences.<\/p>\n<p>When a visitor follows a link away from a page, the browser tells the destination where the visitor came from. How much it tells is what this header sets. <code>unsafe-url<\/code> passes the full address including the path; <code>no-referrer<\/code> passes nothing; <code>strict-origin-when-cross-origin<\/code> passes the full address within the same site and only the domain to foreign ones.<\/p>\n<p>The path is where the sensitivity sits. <code>\/en\/account\/orders\/48120<\/code> reveals a customer number, a password reset link reveals a token, and a search page reveals what was searched for. All of that goes to whichever site is linked to, in an ordinary header, without anything going wrong.<\/p>\n<p>The last of the three values is the sensible default, and modern browsers apply it on their own when the header is missing. Which makes an explicitly set <code>unsafe-url<\/code> worse than no header at all: it replaces a good default with a bad decision.<\/p>\n<h2>What a single fetch shows<\/h2>\n<p>All of this is public. The headers arrive with every response, for any address, and reading them takes one request.<\/p>\n<p>Four questions are worth asking. Does a CSP exist, and does its value give back what it took away. Is the HSTS lifetime long enough to survive between two visits. Do the two framing headers agree, and does the one that wins say what was intended. And does the referrer setting pass on more than the destination needs.<\/p>\n<p>The <a href=\"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/http-security-header-checker\/\">HTTP security header checker<\/a> answers all four for any address. It fetches the page once, reads the headers as a browser reads them, follows the redirects on the way, and judges the values rather than counting the names.<\/p>\n<p>The useful result is not a grade. It is the short list of headers that are present and doing nothing &#8211; because those are the ones that will not be looked at again.<\/p>\n<div class=\"lw-faq\">\n<h2>Questions and answers<\/h2>\n<h3>How can &#8216;unsafe-inline&#8217; be dropped without moving every inline script out of the page?<\/h3>\n<p>With nonces or hashes. A nonce is a random value that appears in the CSP as &#8216;nonce-\u2026&#8217; and as an attribute on every permitted script; the browser then only runs inline scripts that carry this value. A hash (&#8216;sha256-\u2026&#8217;) permits a script with exactly that content. An injected script neither knows the value nor matches the hash, and that is precisely what restores the protection &#8216;unsafe-inline&#8217; took away.<\/p>\n<p>As soon as a nonce or a hash appears in the policy, current browsers ignore an &#8216;unsafe-inline&#8217; next to it. It can therefore stay as a fallback for very old browsers without weakening the protection in the others.<\/p>\n<p>Two constraints follow. A nonce has to be generated afresh for every response; a page cache that serves the same HTML with the same nonce to everyone makes it known and therefore worthless, which is why hashes work better with caches. And event attributes such as onclick are not covered by nonces at all, and by hashes only with the additional keyword &#8216;unsafe-hashes&#8217;; moving them into scripts is the cleaner route. Until everything is in place, the Content-Security-Policy-Report-Only header shows what a policy would block without blocking it.<\/p>\n<h3>Does an HSTS header sent over an unencrypted connection have any effect?<\/h3>\n<p>No. Browsers only honour Strict-Transport-Security in responses over HTTPS and ignore the header in an unencrypted response, because anyone along the way could have inserted or removed it there. The response on http:\/\/ should therefore only redirect to HTTPS, and the header belongs in the response that redirect leads to.<\/p>\n<h3>What happens when both the web server and the application send a CSP?<\/h3>\n<p>Both apply. The browser does not merge them into one common policy but checks each on its own, and a resource is only loaded if every policy permits it. A second, looser CSP therefore cannot weaken a strict one; a forgotten strict policy, in the web server configuration for instance, on the other hand blocks things the application expressly permits in its own policy.<\/p>\n<p>Strict-Transport-Security behaves differently: if the header arrives twice, the browser processes only the first one, as RFC 6797 requires. When headers are set in several places, such as the web server, a plugin and a CDN, the response actually delivered is what needs checking, not the individual configurations.<\/p>\n<h3>Can frame-ancestors also be set in a meta element?<\/h3>\n<p>No. A CSP in a meta element does not support frame-ancestors, nor report-uri or sandbox, and X-Frame-Options likewise only works as a real header. Protection against embedding therefore always needs a setting on the server or in the CDN.<\/p>\n<\/div>\n<div class=\"lw-quellen\">\n<h2>Sources<\/h2>\n<ul>\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Guides\/CSP\" target=\"_blank\" rel=\"noopener noreferrer\">MDN: Content Security Policy<\/a><\/li>\n<li><a href=\"https:\/\/www.rfc-editor.org\/rfc\/rfc9110.html\" target=\"_blank\" rel=\"noopener noreferrer\">RFC 9110: HTTP Semantics<\/a><\/li>\n<li><a href=\"https:\/\/www.rfc-editor.org\/rfc\/rfc6797.html\" target=\"_blank\" rel=\"noopener noreferrer\">RFC 6797: HTTP Strict Transport Security<\/a><\/li>\n<\/ul>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Security headers are checked by their names far too often. The name says a rule exists; only the value says whether it does anything &#8211; and some values cancel the very rule they belong to.<\/p>\n","protected":false},"author":1,"featured_media":16112,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[137],"tags":[91099,91219,91115],"class_list":["post-13477","post","type-post","status-publish","format-standard","hentry","category-tutorials-en-it-networks","tag-server-administration","tag-tutorial","tag-web-security"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>HTTP Security Headers Explained: Which Ones Protect and Which Are Merely Present | Lukas Wojcik<\/title>\n<meta name=\"description\" content=\"What the HTTP security headers do, why a Content-Security-Policy with unsafe-inline protects almost nothing, and how to read the values instead of counting the names.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/en\/it-networks\/tutorials-en-it-networks\/http-security-headers-explained-which-ones-protect-and-which-are-merely\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"HTTP Security Headers Explained: Which Ones Protect and Which Are Merely Present | Lukas Wojcik\" \/>\n<meta property=\"og:description\" content=\"What the HTTP security headers do, why a Content-Security-Policy with unsafe-inline protects almost nothing, and how to read the values instead of counting the names.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/en\/it-networks\/tutorials-en-it-networks\/http-security-headers-explained-which-ones-protect-and-which-are-merely\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-08T05:35:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-13477-http-security-headers-explained-nz.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Lukas Wojcik\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Lukas Wojcik\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/it-networks\\\/tutorials-en-it-networks\\\/http-security-headers-explained-which-ones-protect-and-which-are-merely\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/it-networks\\\/tutorials-en-it-networks\\\/http-security-headers-explained-which-ones-protect-and-which-are-merely\\\/\"},\"author\":{\"name\":\"Lukas Wojcik\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"headline\":\"HTTP Security Headers Explained: Which Ones Protect and Which Are Merely Present\",\"datePublished\":\"2026-10-08T05:35:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/it-networks\\\/tutorials-en-it-networks\\\/http-security-headers-explained-which-ones-protect-and-which-are-merely\\\/\"},\"wordCount\":1529,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/it-networks\\\/tutorials-en-it-networks\\\/http-security-headers-explained-which-ones-protect-and-which-are-merely\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/hero-13477-http-security-headers-explained-nz.png\",\"keywords\":[\"Server Administration\",\"Tutorial\",\"Web Security\"],\"articleSection\":[\"Tutorials\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/it-networks\\\/tutorials-en-it-networks\\\/http-security-headers-explained-which-ones-protect-and-which-are-merely\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/it-networks\\\/tutorials-en-it-networks\\\/http-security-headers-explained-which-ones-protect-and-which-are-merely\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/it-networks\\\/tutorials-en-it-networks\\\/http-security-headers-explained-which-ones-protect-and-which-are-merely\\\/\",\"name\":\"HTTP Security Headers Explained: Which Ones Protect and Which Are Merely Present | Lukas Wojcik\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/it-networks\\\/tutorials-en-it-networks\\\/http-security-headers-explained-which-ones-protect-and-which-are-merely\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/it-networks\\\/tutorials-en-it-networks\\\/http-security-headers-explained-which-ones-protect-and-which-are-merely\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/hero-13477-http-security-headers-explained-nz.png\",\"datePublished\":\"2026-10-08T05:35:00+00:00\",\"description\":\"What the HTTP security headers do, why a Content-Security-Policy with unsafe-inline protects almost nothing, and how to read the values instead of counting the names.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/it-networks\\\/tutorials-en-it-networks\\\/http-security-headers-explained-which-ones-protect-and-which-are-merely\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/it-networks\\\/tutorials-en-it-networks\\\/http-security-headers-explained-which-ones-protect-and-which-are-merely\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/it-networks\\\/tutorials-en-it-networks\\\/http-security-headers-explained-which-ones-protect-and-which-are-merely\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/hero-13477-http-security-headers-explained-nz.png\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/hero-13477-http-security-headers-explained-nz.png\",\"width\":1200,\"height\":630,\"caption\":\"HTTP Security Headers Explained: Which Ones Protect and Which Are Merely Present\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/it-networks\\\/tutorials-en-it-networks\\\/http-security-headers-explained-which-ones-protect-and-which-are-merely\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"HTTP Security Headers Explained: Which Ones Protect and Which Are Merely Present\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"Lukas Wojcik\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"Lukas Wojcik\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"HTTP Security Headers Explained: Which Ones Protect and Which Are Merely Present | Lukas Wojcik","description":"What the HTTP security headers do, why a Content-Security-Policy with unsafe-inline protects almost nothing, and how to read the values instead of counting the names.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/en\/it-networks\/tutorials-en-it-networks\/http-security-headers-explained-which-ones-protect-and-which-are-merely\/","og_locale":"en_US","og_type":"article","og_title":"HTTP Security Headers Explained: Which Ones Protect and Which Are Merely Present | Lukas Wojcik","og_description":"What the HTTP security headers do, why a Content-Security-Policy with unsafe-inline protects almost nothing, and how to read the values instead of counting the names.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/en\/it-networks\/tutorials-en-it-networks\/http-security-headers-explained-which-ones-protect-and-which-are-merely\/","og_site_name":"Lukas Wojcik - Blog","article_published_time":"2026-10-08T05:35:00+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-13477-http-security-headers-explained-nz.png","type":"image\/png"}],"author":"Lukas Wojcik","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Lukas Wojcik","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/it-networks\/tutorials-en-it-networks\/http-security-headers-explained-which-ones-protect-and-which-are-merely\/#article","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/it-networks\/tutorials-en-it-networks\/http-security-headers-explained-which-ones-protect-and-which-are-merely\/"},"author":{"name":"Lukas Wojcik","@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"headline":"HTTP Security Headers Explained: Which Ones Protect and Which Are Merely Present","datePublished":"2026-10-08T05:35:00+00:00","mainEntityOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/it-networks\/tutorials-en-it-networks\/http-security-headers-explained-which-ones-protect-and-which-are-merely\/"},"wordCount":1529,"commentCount":0,"publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/it-networks\/tutorials-en-it-networks\/http-security-headers-explained-which-ones-protect-and-which-are-merely\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-13477-http-security-headers-explained-nz.png","keywords":["Server Administration","Tutorial","Web Security"],"articleSection":["Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/it-networks\/tutorials-en-it-networks\/http-security-headers-explained-which-ones-protect-and-which-are-merely\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/it-networks\/tutorials-en-it-networks\/http-security-headers-explained-which-ones-protect-and-which-are-merely\/","url":"https:\/\/www.lukaswojcik.com\/blog\/en\/it-networks\/tutorials-en-it-networks\/http-security-headers-explained-which-ones-protect-and-which-are-merely\/","name":"HTTP Security Headers Explained: Which Ones Protect and Which Are Merely Present | Lukas Wojcik","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/it-networks\/tutorials-en-it-networks\/http-security-headers-explained-which-ones-protect-and-which-are-merely\/#primaryimage"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/it-networks\/tutorials-en-it-networks\/http-security-headers-explained-which-ones-protect-and-which-are-merely\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-13477-http-security-headers-explained-nz.png","datePublished":"2026-10-08T05:35:00+00:00","description":"What the HTTP security headers do, why a Content-Security-Policy with unsafe-inline protects almost nothing, and how to read the values instead of counting the names.","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/it-networks\/tutorials-en-it-networks\/http-security-headers-explained-which-ones-protect-and-which-are-merely\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/it-networks\/tutorials-en-it-networks\/http-security-headers-explained-which-ones-protect-and-which-are-merely\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/it-networks\/tutorials-en-it-networks\/http-security-headers-explained-which-ones-protect-and-which-are-merely\/#primaryimage","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-13477-http-security-headers-explained-nz.png","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-13477-http-security-headers-explained-nz.png","width":1200,"height":630,"caption":"HTTP Security Headers Explained: Which Ones Protect and Which Are Merely Present"},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/it-networks\/tutorials-en-it-networks\/http-security-headers-explained-which-ones-protect-and-which-are-merely\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"HTTP Security Headers Explained: Which Ones Protect and Which Are Merely Present"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"Lukas Wojcik","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"Lukas Wojcik"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/13477","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=13477"}],"version-history":[{"count":3,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/13477\/revisions"}],"predecessor-version":[{"id":21698,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/13477\/revisions\/21698"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media\/16112"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=13477"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/categories?post=13477"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=13477"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}