Turbo, Helment, And Csp

23 Mar 2024 - Ben

I had some trouble with Turbo, but I couldn’t find anything online about it. It appeared my requests were being upgraded automatically from http to https, and I couldn’t figure out why. I’m building a little node web app for easier calendar entry of my fiance’s irregular work schedule. It’s mostly a learning project, I wanted to learn a little about WebDAV and different ways to deploy to production. I know javascript, node, express pretty well so I started there. Got everything working, rendering Nunjucks templates and absolutely no client side javascript. I learned some stuff about user authentication, and installed Helmet into my application, but didn’t change too many of the defaults.

Then I wanted to learn more about Turbo. I knew I wanted some javascript to add a little more feedback here and there, but this site was meant as an experiment in good progressive enhancement techniques, so the site didn’t need any javascript running. I toyed with the idea of HTMX, but Turbo did so much right out of the gate that I was hooked. It also seems to have a good story about progressive enhancment as well. Except forms wouldn’t reload properly!

Finally I just used data-turbo="false" to disable it for my main form, but that wasn’t want I wanted long term. None of my requests were doing this before Turbo, but I couldn’t figure out what difference was causing the issue. See, Turbo swaps the browser’s builtin request mechanisms for ajax calls. It’s nearly transparent and they’re both network requests, so what’s the big deal? Browsers treat these two things very differently though, because normal navigation can be trusted (the browser must think, “I made it myself”) but ajax calls are untrusted and Content Security Policies (CSP) greatly affect how scripts can run.

There’s a lot of options for CSP header directives, I don’t fully understand them all. But that’s what Helment is for! Good defaults and strong security, except even it acknowledges that it’s CSP header may need some configuration. After a little trial and error I settled on the “update insecure requests” directive was the one causing the issue. My server was requesting the browser upgrade any requests being made, and the browser was happily complying! It wasn’t happening to normal redirects because the server asks the browser to make those, so there’s no client side involvement. But with Turbo intercepting those redirect requests, the browser needed to make sure those would be secure, that’s what the server asked for!

End of the story is that I disabled that directive of the CSP header in development and now my forms work just as advertised! I don’t expect this to be an issue in production, where I want all requests to be made securely. Hopefully this little tidbit is helpful!