The core of this project is a Python 3 script that helps you check compliance against a baseline. The baseline is defined in code to make it easier to audit changes to them.
Secondary purpose of the project is this README. The table below serves as a best practise cheat sheet for HTTP response headers.
Header | Web | API | Remark |
---|---|---|---|
Strict-Transport-Security |
Add | Add | - |
X-XSS-Protection |
Add | N/A | Remark 1 |
X-Content-Type-Options |
Add | N/A | Remarks 1/4 |
X-Frame-Options |
Add | N/A | Remark 1 |
Content-Security-Policy |
Add | Add | Remarks 2a/2b |
Server |
Remove | Remove | Remark 3 |
X-Powered-By |
Remove | Remove | Remark 3 |
Permissions-Policy |
Add | Add | Remark 5 |
Feature-Policy |
Add | Add | Remark 5 |
Referrer-Policy |
TBR | Add | Remark 2b |
Remark 1 : When serving an API that provides only JSON responses and doesn't serve active content, there's no benefit in adding this header.
Remark 2a : On a web page (APIs are a different deal; see 2b) getting a CSP right can be challenging if you don't incorporate it in your project from the beginning AND stick to keep crafting it properly. Contrary to headers like Strict-Transport-Security
, which apply across the board with one value for your entire site, trying to craft one single CSP for every page may open you up to a vulnerability which could've easily been mitigated by customizing it per page. In short: If a CSP is not designed to be 100% watertight, it can be bypassed by a skilled attacker.
Remark 2b : There is some debate whether or not certain security headers are useful on an API that has an application/json
content type, because there is no script context. Nevertheless, there may be cases where your API returns HTML and this is where certain headers do have value as per OWASP guidance [5]. "I don't need this because the data in my JSON objects is never in HTML" can be true today and at the same tome it is a risky prediction to make for the future of your project. To ascertain that your API will remain properly secured by CSP in the future, the following headers should be added as a best practice:
Content-Security-Policy: default-src 'none'
Feature-Policy: 'none'
Permissions-Policy: 'none'
'Referrer-Policy: no-referrer
Remark 3 : These headers, whose purpose is to advertise details about the technology stack on the server side, don't serve any other good purpose. The information that they show can only ever serve as useful for someone who is looking for vulnerable technologies when preparing an attack. Malicious hackers perform mass scans of public domains or IP addresses to identify easy targets based on the version information that is displayed here.
Remark 4 : If you're running a JSON API you should serve the responses with Content-Type: application/json
which removes the need for the nosniff directive.
Remark 5 : Permissions-Policy
is the new name for the to be deprecated Feature-Policy
, however not all browsers support it. Currently it is recommended to add both with the same value to achieve greater browser coverage [6].
[1] https://scotthelme.co.uk/hardening-your-http-response-headers/
[2] https://security.stackexchange.com/questions/147554/security-headers-for-a-web-api
[3] https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#Security
[4] https://pentest-tools.com/blog/essential-http-security-headers/
[5] https://cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html#security-headers