X-Content-Type-Options errors with nginx configuration

I'm wondering what I'm missing in my nginx configuration that is causing these errors to occur in the browser console and preventing the site from rendering nicely.

I've set up what I thought was a working nginx configuration for a new Linode (Ubuntu 18.04 LTS, Plone 5.2 (yes!), Python 3.6.8), and letsencrypt (certbot is very nice).

But my site isn't rendering nicely because I'm getting many errors like this appearing in the browser (Firefox) console:

The script from “https://plone.oshcom.net/++plone++static/++unique++2019-07-20%2013%3A21%3A37.502871/plone-base-compiled.min.js” was loaded even though its MIME type (“text/html”) is not a valid JavaScript MIME type.

That is if I do not have this in the nginx configuration:

add_header X-Content-Type-Options "nosniff";

If I do have "nosniff" set, I get many of these errors:

The resource from “https://plone.oshcom.net/++plone++static/components/jquery/dist/jquery.min.js” was blocked due to MIME type (“text/html”) mismatch (X-Content-Type-Options: nosniff).
Loading failed for the <script> with source “https://plone.oshcom.net/++plone++static/components/jquery/dist/jquery.min.js”.

The page that Mozilla links to, as an explanation for these errors is:

My nginx configuration file is:

add_header X-Frame-Options "SAMEORIGIN";
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
add_header Content-Security-Policy "default-src 'self'; img-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'";
upstream plone52 {
    server 127.0.0.1:8080;
}
server {
    server_name plone.oshcom.net;
    access_log /var/log/nginx/plone.access.log;
    error_log /var/log/nginx/plone.error.log;
    set $vh_protocol "https";
    set $vh_port "443";
    location / {
        auth_basic off;
          proxy_pass http://plone52/VirtualHostBase/$vh_protocol/$server_name:$vh_port/Plone/VirtualHostRoot/;
    }
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/plone.oshcom.net/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/plone.oshcom.net/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
    if ($host = plone.oshcom.net) {
        return 301 https://$host$request_uri;
    } # managed by Certbot
    listen 80;
    server_name plone.oshcom.net;
    return 404; # managed by Certbot
}

When I look at the HTML source of the front page of the site, the JS seems to be specified with the correct type text/javascript:

<script type="text/javascript" src="https://plone.oshcom.net/++plone++static/++unique++2019-07-20%2013%3A21%3A37.502871/plone-base-compiled.min.js" data-bundle="plone-base">

What would be erroneously giving it MIME type (“text/html”) ?

For one, that url returns html for me.

http://plone.oshcom.net always redirects to https for me... but thx for looking

Thanks for repyling, but thats not what I said.

I said that url like, and including, https://plone.oshcom.net/++plone++static/++unique++2019-07-20 13%3A21%3A37.514871/plone-compiled.css do not return css, but an html page.

This is how the page looks to me, so something else is wrong.

Yes, that’s what it looks like to me too, hence my asking for help :joy:

Does https://plone.oshcom.net/logo.png work directly on the upstream? ie http://127.0.0.1:8080/Plone/logo.png on the server?

hmm. I've never done a direct proxy_pass like that, we always use first a rewrite stanza like

location / {
    rewrite ^/(.*)$ /VirtualHostBase/$vh_protocol/$server_name:$vh_port/Plone/VirtualHostRoot/$1;
}

followed by

location /VirtualHostBase/ {
    proxy_pass http://upstream_or_local:port;
    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_redirect off;
}

I just had the same effect when I was trying to get rid of the static host string in my proxy_pass rule:

before I had:

   location / {
       proxy_pass http://127.0.0.1:9010/VirtualHostBase/https/www.mysite.com:443/Plone/VirtualHostRoot/;
   }

when I changed it to:

   location / {
       proxy_pass http://127.0.0.1:9010/VirtualHostBase/https/$server_name:443/Plone/VirtualHostRoot/;
   }

the resources where missing.
After debugging nginx, I found out that, the request to the backend was missing the $request_uri parameters. So I changed it to:

   location / {
       proxy_pass http://127.0.0.1:9010/VirtualHostBase/https/$server_name:443/Plone/VirtualHostRoot/$request_uri;
   }

and everything works fine :wink:

It seems that nginx handles the rule in a diffenrent way when you add variables there, as the rule was working like this with the static host string in it.

2 Likes

In the end I simplified my nginx configuration by removing the add_header directives. This is what I used successfully:

server {
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/wave.oshcom.net/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/wave.oshcom.net/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
  ssl on;

    server_name wave.oshcom.net;

  client_max_body_size 5M;

  proxy_set_header X-Real-IP $remote_addr;
  # Note that the setting below overrides any pre-existing X-Forwarded-For
  # information. You'll want to change this if you have trustworthy incoming
  # forward information.
  proxy_set_header X-Forwarded-For $remote_addr;

   set $vh_protocol "https";
   set $vh_port "443";

  location / {
    rewrite ^/(.*)$ /VirtualHostBase/$vh_protocol/$server_name:$vh_port/WaveRobotics/VirtualHostRoot/$1 break;
    auth_basic off;
    proxy_pass http://localhost:8080;
  }
  location ~ /manage_ {
    deny all;
  }
}

server {
    if ($host = wave.oshcom.net) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen 80;
    server_name wave.oshcom.net;
    return 404; # managed by Certbot
}

Plone Foundation Code of Conduct