20

I just got a setup, a golang web api behind a caddy server that has HTTPS by default via Let's Encrypt, the server proxies all requests to the web api. So I went around to test my webserver "security" on sites such as securityheaders.io. They gave me an F, so I added the headers they demanded and I got an A

Access-Control-Allow-Methods "GET, POST, OPTIONS"
Strict-Transport-Security "max-age=31536000;"
Content-Security-Policy "script-src 'self'"
X-XSS-Protection "1; mode=block"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
-Server

These are the headers I currently have, but I'd like to know if they are necessary for security when what I'm making is not a website but rather a API webserver, something like

Access-Control-Allow-Methods "GET, POST, OPTIONS"
-Server

So basically, all those security headers necessary if you want to just request your API?

Whiteclaws
  • 333
  • 1
  • 3
  • 6
  • Those are the decent headers for a good browser alright. Several browser's will not support them but there is a good deal of browsers that will respect that. It all depends on what you want to **defend against**. For example, if you want different things to be sent when accessing the API from different clients you may as well try adding something like: `X-Requested-With: XMLHttpRequest`. HSTS may or may not be required too. (and if you want to go overboard even HSTS pinning, although only dev versions of browsers currently support that) – grochmal Jan 07 '17 at 01:27
  • most of those are to protect html-delivered applications, APIs don't really need all that. CORS would be good for an API, but the others do basically nothing for an XMLHttpRequest and only add bandwidth. – dandavis Jan 08 '17 at 08:20

1 Answers1

43

Checking headers off a list is not the best technique to assert a site's security. Services like securityheaders.io can point you in the right direction but all they do is compare against a list of proposed settings without any context about your application. Consequently, some of the proposals wont't have any impact on the security of an API endpoint that serves nothing but JSON responses.

  • Strict-Transport-Security makes sense because it guarantees that users will directly connect to your site via HTTPS after their first visit and until the max-age timeout is reached - thereby preventing downgrade attacks. Even an API endpoint should be secured with SSL, so keep that header.

  • Access-Control-Allow-Methods: GET, POST, OPTIONS is not a security option per se. If your API works via CORS preflight requests you need to decide which methods you allow for cross-origin sites to use. Disabling CORS could make your API unavailable. If that particular setting is sensible depends on your implementation.

  • X-XSS-Protection: 1; mode=block can be good adivice for regular sites because it instructs the XSS Auditor (which is implemented in WebKit browsers but not Firefox) to not render the site when it detects a reflected XSS attempt. But for an API that just provides JSON responses and doesn't serve active content, this header doesn't bring any benefit.

  • X-Content-Type-Options: nosniff prevents browsers from making assumptions about the content type if the site didn't declare the type correctly. If you're running a JSON API you should serve the responses with Content-Type: application/json. If you do that correctly there will be no need to add the nosniff directive.

  • X-Frame-Options: Deny prevents any website from embedding your site in an HTML frame. That option stops clickjacking attacks where an attacker tricks users into interacting with your website through a disguised frame. But without interactive elements there is limited risk through cross-origin framing. Yet, as there are advanced attacks involving dragging content out of the frame which could disclose JSON responses, you might still want to leave that header there.

  • Content-Security-Policy headers control what kind of content from what origin your site is allowed to interact with (scripts, stylesheets, images, etc.). Your setting "script-src 'self' means that only scripts from the same origin may be loaded. A CSP is useful for regular sites but doesn't make sense for your API endpoint because you don't serve any active content that could be controlled by the CSP.

  • The Server header specifies information about the server and the software running on it. It's often advised to not send that header at all to not disclose anything about backend software and versions.

Arminius
  • 43,922
  • 13
  • 140
  • 136
  • 3
    Also smart to remove the `X-Powered-By` in addition to the `Server` header. – pim Sep 20 '17 at 16:27
  • 4
    FWIW, Mozilla actually _recommends_ API endpoints send a Content-Security-Policy header: https://observatory.mozilla.org/faq/ and https://infosec.mozilla.org/guidelines/web_security#content-security-policy – shelley Jun 17 '19 at 15:57
  • @Arminius and what about the Cache-Control and Pragma headers? – Gawey Aug 20 '20 at 12:15
  • What about the Permissions Policy header that has become part of https://securityheaders.com/ checks ? Is it relevant for APIs ? I find very little documentation about it. – Cyril Duchon-Doris Oct 20 '20 at 10:07