diff --git a/CHANGELOG.md b/CHANGELOG.md index 2800288..3c67714 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +- 2024-02-15: 2.18.0 + + - FEATURE: Implement a default Content-Security-Policy + - 2024-02-15: 2.17.1 - UX: fixed top menu when backlink to the site exists diff --git a/lib/logster/middleware/viewer.rb b/lib/logster/middleware/viewer.rb index 7736f82..1caed4d 100644 --- a/lib/logster/middleware/viewer.rb +++ b/lib/logster/middleware/viewer.rb @@ -85,7 +85,7 @@ def call(env) [200, { "content-type" => "application/json; charset=utf-8" }, [message.to_json]] else preload = { "/show/#{key}" => message } - [200, { "content-type" => "text/html; charset=utf-8" }, [body(preload)]] + js_app(preload) end elsif resource =~ %r{/settings(\.json)?$} json = $1 == ".json" @@ -114,7 +114,7 @@ def call(env) [JSON.generate(suppression: suppression, grouping: grouping)], ] else - [200, { "content-type" => "text/html; charset=utf-8" }, [body]] + js_app end elsif resource =~ %r{/patterns/([a-zA-Z0-9_]+)\.json$} unless Logster.config.enable_custom_patterns_via_ui @@ -151,7 +151,7 @@ def call(env) Logster.store.remove_ignore_count(pattern) [200, {}, ["OK"]] elsif resource == "/" - [200, { "content-type" => "text/html; charset=utf-8" }, [body]] + js_app elsif resource =~ %r{/fetch-env/([0-9a-f]+)\.json$} key = $1 env = Logster.store.get_env(key) @@ -299,15 +299,12 @@ def resolve_path(path) $3 || "/" if path =~ @path_regex end - def css(name, attrs = {}) - attrs = attrs.map { |k, v| "#{k}='#{v}'" }.join(" ") - - "" + def css(name, csp_nonce) + "" end - def script(prod, dev = nil) - name = ENV["DEBUG_JS"] == "1" && dev ? dev : prod - "" + def script(name, csp_nonce) + "" end def to_json_and_escape(payload) @@ -344,32 +341,43 @@ def preloaded_data preload end - def body(preload = {}) + def js_app(preload = {}) + csp_nonce = SecureRandom.hex preload = preloaded_data.merge(preload) root_url = @logs_path root_url += "/" if root_url[-1] != "/" - <<~HTML + body = <<~HTML #{Logster.config.web_title || "Logs"} - - + + - #{css("vendor.css")} - #{css("client-app.css")} - #{script("vendor.js")} + #{css("vendor.css", csp_nonce)} + #{css("client-app.css", csp_nonce)} + #{script("vendor.js", csp_nonce)} - #{script("client-app.js")} + #{script("client-app.js", csp_nonce)} HTML + + [ + 200, + { + "content-type" => "text/html; charset=utf-8", + "content-security-policy" => + "script-src 'nonce-#{csp_nonce}'; style-src 'nonce-#{csp_nonce}'; object-src 'none'; base-uri 'none';", + }, + [body], + ] end end end diff --git a/lib/logster/version.rb b/lib/logster/version.rb index 1ea3594..6a9c2d3 100644 --- a/lib/logster/version.rb +++ b/lib/logster/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Logster - VERSION = "2.17.1" + VERSION = "2.18.0" end