Skip to content

Commit

Permalink
Use script-src: sha256-* instead of nonce for importmap
Browse files Browse the repository at this point in the history
This allows the importmap to be cached without creating a long lived nonce in the cache
  • Loading branch information
martinemde committed Jan 31, 2024
1 parent c1ec80a commit 033ffb6
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 0 deletions.
17 changes: 17 additions & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,23 @@ class ApplicationController < ActionController::Base

add_flash_types :notice_html

###
# Content security policy override for script-src
# This is necessary because we use a SHA256 for the importmap script tag
# because caching behavior of the mostly static pages could mean longer lived nonces
# being served from cache instead of unique nonces for each request.
# This ensures that importmap passes CSP and can be cached safely.
content_security_policy do |policy|
policy.script_src(
:self,
"'sha256-#{Digest::SHA256.base64digest(Rails.application.importmap.to_json(resolver: ApplicationController.helpers))}'",
"https://secure.gaug.es",
"https://www.fastly-insights.com",
"https://unpkg.com/@hotwired/stimulus/dist/stimulus.umd.js",
"https://unpkg.com/stimulus-rails-nested-form/dist/stimulus-rails-nested-form.umd.js"
)
end

def set_locale
I18n.locale = user_locale

Expand Down
7 changes: 7 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ def atom_feed_link(title, url)
title: title)
end

# Copied from importmap-rails but with the nonce removed. We rely on the sha256 hash instead.
# Relying on the hash improves the caching behavior by not sending the cached nonce to the client.
def javascript_inline_importmap_tag(importmap_json = Rails.application.importmap.to_json(resolver: self))
tag.script importmap_json.html_safe,
type: "importmap", "data-turbo-track": "reload"
end

def short_info(rubygem)
info = gem_info(rubygem).strip.truncate(90)
escape_once(sanitize(info))
Expand Down
2 changes: 2 additions & 0 deletions config/initializers/content_security_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
policy.img_src :self, "https://secure.gaug.es", "https://gravatar.com", "https://www.gravatar.com", "https://secure.gravatar.com",
"https://*.fastly-insights.com", "https://avatars.githubusercontent.com"
policy.object_src :none
# NOTE: This scirpt_src is overridden for all requests in ApplicationController
# This is the baseline in case the override is ever skipped
policy.script_src :self,
"https://secure.gaug.es",
"https://www.fastly-insights.com",
Expand Down

0 comments on commit 033ffb6

Please sign in to comment.