General strategy for misc. sources?

Created on 30 August 2024, 7 months ago
Updated 20 September 2024, 7 months ago

I've been researching our current Content Security Policy (CSP) strategy, and I'm curious about the best practices for handling common sources that need to be included in a CSP. Recently, I've started to move away from adding sources directly through the CSP UI, preferring instead to implement them via an event subscriber. I'm also exploring the new #attached option—thanks for that feature!

Using the event subscriber, I can add comments next to each source, documenting why it's there and whether it's still relevant. This approach should help me understand the policy better when revisiting it in the future. Currently, I'm developing a custom "CSP Starter" module for my agency. This module will provide a starting point with the event subscriber and include common sources.

I'm also interested in how we can make the entire Drupal CSP ecosystem smarter. For example, both Pantheon and Acquia integrate with New Relic, which automatically adds the New Relic metrics tracking scripts from:

  • js-agent.newrelic.com
  • bam.nr-data.net
  • bam-cell.nr-data.net

I've found that I can detect whether these scripts are being added by checking the newrelic.browser_monitoring.auto_instrument config in PHP. Here's the code snippet I use:

    // Check to see if New Relic monitoring is enabled, and add the policies to allow the insights scripts.
    // https://docs.newrelic.com/docs/apm/agents/php-agent/configuration/php-agent-configuration/#inivar-autorum
    $nrAutoInstrument = ini_get('newrelic.browser_monitoring.auto_instrument');
    if ($nrAutoInstrument && $nrAutoInstrument === TRUE) {
      $newRelicScripts = [
        'js-agent.newrelic.com',
        'bam.nr-data.net',
        'bam-cell.nr-data.net',
      ];
      $policies['script-src'] = array_merge($policies['script-src'], $newRelicScripts);
    }

I imagine others would be interested in this. Is this an update to contribute to this module? Should I think about open sourcing my "CSP Starter" module with these types of things? I'm not sure the starter module I'm working on would be too great for that since part of the approach I'm taking there is to just have people clone it, then commit it to their project to customize at will. The examples are commented out, and they can un-comment what they need. I'd like to be smart about adding things like the New Relic example, but every single thing just seems so bespoke. I took an inventory of sources across several of my projects, and here are a few common sources. I also have several others that are less common, which I excluded.


    $policies = [
      /*
       * In this basic example, everything is added to the "default-src" directive. But developers are encouraged to
       * move these around to other directive types for what works best for their current site. This is just a starter
       * list. Uncomment the directives you need.
       */
      'default-src' => [


        /*
         * Google Tag Manager,
         * Dealing with the complexity of loading external scripts via other javascript, and weighing the need to use a
         * nonce, which would invalidate existing directives that use "unsafe-inline", will probably recommend this
         * being in the standard CSP.
         * https://www.drupal.org/project/google_tag/issues/3203811
         */
        //'www.googletagmanager.com',

        /*
         * Gov delivery scripts/pop-ups. May be desired on any government website
         */
        //'public.govdelivery.com',

        /*
         * US Gov digital analytics program scripts.
         * https://digital.gov/guides/dap/
         */
        //'dap.digitalgov.gov',

        /*
         * "Cleardot" tracking pixel? Also assets for the Youtube player
         */
        //'www.google.com',

        /*
         * Fonts and other assets from Google.
         * You should move these to inside the theme. as linking directly to google fonts may not be GDPR compliant
         */
        //'www.gstatic.com',

        /*
         * Fonts and other assets from Google.
         * You should move these to inside the theme. as linking directly to google fonts may not be GDPR compliant
         */
        //'fonts.googleapis.com',

        /*
         * Youtube images. Can these be added via the new #attached values in the media elements?
         */
        //'s.ytimg.com',
        //'www.youtube.com',


        /*
         * Facebook tracking
         */
        //'connect.facebook.net',
        //'www.facebook.com',

        /*
         * Cloudflare metric tracking. TODO: Can we sniff the request headers to tell if this came from CloudFlare?
         */
        //'static.cloudflareinsights.com',
      ],

      'img-src' => [
        /*
         * Inline image data is an extremely common method for embedding images.
         */
        'data:',
      ],


My other thought is that if there is a service here, and a corresponding Drupal module, perhaps we should raise an issue in that module to add a CSP event subscriber. Only problmen might be that people may be using these sources, without necessarily using a related Drupal.org module. Anyway, I'm interested to hear your thoughts on this.

💬 Support request
Status

Closed: outdated

Version

2.0

Component

Code

Created by

🇺🇸United States bburg Washington D.C.

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @bburg
  • 🇨🇦Canada gapple

    I'm not sure about best practices, but I do have thoughts :)

    Ideally, other modules use CSP's APIs so that site builders, or anyone else, just needs to enable the module and the site's policy will be updated as needed for the module's functionality to work. CSP handles any adjustments for core, but shouldn't take on the responsibility for every other contrib module or hosting platform.
    It's definitely a challenge that every site may need a pretty bespoke policy for its functionality (and the dev/support team's capacity for monitoring and managing its strictness).

    A lot of cases for scripts and styles are handled transparently by parsing library info, but more complex cases or non script/style sources will currently need to implement an alter subscriber (e.g. Google Tag Manager / Google Analytics, which uses a loader script and can use a nonce, and also needs to modify img-src and connect-src [ Merge Request pending on google_tag Support Content Security Policy nonce Active ]; or Google Fonts, where a local CSS file needs an external domain included in font-src).
    The render attached info should enable supporting some cases in a more direct way than an alter subscriber, and some more cases for libraries would be supported if/when Enable specifying additional directives in library definitions Active is implemented.

    If someone's implementing a custom module instead of a public contrib module, then I'm not particularly worried. I assume by them implementing a CSP policy they'll know to make necessary policy modifications, and they can use the contrib module's subscriber as a reference.

    There's a possibility of another contrib module that extends CSP's config form with a new tab that has checkboxes to enable policy modifications for additional services that are used without a module, but that could get fairly long and messy for a lot of services that any particular site is not going to use.

    There was a GitHub repo some time ago that documented the directives required for a lot of different services - I'll have to search if it still exists and is up to date. If there isn't a good reference somewhere else, a page could be added to the module's documentation for services commonly used on Drupal sites, and then site builders could choose to apply the changes in their configuration or a custom subscriber according to their preference (and anyone can contribute new services or changes to the documentation).

    ----

    Where the policy values are static and global (and the config form could be disabled so it's not used), adding them using config overrides in settings.php would also be an option, and would make it clearer that the base value is enabled too (so, e.g., img-src data: isn't enabled without 'self' when uncommented).

  • Status changed to Closed: outdated 7 months ago
Production build 0.71.5 2024