DEV: Add manifest-src to CSP (#13319)

DEV: Add manifest-src to CSP (#13319)

Defaults to manifest-src: 'self' and allows plugins/themes to extend it.

diff --git a/lib/content_security_policy/builder.rb b/lib/content_security_policy/builder.rb
index fe2e830..9ff21f4 100644
--- a/lib/content_security_policy/builder.rb
+++ b/lib/content_security_policy/builder.rb
@@ -6,6 +6,7 @@ class ContentSecurityPolicy
     EXTENDABLE_DIRECTIVES = %i[
       base_uri
       frame_ancestors
+      manifest_src
       object_src
       script_src
       worker_src
@@ -19,7 +20,6 @@ class ContentSecurityPolicy
       form_action
       frame_src
       img_src
-      manifest_src
       media_src
       prefetch_src
       style_src
diff --git a/lib/content_security_policy/default.rb b/lib/content_security_policy/default.rb
index 3acafad..f3382e3 100644
--- a/lib/content_security_policy/default.rb
+++ b/lib/content_security_policy/default.rb
@@ -14,6 +14,7 @@ class ContentSecurityPolicy
         directives[:worker_src] = worker_src
         directives[:report_uri] = report_uri if SiteSetting.content_security_policy_collect_reports
         directives[:frame_ancestors] = frame_ancestors if restrict_embed?
+        directives[:manifest_src] = ["'self'"]
       end
     end
 
diff --git a/spec/fixtures/plugins/csp_extension/plugin.rb b/spec/fixtures/plugins/csp_extension/plugin.rb
index 364dd10..71625d3 100644
--- a/spec/fixtures/plugins/csp_extension/plugin.rb
+++ b/spec/fixtures/plugins/csp_extension/plugin.rb
@@ -8,5 +8,6 @@
 extend_content_security_policy(
   script_src: ['https://from-plugin.com'],
   object_src: ['https://test-stripping.com'],
-  frame_ancestors: ['https://frame-ancestors-plugin.ext']
+  frame_ancestors: ['https://frame-ancestors-plugin.ext'],
+  manifest_src: ['https://manifest-src.com']
 )
diff --git a/spec/lib/content_security_policy_spec.rb b/spec/lib/content_security_policy_spec.rb
index 73192cd..c203c85 100644
--- a/spec/lib/content_security_policy_spec.rb
+++ b/spec/lib/content_security_policy_spec.rb
@@ -155,6 +155,12 @@ describe ContentSecurityPolicy do
     end
   end
 
+  describe 'manifest-src' do
+    it 'is set to self' do
+      expect(parse(policy)['manifest-src']).to eq(["'self'"])
+    end
+  end
+
   describe 'frame-ancestors' do
     context 'with content_security_policy_frame_ancestors enabled' do
       before do
@@ -198,7 +204,7 @@ describe ContentSecurityPolicy do
       end
     end
 
-    it 'can extend script-src and object-src' do
+    it 'can extend script-src, object-src, manifest-src' do
       plugin = plugin_class.new(nil, "#{Rails.root}/spec/fixtures/plugins/csp_extension/plugin.rb")
 
       plugin.activate!
@@ -208,9 +214,12 @@ describe ContentSecurityPolicy do
       expect(parse(policy)['script-src']).to include('https://from-plugin.com')
       expect(parse(policy)['object-src']).to include('https://test-stripping.com')
       expect(parse(policy)['object-src']).to_not include("'none'")
+      expect(parse(policy)['manifest-src']).to include("'self'")
+      expect(parse(policy)['manifest-src']).to include('https://manifest-src.com')
 
       plugin.enabled = false
       expect(parse(policy)['script-src']).to_not include('https://from-plugin.com')
+      expect(parse(policy)['manifest-src']).to_not include('https://manifest-src.com')
 
       Discourse.plugins.delete plugin
     end

GitHub sha: 8336e732d375fe891d6f7e33011b243c9962c1b2

This commit appears in #13319 which was approved by Falco. It was merged by pmusaraj.