Add support for adding CSP nonce to profile handler JS script tag (#495)

Add support for adding CSP nonce to profile handler JS script tag (#495)

  • Add content_security_policy_nonce Config option Add MiniProfiler#content_security_policy_nonce method for obtaining current CSP value from config, passing env to Config

  • Determine effective content_security_policy_nonce value from config or env in MiniProfiler#get_profile_script Remove MiniProfiler#content_security_policy_nonce method Remove Proc init in Config#default for content_security_policy_nonce config setting

diff --git a/README.md b/README.md
index f22932e..8972361 100644
--- a/README.md
+++ b/README.md
@@ -412,13 +412,14 @@ snapshots_transport_destination_url|`nil`|Set this config to a valid URL to enab
 snapshots_transport_auth_key|`nil`|`POST` requests made by the snapshots transporter to the destination URL will have a `Mini-Profiler-Transport-Auth` header with the value of this config. Make sure you use a secure and random key for this config.
 snapshots_redact_sql_queries|`true`|When this is true, SQL queries will be redacted from sampling snapshots, but the backtrace and duration of each SQL query will be saved with the snapshot to keep debugging performance issues possible.
 snapshots_transport_gzip_requests|`false`|Make the snapshots transporter gzip the requests it makes to `snapshots_transport_destination_url`.
+content_security_policy_nonce|Rails: Current nonce<br>Rack: nil|Set the content security policy nonce to use when inserting MiniProfiler's script block.
 
 ### Using MiniProfiler with `Rack::Deflate` middleware
 
 If you are using `Rack::Deflate` with Rails and `rack-mini-profiler` in its default configuration,
 `Rack::MiniProfiler` will be injected (as always) at position 0 in the middleware stack,
 which means it will run after `Rack::Deflate` on response processing. To prevent attempting to inject
-HTML in already compressed response body MiniProfiler will suppress compression by setting 
+HTML in already compressed response body MiniProfiler will suppress compression by setting
 `identity` encoding in `Accept-Encoding` request header.
 
 ## Special query strings
diff --git a/lib/html/profile_handler.js b/lib/html/profile_handler.js
index 9c6f104..1fa51d4 100644
--- a/lib/html/profile_handler.js
+++ b/lib/html/profile_handler.js
@@ -1 +1 @@
-<script async type="text/javascript" id="mini-profiler" src="{url}" data-css-url="{cssUrl}" data-version="{version}" data-path="{path}" data-current-id="{currentId}" data-ids="{ids}" data-horizontal-position="{horizontalPosition}" data-vertical-position="{verticalPosition}" data-trivial="{showTrivial}" data-children="{showChildren}" data-max-traces="{maxTracesToShow}" data-controls="{showControls}" data-total-sql-count="{showTotalSqlCount}" data-authorized="{authorized}" data-toggle-shortcut="{toggleShortcut}" data-start-hidden="{startHidden}" data-collapse-results="{collapseResults}" data-html-container="{htmlContainer}" data-hidden-custom-fields="{hiddenCustomFields}"></script>
+<script async nonce="{cspNonce}" type="text/javascript" id="mini-profiler" src="{url}" data-css-url="{cssUrl}" data-version="{version}" data-path="{path}" data-current-id="{currentId}" data-ids="{ids}" data-horizontal-position="{horizontalPosition}" data-vertical-position="{verticalPosition}" data-trivial="{showTrivial}" data-children="{showChildren}" data-max-traces="{maxTracesToShow}" data-controls="{showControls}" data-total-sql-count="{showTotalSqlCount}" data-authorized="{authorized}" data-toggle-shortcut="{toggleShortcut}" data-start-hidden="{startHidden}" data-collapse-results="{collapseResults}" data-html-container="{htmlContainer}" data-hidden-custom-fields="{hiddenCustomFields}"></script>
diff --git a/lib/mini_profiler/config.rb b/lib/mini_profiler/config.rb
index b909cbd..417b22b 100644
--- a/lib/mini_profiler/config.rb
+++ b/lib/mini_profiler/config.rb
@@ -68,7 +68,8 @@ module Rack
         :flamegraph_sample_rate, :logger, :pre_authorize_cb, :skip_paths,
         :skip_schema_queries, :storage, :storage_failure, :storage_instance,
         :storage_options, :user_provider, :enable_advanced_debugging_tools,
-        :skip_sql_param_names, :suppress_encoding, :max_sql_param_length
+        :skip_sql_param_names, :suppress_encoding, :max_sql_param_length,
+        :content_security_policy_nonce
 
       # ui accessors
       attr_accessor :collapse_results, :max_traces_to_show, :position,
diff --git a/lib/mini_profiler/profiler.rb b/lib/mini_profiler/profiler.rb
index 52a57d9..7e4b9e4 100644
--- a/lib/mini_profiler/profiler.rb
+++ b/lib/mini_profiler/profiler.rb
@@ -728,6 +728,10 @@ Append the following to your query string:
       url = "#{path}includes.js?v=#{version}" if !url
       css_url = "#{path}includes.css?v=#{version}" if !css_url
 
+      content_security_policy_nonce = @config.content_security_policy_nonce ||
+                                      env["action_dispatch.content_security_policy_nonce"] ||
+                                      env["secure_headers_content_security_policy_nonce"]
+
       settings = {
        path: path,
        url: url,
@@ -745,7 +749,8 @@ Append the following to your query string:
        startHidden: @config.start_hidden,
        collapseResults: @config.collapse_results,
        htmlContainer: @config.html_container,
-       hiddenCustomFields: @config.snapshot_hidden_custom_fields.join(',')
+       hiddenCustomFields: @config.snapshot_hidden_custom_fields.join(','),
+       cspNonce: content_security_policy_nonce,
       }
 
       if current && current.page_struct

GitHub sha: 83fafc9b

This commit appears in #495 which was merged by SamSaffron.