Baroshem / nuxt-security

🛡 Automatically configure your app to follow OWASP security patterns and principles by using HTTP Headers and Middleware
https://nuxt-security.vercel.app/
MIT License
737 stars 56 forks source link

Move meta charset back to top #444

Closed frederikheld closed 3 weeks ago

frederikheld commented 1 month ago

I just added the nuxt-security plugin to my Nuxt project and am using the configuration as it comes out of the box.

Problem: Nuxt adds the CSP meta tag as first element in head. This is a problem because Google Lighthouse will (rightfully!) complain that "Charset declaration is missing or occurs too late in the HTML".

Initially, I had charset defined in useSeoMeta, then moved it to useHead and finally moved it to the app section nuxt.config.ts. None of this moved the meta charset tag back to the top of head. The meta CSP tag always stays the first element.

As I also could not find any information about this issue in the nuxt-security docs, I'm asking this question here:

How can I move meta charset back to the top of head?

vejja commented 1 month ago

Hi @frederikheld We insert CSP meta as first tag in head to conform to the Mozilla security recommendations: https://infosec.mozilla.org/guidelines/web_security#implementation-notes

@Baroshem what's your view on this one ? As I understand, this seems to conflict with Lighthouse. We could provide an option to insert it later ?

frederikheld commented 1 month ago

Ah, I see, we have competing recommendations here. But I think that Mozilla is wrong here. The meta tag defines how the rest of the content should be interpreted so it should go first.

According to the W3C spec for HTML4, the browser will treat anything before the meta charset tag as ISO-8859-1. So we should make sure that nothing of relevance comes before it.

The W3C spec for HTML5 mentions that the document needs to have a meta charset tag (it is not optional like it was in HTML4) and it needs to appear within the first 1024 bytes of the document. I think this is what Lighthouse complains about.

So I would suggest to keep meta charset before the CSP rules. Otherwise the browser might misinterpret them.

Baroshem commented 1 month ago

Thanks for this issue @frederikheld and thanks for heads up @vejja 💚

Considering that we have valid resources that have completely different approaches here, I suggest we should also support both.

So my idea would be to add an option to the ssg object that when set to true, it would add the CSP meta as the last element.

Would that make sense? I am not sure if there is one gold solution for solving both cases unless I am mistaken

frederikheld commented 1 month ago

By all due respect for the security folks at Mozilla, but the Mozilla document is a tutorial with recommendations (see first paragraph) and it doesn't even say why it is recommending to put the csp meta tag before the charset meta tag against the official specs.

This has some serious Judge Dredd vibes that I often encounter in security folks: if the rules don't put us first, we change the rules to be first again.

But what are those csp rules worth if the browser can't interpret them because it uses the wrong charset?

This is what the specs say about the content security policy tag:

Authors are strongly encouraged to place meta elements as early in the document as possible, because policies in meta elements are not applied to content which precedes them. In particular, note that resources fetched or prefetched using the Link HTTP response header field, and resources fetched or prefetched using link and script elements which precede a meta-delivered policy will not be blocked.

Emphasises are mine. source, same wording for CSP2

Those two specs combined make it very clear how the order of meta tags needs to be:

1. meta charset
2. meta csp
3. everything that is script or link

If you want to introduce that switch you proposed, I strongly suggest to default to that order to be compliant to the spec and use the switch to put csp first for anyone who can sleep better if they have it that way.

vejja commented 1 month ago

I have to agree that HTML5 is a W3C spec, while Mozilla only gives a recommendation. I’ll submit a patch

frederikheld commented 1 month ago

Thanks a lot :-) I'm looking forward to it :-)

vejja commented 1 month ago

Implementation proposal in PR #445 follows your suggestion @frederikheld

1. meta charset
2. meta csp
3. everything that is script or link

If meta charset is not the first element, then csp is first.

vejja commented 1 month ago

Dropped #445 in favour of #449 to close this

Baroshem commented 1 month ago

Thank you so much @vejja for it! We will release it as the part of RC1