A web application only sets the HSTS header in responses to requests to /assets/*. Any other response does not include the HSTS header.

While it does seem insecure at first, any browser opening the index page will quickly follow up loading all the assets, which then results in the HSTS header being seen and respected for all future requests.

Is there something I am missing? Is this strange setup fine?

  • 1
    That is a strange setup, but it may be perfectly functional. I'm not 100% sure so I'm curious to see if anyone else has anything to say Apr 10, 2020 at 9:25
  • 3
    The dangers are addressed in other answers. A possible reason for this setup might be that the main website is using a different serverside framework than the /assets folder. Perhaps the main website framework does not support or is not configured for HSTS.
    – Jeff
    Apr 10, 2020 at 13:59

2 Answers 2


It would be recommendable to have the HSTS header set on every HTTPS response, but this effectively provides the same level of security, because the HSTS policy is cached for the max-age seconds. It's defined that the lack of Strict-Transport-Security header doesn't cause deletion of the policy, but only settings a zero value for the max-age (RFC 6796 6.1.1, 5.3 & 12.5). Also, settings a value too low causes it to expire too soon.

These setups can protect a user that has visited the page on a trusted network (or a browser seen the HSTS header on it, to be more precise) within the max-age seconds. If the URLs providing the HSTS header are loaded on every visit, this wouldn't really compromise this. Despite that, I can't see any reason not to move this configuration on hostname level, and it might just be a mistake, too.

However, this prevents from protecting the users before they have ever visited the site (which would be the next step & level), as the presense of Strict-Transport-Security with both includeSubDomains and preload on request to / is mandatory, if you wish to add the domain to an HSTS Pre-Loaded List. This is the only way to protect the whole example.com, *.example.com, *.*.example.com etc. in advance. In addition, hstspreload.org requires that the max-age must be at least 31536000 seconds (1 year).


It does seem strange. Here are two scenarios to illustrate.

Scenario One

Maybe the browser settings may be such that assets are not loaded, e.g., a mobile device on mobile data, where assets might not be loaded to conserve bandwidth.

Then you would be open to all the vulnerabilities that HSTS protects against.

Scenario Two (This scenario edited after discussion in comments below)

Moreover, even without such a restriction on assets loading, without the HSTS header for the index page, your leave your web app open to attacks, the result of which is that an attacker might already have succeeded in replacing the initial response with an arbitrary page of their choosing, over http. If this happens for the load of the index page, then whatever asset loading that is supposed to happen next, becomes irrelevant, so your browser never even requests for those assets, and never see the HSTS header in the responses.

As a concrete example, consider an SSL-stripping man-in-the-middle (MiTM) attacks. With SSL stripping MiTM attacks, a https connection is converted to http by the MiTM. Now, what is to prevent the attacker from simply ignoring the HSTS header coming from your web app its response, and presenting their arbitrary response back to the client over http without the HSTS header? That's where preload lists come into the picture.

All the major browsers implement HSTS preload lists that include known sites supporting HSTS. Thus, the browser doesn't have to rely on receiving the actual response from the site in order to know that it implements HSTS, so the browser will enforce the use of https. So, how are these HSTS preload lists generated for use by the browsers?

In the case of firefox, for example (see blog.mozilla.org/security),

To build our preload list, a request is sent to every host with ‘mode: “force-https”‘ on Chrome’s list. Only if a host responds with a valid HSTS header ..

so not including the HSTS header in the web app's index page may cause it to be excluded from the preload list, leaving the web app open to attacks that HSTS (implemented with preload lists) would normally protect against.

  • Not 100% sure but: That last part is true but perhaps not completely relevant. If the user loads the actual main index page then the browser will request the assets and therefore encounter the HSTS. Therefore the only way to stop the HSTS from being encountered by the browser is to keep the user from loading the index page in the first place, which is what you would do during a standard SSL Strip attack anyway, the only defense for which is to get on the pre-load list. So this doesn't appear to put them in a worst position than if they just had the HSTS on the index Apr 10, 2020 at 9:49
  • I definitely agree with the first part though. If there are cases where assets are not loaded (maybe mobile?) then this is definitely not the way to go. If they have an API endpoints that would also do it... Apr 10, 2020 at 9:50
  • For the second part, what I meant is that without the HSTS header, various attacks could be possible, including SSL stripping man-in-the-middle attacks, which might then present an arbitrary different index page over http. This arbitrary different index page need not include all of, or any of, the assets associated with the original page. Apr 10, 2020 at 14:46
  • 1
    Indeed, but how is that any different than if they had HSTS on the index page? An SSL stripping MitM attack can remove the HSTS header even if it was on the index page. The only thing that could stop that would be the preload list. As a result the fact that HSTS is only on the assets doesn't change the overall picture (for an SSL stripping MitM attack anyway) Apr 10, 2020 at 14:51
  • 1
    Interesting! I think these details will add a lot to your answer - you should add them in! Apr 10, 2020 at 19:32

You must log in to answer this question.