Blog
9 min read seguridad · frontend · web

Security headers every web developer should know

A practical explanation of the most important HTTP security headers: what problem they reduce, when to use them and why you should not copy them without understanding them.

Las cabeceras de seguridad son una de esas partes del desarrollo web que suelen aparecer tarde. Primero aprendes HTML, CSS, JavaScript, rutas, componentes, formularios, SEO, rendimiento. Luego un día pasas una herramienta de análisis o lees sobre seguridad web y descubres que tu servidor puede enviar instrucciones al navegador para reducir riesgos bastante importantes.

No son una solución mágica. Una cabecera no arregla una aplicación vulnerable, no valida formularios por ti y no sustituye revisar dependencias, permisos o lógica de servidor.

Pero sí forman parte de una web profesional.

Lo interesante es entender qué problema intenta reducir cada una. Copiar una configuración de internet sin saber qué hace puede romper imágenes, scripts, analítica, iframes o integraciones externas. En seguridad, una configuración que no entiendes es una deuda.

Qué es una cabecera HTTP

Cuando el navegador pide una página, el servidor no responde solo con HTML. También envía metadatos en forma de cabeceras HTTP.

Algunas indican el tipo de contenido. Otras controlan caché. Otras dan instrucciones de seguridad.

Por ejemplo, una respuesta puede decirle al navegador:

  • Esta página solo debe cargarse por HTTPS.
  • No permitas que otros sitios la metan dentro de un iframe.
  • No ejecutes scripts que no estén permitidos.
  • No compartas demasiada información en el Referer.
  • No permitas acceso a cámara, micrófono o geolocalización.

La cabecera no cambia el contenido de la página. Cambia las reglas con las que el navegador trata esa página.

Por qué debería importarle al frontend

Durante mucho tiempo pensé en la seguridad como algo más de backend o de sistemas. Base de datos, contraseñas, servidores, permisos.

Pero muchas cabeceras afectan directamente al frontend.

Si cargas scripts externos, usas Google Analytics, sirves imágenes, trabajas con fuentes locales, tienes formularios, publicas una PWA o quieres evitar que tu web se incruste en otra página, las cabeceras te afectan.

Además, un desarrollador frontend suele tomar decisiones que luego condicionan la seguridad:

  • Añadir scripts de terceros.
  • Usar iframes.
  • Cargar fuentes externas.
  • Permitir imágenes de otros dominios.
  • Insertar HTML dinámico.
  • Conectar con APIs.
  • Usar analítica o píxeles de seguimiento.

Por eso conviene conocer las cabeceras aunque no seas especialista en ciberseguridad. No para memorizar todas las directivas, sino para saber qué preguntas hacer antes de publicar.

Strict-Transport-Security

Strict-Transport-Security, normalmente abreviada como HSTS, le dice al navegador que ese sitio debe cargarse siempre por HTTPS durante un tiempo determinado.

Ejemplo:

Strict-Transport-Security: max-age=31536000; includeSubDomains

El objetivo es reducir el riesgo de que alguien intente forzar una conexión insegura por HTTP.

Si una persona visita tu web una vez por HTTPS y recibe esta cabecera, el navegador recordará que debe usar HTTPS en siguientes visitas. Incluso si el usuario escribe http://, el navegador intentará ir por HTTPS.

Es una cabecera muy útil, pero no conviene activarla a ciegas con subdominios si no controlas bien toda la infraestructura. includeSubDomains significa que también afecta a subdominios. Si tienes alguno mal preparado para HTTPS, puedes bloquear accesos.

Para una web profesional publicada en un dominio propio, HTTPS debería ser obligatorio. HSTS ayuda a reforzarlo.

Content-Security-Policy

Content-Security-Policy, o CSP, es una de las cabeceras más potentes y también una de las más delicadas.

Sirve para decirle al navegador qué fuentes están permitidas para scripts, estilos, imágenes, fuentes, conexiones, iframes y otros recursos.

Un ejemplo simplificado:

Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'

La idea es reducir el impacto de ataques como XSS. Si un atacante consigue inyectar un script, una CSP bien configurada puede impedir que ese script se ejecute o que cargue recursos desde un dominio no permitido.

Pero aquí hay que ir con cuidado. Una CSP demasiado estricta puede romper la web. Una demasiado permisiva apenas aporta.

Por ejemplo, si tu web usa Google Analytics, tendrás que permitir ciertos dominios en script-src y connect-src. Si sirves imágenes externas, tendrás que reflejarlo en img-src. Si usas estilos inline, tendrás que decidir si los permites, si usas hashes o si cambias la forma de cargar estilos.

Algunas directivas habituales:

  • default-src: regla por defecto cuando no hay una directiva más específica.
  • script-src: desde dónde se pueden cargar scripts.
  • style-src: desde dónde se pueden cargar estilos.
  • img-src: desde dónde se pueden cargar imágenes.
  • font-src: desde dónde se pueden cargar fuentes.
  • connect-src: a qué dominios puede conectarse la web con fetch, XHR, WebSocket o analítica.
  • object-src: controla recursos tipo <object> o <embed>. En muchas webs modernas puede ser 'none'.
  • base-uri: limita el uso de la etiqueta <base>.
  • frame-ancestors: controla quién puede incrustar tu página en un iframe.

Una buena forma de trabajar CSP es empezar en modo informe con Content-Security-Policy-Report-Only, revisar qué rompería y después aplicar la política real.

En una web pequeña y estática puedes llegar a una CSP bastante estricta. En una aplicación con muchas integraciones externas, necesitarás más paciencia.

X-Content-Type-Options

X-Content-Type-Options es una cabecera sencilla:

X-Content-Type-Options: nosniff

Le dice al navegador que no intente adivinar el tipo de archivo si el servidor ya ha enviado un Content-Type.

Esto importa porque algunos navegadores históricamente intentaban interpretar recursos de forma flexible. Si un archivo se servía con un tipo incorrecto, podían tratarlo como JavaScript o CSS aunque no correspondiera.

Con nosniff, reduces ese comportamiento.

No es una cabecera complicada y suele tener sentido activarla en prácticamente cualquier web. La condición es servir bien los tipos de contenido. Si envías un CSS como text/plain, el navegador puede bloquearlo, y con razón.

Referrer-Policy

Cuando alguien hace clic desde tu web hacia otra página, el navegador puede enviar información sobre la URL de origen mediante el encabezado Referer.

Sí, se escribe Referer, con esa errata histórica.

Referrer-Policy permite controlar cuánta información compartes.

Una opción bastante razonable para muchas webs es:

Referrer-Policy: strict-origin-when-cross-origin

Con esta política, al navegar dentro del mismo sitio se puede enviar la URL completa. Al salir hacia otro origen, se envía solo el origen, no la ruta completa. Y si el destino es menos seguro, por ejemplo de HTTPS a HTTP, no se envía.

Esto ayuda a no filtrar URLs internas con parámetros o rutas sensibles a otros dominios.

No todas las webs necesitan la misma política. Si tu analítica o tus integraciones dependen de datos concretos del referer, tendrás que revisarlo. Pero enviar siempre la URL completa a cualquier destino suele ser más exposición de la necesaria.

Permissions-Policy

Permissions-Policy permite limitar qué capacidades del navegador puede usar tu página o sus iframes.

Por ejemplo:

Permissions-Policy: camera=(), microphone=(), geolocation=()

Esto indica que la página no puede usar cámara, micrófono ni geolocalización.

Para una web de contenido, portfolio o blog, normalmente no necesitas acceso a cámara, micrófono, geolocalización, pagos, pantalla completa o captura de pantalla. Bloquear lo que no usas reduce superficie y deja más clara la intención de la web.

No es que una página pueda activar la cámara sin permiso del usuario. El navegador ya pide permiso. Pero si tu web no necesita esa capacidad, no hay razón para dejarla disponible.

Es una cabecera especialmente útil para aplicar el principio de mínimo privilegio: permitir solo lo necesario.

X-Frame-Options y frame-ancestors

El clickjacking consiste en engañar al usuario para que interactúe con una página legítima incrustada dentro de otra página.

Una defensa clásica era:

X-Frame-Options: DENY

O:

X-Frame-Options: SAMEORIGIN

Hoy, si usas CSP, la directiva más flexible y moderna es frame-ancestors.

Por ejemplo:

Content-Security-Policy: frame-ancestors 'none'

Eso indica que nadie puede incrustar tu página en un iframe.

Para un portfolio, blog o web corporativa simple, normalmente tiene sentido bloquear que otros sitios te incrusten. Si tu proyecto necesita estar embebido en otros dominios, entonces tendrás que permitir esos orígenes concretos.

Aquí la pregunta práctica es sencilla: ¿hay algún motivo real para que otra web cargue esta página dentro de un iframe?

Si la respuesta es no, bloquéalo.

Cross-Origin-Opener-Policy

Cross-Origin-Opener-Policy, o COOP, controla cómo se relaciona tu página con otras ventanas o pestañas de distinto origen.

Una configuración común es:

Cross-Origin-Opener-Policy: same-origin

Esto ayuda a aislar tu documento de otros orígenes. Puede ser útil para reducir ciertos riesgos relacionados con ventanas abiertas, acceso entre contextos y aislamiento del navegador.

Pero también puede romper flujos que dependen de popups externos, como algunos inicios de sesión o integraciones de pago. Por eso a veces se usa una opción más compatible:

Cross-Origin-Opener-Policy: same-origin-allow-popups

Esta cabecera no suele ser la primera que configuraría alguien que empieza. Primero entendería CSP, HSTS, nosniff, Referrer-Policy y Permissions-Policy. Pero merece conocerla porque aparece cada vez más en auditorías y configuraciones modernas.

Cross-Origin-Resource-Policy

Cross-Origin-Resource-Policy, o CORP, permite indicar quién puede cargar un recurso desde otro origen.

Por ejemplo:

Cross-Origin-Resource-Policy: same-site

O:

Cross-Origin-Resource-Policy: cross-origin

No se usa igual para todos los recursos. En assets internos puede tener sentido restringir más. En imágenes públicas, favicon u otros recursos que quieres permitir desde fuera, quizá necesitas una política más abierta.

En mi web, por ejemplo, tiene sentido pensar distinto para assets generados, imágenes públicas y páginas HTML. No todo necesita la misma regla.

Esta es una idea importante: las cabeceras no tienen por qué ser idénticas para toda la web. Un sitemap, un archivo de texto, una imagen y una página HTML no tienen el mismo comportamiento.

Cache-Control también afecta a seguridad

Cache-Control no suele meterse en la lista de cabeceras de seguridad, pero puede tener implicaciones.

En una web estática, cachear assets con hash durante mucho tiempo es razonable:

Cache-Control: public, max-age=31536000, immutable

Si el archivo cambia de nombre cuando cambia su contenido, el navegador puede guardarlo mucho tiempo sin problema.

Pero no aplicarías la misma lógica a una página con información sensible, una respuesta personalizada o un documento que no quieres que quede guardado en cachés intermedias.

En una web como un portfolio, el riesgo es menor porque el contenido es público. Aun así, conviene entender que caché no es solo rendimiento. También define dónde y durante cuánto tiempo puede quedarse una respuesta.

Cabeceras que no conviene copiar por inercia

Hay cabeceras antiguas o configuraciones que todavía aparecen en artículos, pero no siempre tienen sentido hoy.

Un ejemplo típico es:

X-XSS-Protection: 1; mode=block

Durante años se usó para activar filtros XSS del navegador. Hoy está obsoleta en navegadores modernos y puede incluso crear comportamientos no deseados. Es mejor invertir el esfuerzo en una CSP bien planteada y en evitar la inyección desde la base.

También conviene tener cuidado con copiar políticas CSP enormes sin entenderlas. Si ves una configuración llena de dominios, hashes y excepciones, probablemente responde a una web concreta. No significa que sea buena para la tuya.

La regla práctica es simple: si no sabes qué recurso permite una directiva, no la pegues todavía.

Cómo lo aplicaría en una web pequeña

Para una web profesional sencilla, como un portfolio, blog o landing sin zona privada, empezaría por estas:

Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Content-Security-Policy: default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'

No lo copiaría tal cual sin probar.

La CSP casi siempre necesitará ajustes. Si usas analítica, fuentes externas, imágenes remotas o scripts de terceros, tendrás que permitirlos de forma explícita.

El orden razonable sería:

  1. Activar HTTPS correctamente.
  2. Añadir HSTS cuando el dominio esté preparado.
  3. Añadir nosniff y Referrer-Policy.
  4. Definir una Permissions-Policy restrictiva.
  5. Diseñar una CSP mínima.
  6. Probar en local, staging o modo report-only.
  7. Revisar la consola del navegador y las respuestas reales.
  8. Ajustar solo lo necesario.

No hace falta convertirlo en una obsesión. Hace falta tratarlo como parte normal de publicar una web.

Cómo comprobar tus cabeceras

Hay varias formas sencillas:

  • Abrir DevTools, ir a Network, seleccionar una petición y revisar Response Headers.
  • Usar curl -I https://tu-dominio.com.
  • Pasar herramientas como Security Headers.
  • Revisar la configuración del hosting.
  • Comprobar que no solo funciona la home, sino también páginas internas, imágenes y archivos técnicos.

La parte importante es mirar la respuesta real en producción. No basta con que el archivo de configuración parezca correcto.

También hay que revisar después de añadir scripts externos. Muchas veces una CSP funciona hasta que añades analítica, un widget, un formulario embebido o un recurso de terceros.

Qué me llevo como desarrollador

Las cabeceras de seguridad me parecen un buen ejemplo de algo que un desarrollador web debería entender aunque no sea especialista en seguridad.

No necesitas memorizar todas las directivas. Necesitas saber qué riesgos existen y qué controles básicos puedes aplicar.

Para mí, la idea principal es esta:

Una web profesional no solo debe verse bien y cargar rápido. También debe decirle al navegador qué está permitido y qué no.

Eso reduce margen de error, obliga a pensar en los recursos que cargas y hace que la web sea más explícita.

Si estás empezando, no intentes configurar todas las cabeceras posibles el mismo día. Empieza por entender HSTS, CSP, nosniff, Referrer-Policy y Permissions-Policy. Con eso ya tienes una base mucho más seria que simplemente publicar la web y esperar que todo vaya bien.

La seguridad no aparece de golpe al final del proyecto. Se construye con pequeñas decisiones correctas desde el principio.

Security headers are one of those parts of web development that usually appear late. First you learn HTML, CSS, JavaScript, routes, components, forms, SEO, performance. Then one day you run an audit tool or read about web security and realise your server can send instructions to the browser to reduce some important risks.

They are not a magic fix. A header will not repair a vulnerable application, validate forms for you or replace dependency checks, permissions or server-side logic.

But they are part of a professional website.

The useful part is understanding what problem each header tries to reduce. Copying a configuration from the internet without knowing what it does can break images, scripts, analytics, iframes or external integrations. In security, a configuration you do not understand is debt.

What an HTTP header is

When the browser requests a page, the server does not respond only with HTML. It also sends metadata as HTTP headers.

Some headers describe the content type. Others control caching. Others give security instructions.

For example, a response can tell the browser:

  • This page should only be loaded over HTTPS.
  • Do not allow other sites to embed it inside an iframe.
  • Do not execute scripts that are not allowed.
  • Do not share too much information in the Referer.
  • Do not allow access to camera, microphone or geolocation.

The header does not change the page content. It changes the rules the browser applies to that page.

Why frontend developers should care

For a long time, I thought of security as something closer to backend or systems work. Databases, passwords, servers, permissions.

But many security headers directly affect the frontend.

If you load third-party scripts, use Google Analytics, serve images, work with local fonts, have forms, publish a PWA or want to stop your website being embedded somewhere else, headers affect you.

Frontend developers also make decisions that shape security later:

  • Adding third-party scripts.
  • Using iframes.
  • Loading external fonts.
  • Allowing images from other domains.
  • Injecting dynamic HTML.
  • Connecting to APIs.
  • Using analytics or tracking pixels.

That is why it is worth knowing these headers even if you are not a cybersecurity specialist. Not to memorise every directive, but to know which questions to ask before publishing.

Strict-Transport-Security

Strict-Transport-Security, usually shortened to HSTS, tells the browser that a site must always be loaded over HTTPS for a specific amount of time.

Example:

Strict-Transport-Security: max-age=31536000; includeSubDomains

The goal is to reduce the risk of someone forcing an insecure HTTP connection.

If a person visits your site once over HTTPS and receives this header, the browser remembers that it should use HTTPS on future visits. Even if the user types http://, the browser will try HTTPS.

It is a useful header, but you should not blindly enable it for subdomains if you do not control the whole infrastructure. includeSubDomains means it also affects subdomains. If one of them is not ready for HTTPS, you can break access.

For a professional website on its own domain, HTTPS should be mandatory. HSTS helps reinforce that.

Content-Security-Policy

Content-Security-Policy, or CSP, is one of the most powerful headers and also one of the easiest to get wrong.

It tells the browser which sources are allowed for scripts, styles, images, fonts, connections, iframes and other resources.

A simplified example:

Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'

The idea is to reduce the impact of attacks such as XSS. If an attacker manages to inject a script, a good CSP can stop that script from running or loading resources from an untrusted domain.

But this is where you need to be careful. A CSP that is too strict can break the site. A CSP that is too loose barely helps.

For example, if your site uses Google Analytics, you will need to allow certain domains in script-src and connect-src. If you serve external images, that needs to be reflected in img-src. If you use inline styles, you need to decide whether to allow them, use hashes or change the way styles are loaded.

Common directives include:

  • default-src: fallback rule when there is no more specific directive.
  • script-src: where scripts can be loaded from.
  • style-src: where styles can be loaded from.
  • img-src: where images can be loaded from.
  • font-src: where fonts can be loaded from.
  • connect-src: which domains the site can connect to through fetch, XHR, WebSocket or analytics.
  • object-src: controls resources such as <object> or <embed>. In many modern sites it can be 'none'.
  • base-uri: limits use of the <base> element.
  • frame-ancestors: controls who can embed your page in an iframe.

A good way to work with CSP is to start with Content-Security-Policy-Report-Only, review what would break and then apply the real policy.

On a small static site, you can usually get to a fairly strict CSP. On an app with many external integrations, you will need more patience.

X-Content-Type-Options

X-Content-Type-Options is a simple header:

X-Content-Type-Options: nosniff

It tells the browser not to guess the file type if the server has already sent a Content-Type.

This matters because some browsers historically tried to interpret resources flexibly. If a file was served with the wrong type, they could treat it as JavaScript or CSS even when it was not.

With nosniff, you reduce that behaviour.

It is not a complicated header and it usually makes sense on almost any website. The condition is serving correct content types. If you send CSS as text/plain, the browser may block it, and it would be right to do so.

Referrer-Policy

When someone clicks from your website to another page, the browser may send information about the source URL through the Referer header.

Yes, it is written Referer, with the historical typo.

Referrer-Policy lets you control how much information you share.

A reasonable option for many sites is:

Referrer-Policy: strict-origin-when-cross-origin

With this policy, full URLs can be sent when navigating within the same site. When leaving to another origin, only the origin is sent, not the full path. And if the destination is less secure, for example from HTTPS to HTTP, nothing is sent.

This helps avoid leaking internal URLs with parameters or sensitive paths to other domains.

Not every site needs the same policy. If your analytics or integrations depend on specific referrer data, you need to check that. But sending the full URL to every destination is usually more exposure than necessary.

Permissions-Policy

Permissions-Policy limits which browser capabilities your page or its iframes can use.

For example:

Permissions-Policy: camera=(), microphone=(), geolocation=()

This says the page cannot use camera, microphone or geolocation.

For a content site, portfolio or blog, you usually do not need access to camera, microphone, geolocation, payments, fullscreen or screen capture. Blocking what you do not use reduces surface area and makes the intent of the site clearer.

It is not that a page can turn on the camera without user permission. The browser already asks for permission. But if your site does not need that capability, there is no reason to leave it available.

This header is especially useful for applying the principle of least privilege: allow only what is needed.

X-Frame-Options and frame-ancestors

Clickjacking means tricking a user into interacting with a legitimate page embedded inside another page.

A classic defence was:

X-Frame-Options: DENY

Or:

X-Frame-Options: SAMEORIGIN

Today, if you use CSP, the more flexible and modern option is frame-ancestors.

For example:

Content-Security-Policy: frame-ancestors 'none'

That means nobody can embed your page in an iframe.

For a portfolio, blog or simple business website, it usually makes sense to block other sites from embedding you. If your project needs to be embedded on other domains, then you should allow those specific origins.

The practical question is simple: is there a real reason for another website to load this page inside an iframe?

If the answer is no, block it.

Cross-Origin-Opener-Policy

Cross-Origin-Opener-Policy, or COOP, controls how your page relates to other windows or tabs from a different origin.

A common configuration is:

Cross-Origin-Opener-Policy: same-origin

This helps isolate your document from other origins. It can reduce certain risks related to opened windows, cross-context access and browser isolation.

But it can also break flows that depend on external popups, such as some login or payment integrations. That is why a more compatible option is sometimes used:

Cross-Origin-Opener-Policy: same-origin-allow-popups

This is not usually the first header I would configure when starting out. I would understand CSP, HSTS, nosniff, Referrer-Policy and Permissions-Policy first. But it is worth knowing because it appears more often in modern audits and configurations.

Cross-Origin-Resource-Policy

Cross-Origin-Resource-Policy, or CORP, lets you indicate who can load a resource from another origin.

For example:

Cross-Origin-Resource-Policy: same-site

Or:

Cross-Origin-Resource-Policy: cross-origin

It is not used the same way for every resource. For internal assets, it may make sense to restrict more. For public images, favicons or resources you want to allow externally, you may need a more open policy.

On my site, for example, it makes sense to think differently about generated assets, public images and HTML pages. Not everything needs the same rule.

This is an important idea: headers do not have to be identical across the whole site. A sitemap, a text file, an image and an HTML page do not behave the same way.

Cache-Control also affects security

Cache-Control is not usually listed as a security header, but it can have security implications.

On a static website, caching hashed assets for a long time is reasonable:

Cache-Control: public, max-age=31536000, immutable

If the filename changes when the content changes, the browser can safely keep it for a long time.

But you would not apply the same logic to a page with sensitive information, a personalised response or a document you do not want stored in shared caches.

On a site like a portfolio, the risk is lower because the content is public. Still, it is worth understanding that caching is not only performance. It also defines where and for how long a response can be stored.

Headers you should not copy by habit

Some old headers or configurations still appear in articles, but they do not always make sense today.

A typical example is:

X-XSS-Protection: 1; mode=block

For years, it was used to enable browser XSS filters. Today it is obsolete in modern browsers and can even create unwanted behaviour. It is better to invest effort in a well-designed CSP and in preventing injection at the source.

You should also be careful with copying huge CSP policies without understanding them. If you see a configuration full of domains, hashes and exceptions, it probably belongs to a specific website. That does not mean it is good for yours.

The practical rule is simple: if you do not know what resource a directive allows, do not paste it yet.

How I would apply this on a small website

For a simple professional website, such as a portfolio, blog or landing page without a private area, I would start with these:

Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Content-Security-Policy: default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'

I would not copy this exactly without testing.

CSP will almost always need adjustments. If you use analytics, external fonts, remote images or third-party scripts, you will need to allow them explicitly.

A reasonable order would be:

  1. Enable HTTPS correctly.
  2. Add HSTS once the domain is ready.
  3. Add nosniff and Referrer-Policy.
  4. Define a restrictive Permissions-Policy.
  5. Design a minimal CSP.
  6. Test locally, in staging or in report-only mode.
  7. Check the browser console and real responses.
  8. Adjust only what is necessary.

This does not need to become an obsession. It needs to become a normal part of publishing a website.

How to check your headers

There are several simple ways:

  • Open DevTools, go to Network, select a request and inspect Response Headers.
  • Use curl -I https://your-domain.com.
  • Run tools such as Security Headers.
  • Review your hosting configuration.
  • Check not only the home page, but also internal pages, images and technical files.

The important part is checking the real production response. It is not enough for the configuration file to look correct.

You also need to review after adding external scripts. A CSP often works until you add analytics, a widget, an embedded form or a third-party resource.

What I take from this as a developer

Security headers are a good example of something a web developer should understand even without being a security specialist.

You do not need to memorise every directive. You need to understand the risks and the basic controls you can apply.

For me, the main idea is this:

A professional website should not only look good and load fast. It should also tell the browser what is allowed and what is not.

That reduces room for error, forces you to think about the resources you load and makes the website more explicit.

If you are starting out, do not try to configure every possible header on the same day. Start by understanding HSTS, CSP, nosniff, Referrer-Policy and Permissions-Policy. That already gives you a much more serious foundation than just publishing the site and hoping everything is fine.

Security does not appear suddenly at the end of a project. It is built through small correct decisions from the beginning.