Help

Browser security headers

Six lines your server sends with every response. What each one protects against and which value to start with.

A header is a short line your server sends ahead of every page. Visitors don’t see it. Security headers are house rules for the browser, such as: don’t run scripts from unknown sources. Without them, the browser allows a lot that an attacker can exploit. They cost nothing and work on every visit. How to add them is described in Setting headers by platform. Shopify doesn’t let you add your own headers, though it sets some itself.

For the grade, what counts is whether a header is present. We don’t currently rate its value. How many points each one brings is listed in How the grade is calculated.

Protection against injected scripts (Content-Security-Policy)

If someone gets foreign code into your page, for example through a comment field, that code can read what users type and act on their behalf. This attack is called cross-site scripting, or XSS. AI assistants often create such gaps: on cross-site scripting tasks, Veracode found insecure code in 86% of cases (Veracode, July 2025). This header is a list of the sources your page may load scripts, images and fonts from. The browser then refuses to run foreign code. The header is called CSP for short and, at 25, brings the most points, but only if it really restricts scripts.

Good starting value: object-src 'none'; base-uri 'self'; frame-ancestors 'self'; upgrade-insecure-requests

This value almost never breaks anything, but it doesn’t restrict scripts yet, so it earns only 10 points. As a next step, use script-src to list the sources you actually use, for example script-src 'self'. The full 25 points come when the policy allows neither 'unsafe-inline' without a nonce or hash nor wildcards such as * or https: for scripts. Google’s CSP Evaluator and the Mozilla Observatory rate it the same way. Test that first with the Content-Security-Policy-Report-Only header. The browser then only reports what it would block. We don’t count this test version as set yet. A CSP as a meta tag in the HTML counts if it sets script-src or default-src, but frame-ancestors has no effect there.

Common mistake: default-src 'self' without testing. Afterwards analytics, the chat widget or the payment form stop working. Just as common is 'unsafe-inline' for scripts, which largely removes the protection against injected code again.

Encrypted connections only (Strict-Transport-Security)

Without this header, someone on the same Wi-Fi can redirect your visitors to an unencrypted version of your site and read along. With it, the browser remembers to open your site only over an encrypted connection. The header is called HSTS for short and brings 20 points.

Good starting value: max-age=31536000

The number is one year in seconds. If you’re unsure, start with max-age=86400, which is one day, and raise it later.

Common mistake: includeSubDomains or preload while a subdomain doesn’t have HTTPS yet. Visitors then can’t open that subdomain until the period runs out.

No embedding by other sites (X-Frame-Options)

Without this header, another site can place yours invisibly on top of its own. Users then click buttons they can’t see, such as “Confirm” in your customer portal. This is called clickjacking. The header brings 15 points. If your CSP already contains frame-ancestors, that counts the same.

Good starting value: SAMEORIGIN

Common mistake: ALLOW-FROM. This value is obsolete and browsers ignore it. If a specific partner should be allowed to embed your site, add it to frame-ancestors in the CSP.

No guessing of file types (X-Content-Type-Options)

With this header, the browser trusts your server’s statement about what a file is instead of guessing. That way an uploaded image can’t suddenly run as a script. The header brings 10 points.

Good starting value: nosniff

Common mistake: the server delivers scripts with the wrong file type, for example as plain text. With the header, the browser then stops loading them. After setting it, quickly check that everything still works.

Fewer traces when clicking links (Referrer-Policy)

When someone clicks a link to another site, the browser sends along where they came from. Without a rule, that can be the full address, including search terms or IDs in it. The header brings 10 points.

Good starting value: strict-origin-when-cross-origin

Other sites then see only your domain, not the individual page.

Common mistake: unsafe-url. It always sends the full address. The stricter no-referrer is safe, but it can interfere with analytics and affiliate programs.

Block camera, microphone and location (Permissions-Policy)

This header defines which device features your page and embedded third-party content may request at all, such as camera, microphone or location. It brings 10 points.

Good starting value: camera=(), microphone=(), geolocation=()

The empty parentheses mean: nobody.

Common mistake: blocking a feature you need, such as location for a store finder. In that case use geolocation=(self). The syntax of its predecessor, Feature-Policy, no longer applies either.

Still have questions? Email us.

Is your app
watertight?

Hullwise finds the leaks before someone else does: exposed keys, database credentials and outdated software. Every finding comes with steps to fix it.

https://

Click a finding to mark it as fixed.

See pricingHow a scan works

Ship fast. Stay hullwise.