Check the security of any website
HTTP security headers are a fundamental part of website security. They allow web servers to instruct browsers on how to behave when handling a website's content. This helps prevent common attacks such as Cross-Site Scripting (XSS), clickjacking, and man-in-the-middle attacks. By correctly implementing headers like Content-Security-Policy, Strict-Transport-Security, and X-Frame-Options, you add a crucial layer of defense to your application. This not only protects your website but also the data and privacy of your users.
The HTTP Strict Transport Security (HSTS) header is a powerful security measure that protects websites against man-in-the-middle attacks, such as protocol downgrade attacks and cookie hijacking. In essence, it is an instruction from the web server to the browser to communicate exclusively via a secure, encrypted HTTPS connection and never via insecure HTTP. This instruction is remembered by the browser for a period specified by the website.
The primary danger that HSTS addresses is 'SSL stripping'. Imagine a user connecting to a public Wi-Fi network at a coffee shop. An attacker on the same network can intercept the user's first, unsecured HTTP request. Even if the website normally redirects to HTTPS, the attacker can block this redirection and maintain an unencrypted connection with the user, while establishing an encrypted connection with the server themselves. The user notices nothing, but the attacker can now read all traffic, including passwords and personal data, in plain text. HSTS prevents this scenario completely. Once a browser has received the HSTS header from a domain, it will automatically and internally convert all future attempts to connect via HTTP to HTTPS before the request even leaves the network. The attacker simply never gets the chance to intercept the connection.
The implementation of HSTS is done via the header itself, which can contain several directives. The most important is `max-age`, which specifies in seconds how long the browser should remember the HSTS rule. A typical recommended value is 31536000, which corresponds to one year. Another powerful directive is `includeSubDomains`. If present, the HSTS rule applies not only to the main domain (e.g., `www.example.com`) but also to all subdomains (such as `blog.example.com` and `api.example.com`). This is a crucial addition, but it requires that all subdomains are fully accessible via HTTPS. The ultimate protection is provided by the `preload` directive. If a website meets strict requirements, it can be included in the 'HSTS preload list', a list that is hardcoded into major browsers like Chrome, Firefox, and Safari. This means that even the very first connection a user makes to the website is immediately forced to HTTPS, leaving no window of vulnerability.
The Content-Security-Policy (CSP) is one of the most powerful and essential defense mechanisms against a wide range of content injection attacks, with the primary goal of mitigating Cross-Site Scripting (XSS). In a nutshell, CSP allows a website administrator to define a strict 'whitelist' of trusted sources. Only content originating from these explicitly approved domains may be loaded and executed by the browser. This includes scripts, stylesheets, images, fonts, iframes, and more. Anything not on this list is mercilessly blocked by the browser, drastically reducing the attack surface for common vulnerabilities.
To understand the power of CSP, one must first understand the threat of XSS. An XSS attack occurs when an attacker manages to inject malicious code, usually JavaScript, into a legitimate website. This can happen via a comment field, a search bar, or a manipulated URL. When another user visits the infected page, this script is executed in their browser with the same permissions as the website itself. The attacker can use this to steal session cookies, capture keystrokes, visually modify the page, or redirect the user to a phishing site. CSP tackles this problem at its root. Even if an attacker injects a malicious script, a well-configured CSP will instruct the browser not to execute it because it does not come from an approved source. By default, CSP also blocks inline scripts and `eval()`-like functions, which are common techniques in XSS attacks.
Configuring a CSP is done through a series of 'directives' in the header value. Each directive manages a specific type of content. For example, `script-src` determines which sources can supply scripts, `style-src` controls stylesheets, and `img-src` manages images. The `default-src` directive acts as a fallback for most other directives. Common source values are `'self'` (which refers to the own domain), specific domains (like `https://apis.google.com`), and `'none'` (which allows nothing). Implementing a CSP requires careful planning, as a policy that is too strict can break legitimate functionality. Therefore, CSP also offers a `report-only` mode. In this mode, violations are not blocked, but a report is sent to a developer-specified URL via the `report-uri` or `report-to` directive. This allows teams to test and refine their policy in a production environment without disrupting the user experience.
The `X-Content-Type-Options` header is a seemingly simple, yet extremely effective security measure that blocks a specific and insidious attack vector: MIME type sniffing. With only one possible, valid value, `nosniff`, this header gives a clear and unambiguous instruction to the browser: trust the `Content-Type` header sent by the server and under no circumstances try to guess the file type yourself. This simple rule is a fundamental defense against a class of attacks that exploit the tendency of browsers to be 'helpful'.
The core of the problem is 'MIME sniffing'. Web servers send a `Content-Type` header with every file to tell the browser what it is (e.g., `text/html`, `image/jpeg`, `application/javascript`). However, older browsers sometimes tried to be smarter than the server. For example, if a server sent a file with `Content-Type: text/plain`, but the content looked like HTML, the browser might decide to render it as HTML anyway. Although this was intended to correct misconfigured servers, it created a dangerous vulnerability. An attacker can exploit this by uploading a file that appears harmless at first glance but actually contains malicious code.
A classic attack scenario is as follows: an attacker uploads a file to a website, for example, as a profile picture. This file has a `.jpg` extension and contains valid image data, but malicious JavaScript code is also hidden inside. The server sees the `.jpg` extension, trusts it, and serves the file with `Content-Type: image/jpeg`. When a victim views this 'image', a browser without the `nosniff` instruction might inspect the file. The browser detects the JavaScript code and decides, despite the `Content-Type` header, that it is a script and executes it. Because this script is executed within the context of the website, it has access to the user's session, which can lead to a full account takeover via Cross-Site Scripting (XSS).
The `X-Content-Type-Options: nosniff` header stops this attack completely. The browser is now given the explicit command: 'If the server says this is an `image/jpeg`, treat it as an image and nothing else.' The browser will no longer try to 'sniff' the content and will ignore the hidden JavaScript code. The implementation is trivial – it's simply adding a single header to all server responses. It is a perfect example of a 'defense-in-depth' principle: even if other security layers (like file validation on upload) fail, this header provides a robust final line of defense. It is an essential, low-effort measure that should be present on every modern website.
The `X-Frame-Options` header is a crucial security measure specifically designed to prevent an insidious attack called 'clickjacking'. Clickjacking, also known as a 'UI redress attack', is a technique where an attacker tricks a user into clicking something different from what the user perceives. This is usually achieved by layering an invisible or transparent webpage (or part of it) in an iframe over the visible page. The user thinks they are clicking an innocent button, like 'Win a prize', but in reality, their click is registered on the invisible page underneath, for example, on a 'Delete my account' button of a website they are currently logged into.
The `X-Frame-Options` header provides a simple but effective way to control whether a browser is allowed to render a page within embedding elements like frames or iframes. By including this header in a webpage's HTTP response, the server can instruct the browser on how to handle such requests. There are two commonly used, and one obsolete, directives. The most restrictive and safest option is `DENY`. This value completely forbids rendering the page in a frame, regardless of which website tries to do so. This is the best choice for pages with highly sensitive actions that should never be embedded, such as password change pages or financial transaction pages.
A more flexible, and very common, option is `SAMEORIGIN`. This directive allows the page to be rendered in a frame, but only if the website attempting to embed the page has the same origin (domain) as the page itself. This is particularly useful for web applications that use iframes for their own legitimate functionality, such as displaying modal windows or integrating different parts of the same application, while preventing embedding by external, potentially malicious websites. A third, obsolete option is `ALLOW-FROM uri`, which allowed specifying a specific URL that was permitted to frame the page. However, this option was never widely supported by all browsers and is now considered obsolete.
While `X-Frame-Options` is still very relevant and effective, it is important to note that the more modern `Content-Security-Policy` (CSP) includes a `frame-ancestors` directive. This directive is considered the successor to `X-Frame-Options` as it offers more flexibility (such as specifying multiple allowed domains). However, due to its wide support and simplicity, implementing `X-Frame-Options` remains a recommended 'defense-in-depth' strategy, especially to ensure compatibility with older browsers. By correctly configuring this header, an entire class of UI-based attacks is effectively neutralized.
The `Referrer-Policy` header is an essential tool for protecting user privacy by controlling what information is sent in the `Referer` header (note the historical misspelling) when a user navigates from one page to another. By default, a browser sends the full URL of the previous page to the new page. While this is useful for analytics and understanding traffic flows, it creates a significant privacy risk. URLs can contain sensitive information, such as search terms, user IDs, or even password reset tokens. Forwarding this data to external parties without the user's knowledge is a data leak that can be exploited.
The `Referrer-Policy` allows website owners to precisely control this behavior using various directives. The choice of a directive is a trade-off between privacy and functionality. One of the strictest options is `no-referrer`. As the name suggests, the `Referer` header is completely omitted from all outgoing requests in this case. This provides maximum privacy but makes it impossible for the receiving site to see where the traffic is coming from, which can complicate traffic source analysis. Another common, privacy-friendly option is `strict-origin-when-cross-origin`. This is often a good default choice. It behaves as follows: for navigation within the same website (e.g., from `example.com/page1` to `example.com/page2`), the full URL is sent. However, for navigation to another website (cross-origin), only the base URL (the origin, e.g., `https://example.com/`) is sent, and only if the connection is equally secure (HTTPS to HTTPS).
Other directives offer more granular control. `same-origin` ensures that the referrer is only sent for requests within the same website; it is omitted for all other requests. `strict-origin` sends only the base URL, but unlike `strict-origin-when-cross-origin`, it also does this for navigation within the same site. At the other end of the spectrum is `unsafe-url`, which, as the name implies, is unsafe. This directive always sends the full URL, including query parameters, even on insecure (HTTP) requests. Its use is strongly discouraged. By consciously choosing a `Referrer-Policy`, website owners take responsibility for their users' data. Implementing a restrictive policy, such as `strict-origin-when-cross-origin`, is a simple step that significantly improves privacy without breaking essential functionality.
The `Permissions-Policy` header is a modern and powerful security feature that gives website administrators detailed control over which browser features and APIs can be used on a page. This header, which replaces the older `Feature-Policy`, is based on the 'principle of least privilege': a piece of code should only have the permissions absolutely necessary to perform its task. By explicitly defining which features are allowed, developers can significantly reduce their website's 'attack surface' and better protect user privacy.
Modern web applications increasingly use powerful browser APIs, such as access to the camera (`camera`), microphone (`microphone`), geolocation (`geolocation`), fullscreen mode (`fullscreen`), and payment processing (`payment`). While these features enable innovative user experiences, they also pose a potential risk. A vulnerability in a third-party script, such as an advertising or analytics script loaded on your page, could be exploited to gain unwanted access to these sensitive APIs. For example, a user could be unknowingly prompted to grant microphone access to an untrustworthy script piggybacking on your legitimate website.
The `Permissions-Policy` addresses this problem by specifying a clear policy. The header consists of a series of directives, where each directive represents a specific feature. For each feature, a list of allowed 'origins' (domains) can be specified. For example, if a website does not need access to the microphone, the developer can explicitly disable it with `permissions-policy: microphone=()`. The empty parentheses `()` mean the feature is disabled for all parties (including the own site and all iframes). If a feature should only be used by the own website, it can be set with `microphone=('self')`. This ensures that embedded iframes from third parties, such as a YouTube video, cannot request microphone access.
The real power of `Permissions-Policy` lies in its granular control over third-party content. You can grant permission to a specific domain, for example, `permissions-policy: camera=('self' https://trusted-partner.com)`. This ensures that only your own site and a trusted partner can use the camera. All other iframes will be blocked. Implementing a strict `Permissions-Policy` is a best practice for modern web development. It forces developers to consciously think about what functionality their application really needs and provides a robust defense layer against the abuse of browser APIs. This results in a safer experience for the user and strengthens trust in your platform.
The `X-XSS-Protection` header is a piece of internet history; a security measure once introduced in browsers like Internet Explorer, Chrome, and Safari as a first line of defense against 'reflected' Cross-Site Scripting (XSS) attacks. Although the intention was good, the header is now obsolete and is deprecated and even ignored by all modern browsers. Its functionality has been completely replaced by the much more robust and configurable `Content-Security-Policy` (CSP). However, understanding the operation and shortcomings of `X-XSS-Protection` provides valuable insight into the evolution of web security.
The header was designed to block a specific attack vector: a 'reflected' XSS attack. This type of attack occurs when malicious code, via a URL parameter or form input, is 'reflected' by the server and included directly in the HTML response. The `X-XSS-Protection` header activated a built-in 'auditor' or 'filter' in the browser. This filter used heuristics to detect if script code in the request (e.g., in the URL) also appeared literally in the page's HTML. If so, the browser concluded that an attack was taking place.
The header could have several values. The default value was `1`, which activated the filter. Upon detecting an attack, the browser would try to 'sanitize' the page by removing or neutralizing the malicious code. However, this proved to be a dangerous approach. Attackers discovered ways to bypass these sanitization mechanisms and, in some cases, could even create vulnerabilities that did not exist without the filter. A safer option was `1; mode=block`. In this mode, upon detecting an attack, the browser would stop rendering the page completely and show a blank page. This prevented the script from executing but provided a poor user experience. The value `0` explicitly disabled the filter.
Ultimately, the header was deprecated for several reasons. The filters were unreliable, could be bypassed, and sometimes caused 'false positives' that broke legitimate websites. More importantly, the rise of `Content-Security-Policy` offered a fundamentally superior approach. Instead of trying to 'guess' attacks based on unreliable heuristics, CSP allows developers to define a strict 'whitelist' of trusted code sources. This 'deny by default' model is inherently safer. Although you may still encounter the `X-XSS-Protection` header on older websites, it is no longer considered an active security measure for modern web development. The focus is now entirely on a strong and well-configured CSP.
This tool analyzes the URL you enter and checks for the presence and correct configuration of the most important security headers. We provide a clear overview of which headers are present and which are missing. Additionally, we offer a detailed explanation of the purpose of each header and the risks you run if it is not present. Use this analysis to improve your website's security.