Adding CSP header by merging headers

I am trying to create a vary basic .rb plugin (based on the now obsolete in chrome) discourse-allowall which will merge the CSP header to the default ones but cant get it to work.

The below does not seem to do it.

Rails.application.config.action_dispatch.default_headers.merge!({'Content-Security-Policy' => "frame-ancestors 'http://mylocal.com.localhost'"})

I literally have 0 experience with ruby so need to know:

  1. If thats possible
  2. The correct syntax for defining the above header and merging it with the default ones

NOTE: End goal is to allow for the application to be frameable by 2 specific domains.

To achieve your goal of modifying the Content Security Policy (CSP) headers in Discourse using a basic plugin, here’s how you can approach it step by step:

Key Points

  1. Is it possible? Yes, it’s possible. Discourse plugins can extend and modify Rails configuration, including headers.
  2. Correct syntax and merging headers: You’ll need to hook into Discourse’s middleware and correctly append the new CSP directive while preserving existing ones.

Below is an example of how you can create a plugin to allow the application to be framed by two specific domains.


Plugin Implementation

  1. Create the Plugin Folder Structure In your Discourse installation, create a folder for your plugin under:
/plugins/discourse-custom-csp

Inside this folder, create the following files:

  • plugin.rb
  • config/settings.yml (optional if you want to add settings)
  1. **Edit plugin.rb**Add the following code to define your plugin:
# plugins/discourse-custom-csp/plugin.rb
# frozen_string_literal: true

# Plugin metadata
# Replace `discourse-custom-csp` with the name of your plugin
# Ensure `plugin.rb` is the main file to be loaded.

PLUGIN_NAME ||= 'discourse-custom-csp'

enabled_site_setting :enable_custom_csp

after_initialize do
  # Use Rails middleware to modify headers
  Rails.application.config.action_dispatch.default_headers.merge!({
    'Content-Security-Policy' => "frame-ancestors 'self' http://mylocal.com.localhost https://another-allowed-domain.com;"
  })
end
  1. Syntax Explanation
  • merge! is used to append your custom CSP header to the default headers.
  • The CSP directive frame-ancestors controls which domains are allowed to embed the Discourse site in an iframe.
  • 'self' ensures that Discourse still functions normally while allowing the specified domains.
  1. Restart Your Discourse Application After creating the plugin, restart your Discourse server:
./launcher restart app

Testing the Plugin

  1. Check Headers Use browser developer tools or curl to verify that the Content-Security-Policy header includes your changes:
curl -I http://your-discourse-instance
  1. Validate CSP Make sure your application can now be framed by the specified domains. Test this by embedding your Discourse instance in an iframe from the allowed domains.

Notes:

  1. Be Cautious with CSP: Modifying the CSP header can introduce security vulnerabilities. Only allow trusted domains.
  2. Adding Plugin Settings (Optional): If you want to allow administrators to manage the domains, you can add a setting in config/settings.yml and dynamically generate the CSP value in plugin.rb.

Let me know if you need further clarification or additional features!