Allow to disable (dynamic) CDN loading of libraries in general

Created on 23 February 2023, almost 2 years ago

Problem/Motivation

At /admin/structure/webform/config/libraries you can enable / disable which extra libraries to use. Still it seems in some cases the libraries are loaded from CDN dynamically, even if unchecked?

In detail, I saw that https://unpkg.com/tippy.js@6.3.7/dist/tippy-bundle.umd.min.js was loaded on all our pages with webforms.
This is a dangerous risk with GDPR, as it's not allowed to load code from external sources without user consent! (As the IP is already considered private data which is then exposed to the CDN's - that's ridiculous, but we don't make the laws...). So we have to ensure something like that never happens.

If it was just a bug ( #3316667: Tippy.js is loaded via CDN even when disabled β†’ in detail) and disabled libraries should never be loaded from CDN by design, please close this issue. I'm not totally sure how Webform implements this, so I decided to create this issue.

Thanks :)

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

πŸ“Œ Task
Status

Active

Version

6.2

Component

Code

Created by

πŸ‡©πŸ‡ͺGermany Anybody Porta Westfalica

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

Comments & Activities

  • Issue created by @Anybody
  • πŸ‡©πŸ‡ͺGermany Anybody Porta Westfalica
  • πŸ‡ΊπŸ‡ΈUnited States jrockowitz Brooklyn, NY

    I think we need to make sure the disabled library is not loaded

  • Status changed to Postponed: needs info almost 2 years ago
  • πŸ‡ΊπŸ‡ΈUnited States jrockowitz Brooklyn, NY

    With the very latest 6.2.x-dev release if I uncheck all the external libraries, none of the libraries are loaded including Tippy.js.

    To kill CDN support the 'cdn' property needs to be removed from all the webform libraries via patch or alter hook.

  • πŸ‡ΊπŸ‡ΈUnited States jrockowitz Brooklyn, NY
  • Status changed to Active over 1 year ago
  • πŸ‡©πŸ‡ͺGermany Anybody Porta Westfalica

    Sorry @jrockowitz to reopen, but using 6.2.0-beta5 this issue still exists for popperjs and tippyjs, while no external library is enabled in the settings. See attached screenshot.

    And yes, I'm sure it comes from Webform. If I comment out the CDN lines, the issue is gone.

    libraries.popperjs:
      remote: https://github.com/floating-ui/floating-ui
      version: '2.11.6'
      license:
        name: MIT
        url: https://github.com/floating-ui/floating-ui/blob/v2.x/LICENSE.md
        gpl-compatible: true
      directory: popperjs
      # cdn:
      #   /libraries/popperjs/dist/umd/: https://unpkg.com/@popperjs/core@2.11.6/dist/umd/
      js:
        /libraries/popperjs/dist/umd/popper.js: {  }
    
    libraries.tippyjs:
      remote: https://github.com/atomiks/tippyjs
      version: '6.2.6'
      license:
        name: MIT
        url: https://github.com/atomiks/tippyjs/blob/master/LICENSE
        gpl-compatible: true
      directory: tippyjs
      # cdn:
      #   /libraries/tippyjs/dist/: https://unpkg.com/tippy.js@6.2.6/dist/
      js:
        /libraries/tippyjs/dist/tippy-bundle.umd.js: { }
      dependencies:
        - webform/libraries.popperjs

    Possibly related issues, which should (instead) be reopened or where the issue was re-introduced perhaps:
    #3199336: Tippy 6 is always loaded from the CDN even if there is a local copy, because webform_library_info_alter is not rewriting its directory from the 5 version to the 6 version β†’
    #3246508: [Drupal 9.x] Only require Tippy 6.x β†’
    πŸ› popper.js library missing in composer.libraries.json Fixed
    πŸ› Webform backend causes requests to third-party servers Fixed
    πŸ› popper.js library missing in composer.libraries.json Fixed

    all these were merged before beta5 date (Jan, 12th)

    Running drush webform:libraries:composer > DRUPAL_ROOT/composer.libraries.json results in:

    {
        "name": "drupal/webform",
        "description": "Enables the creation of webforms and questionnaires.",
        "type": "drupal-module",
        "license": "GPL-2.0-or-later",
        "minimum-stability": "dev",
        "homepage": "https://drupal.org/project/webform",
        "authors": [
            {
                "name": "Jacob Rockowitz (jrockowitz)",
                "homepage": "https://www.drupal.org/u/jrockowitz",
                "role": "Maintainer"
            },
            {
                "name": "Contributors",
                "homepage": "https://www.drupal.org/node/7404/committers",
                "role": "Contributor"
            }
        ],
        "support": {
            "issues": "https://www.drupal.org/project/issues/webform?version=8.x",
            "source": "https://git.drupalcode.org/project/webform",
            "docs": "https://www.drupal.org/docs/8/modules/webform",
            "forum": "https://drupal.stackexchange.com/questions/tagged/webform"
        },
        "require": {},
        "suggest": {
            "drupal/jquery_ui_checkboxradio": "Provides jQuery UI Checkboxradio library. Required by the Webform jQueryUI Buttons module. The Webform jQueryUI Buttons module is deprecated because jQueryUI is no longer maintained.",
            "drupal/jquery_ui_datepicker": "Provides jQuery UI Datepicker library. Required to support datepickers. The Webform jQueryUI Datepicker module is deprecated because jQueryUI is no longer maintained."
        },
        "repositories": {}
    }
    

    I also tried dev-6.2.x b54bb33 with no luck!

  • πŸ‡©πŸ‡ͺGermany Anybody Porta Westfalica
  • πŸ‡©πŸ‡ͺGermany Anybody Porta Westfalica

    Workaround, if anyone needs it for GDPR reasons or so:

     /**
      * Implements hook_library_info_alter().
      */
    function drowl_customer_library_info_alter(&$libraries, $extension) {
      // Kill webform CDN loading, see
      if ($extension == 'webform') {
        if(!empty($libraries)){
          foreach ($libraries as $key => $library) {
            if (!empty($libraries[$key]['cdn'])) {
              unset($libraries[$key]['cdn']);
            }
          }
        }
      }
    }
  • Status changed to Closed: won't fix over 1 year ago
  • πŸ‡ΊπŸ‡ΈUnited States jrockowitz Brooklyn, NY

    I think using custom code is acceptable or the snippet can be moved into a dedicated contributed module.

  • Status changed to Active 10 months ago
  • πŸ‡©πŸ‡°Denmark ressa Copenhagen

    Could something like the method used in Tagify work for Webform? It checks if a library is present, and uses that if it is. If it's not present, only then does it get the library from a CDN: https://git.drupalcode.org/project/tagify/-/blob/1.2.x/tagify.module

    Or is that what #8 does? If yes -- perhaps an MR could get created, and eventually committed?

  • πŸ‡©πŸ‡°Denmark ressa Copenhagen

    I just re-read the whole issue, and gained a better understanding of the problem.

    Perhaps the function in #8 could be considered to get added in Webform, as a global checkbox option?

    [x] Never load libraries from a CDN

  • πŸ‡©πŸ‡ͺGermany Anybody Porta Westfalica

    @ressa: Thanks, yes such a switch or any other global option to opt-in to CDN or being able to disable it would be fine. It's really dangerous for GDPR reasons, but I can see why developers outside the EU don't care that much.

  • πŸ‡©πŸ‡°Denmark ressa Copenhagen

    Thanks for sharing it in the first place @Anybody. And yes, GDPR is so far only a thing in EU, but with ~450 mio. people, it's not exactly a small portion of the world :)

    Also, you could argue that any effort made to respect user privacy is always good, looking at it from a moral point of view. You could even argue that user data protection and human rights largely overlap, as the author does in Data Protection and Human Rights: A Global Perspective.

    If you were to create an MR, I would be very much ready to test it.

  • πŸ‡ΊπŸ‡ΈUnited States jrockowitz Brooklyn, NY

    There could be a dedicated Webform GDR module that, when enabled, improves Webform GDR support.

  • πŸ‡ͺπŸ‡ΈSpain pcambra Asturies

    I've been using this technique on my js modules: https://git.drupalcode.org/project/inspire_tree/-/blob/1.x/inspire_tree....

    This works so you declare the libraries with their CDN version but then if they exist on libraries, it uses that instead, would something like this be acceptable? no config and no additional code.

  • πŸ‡©πŸ‡°Denmark ressa Copenhagen

    That's how Webform already works, as far as I understand this sentence:

    [...] It is recommended that these libraries are installed in your Drupal installation's /libraries or /web/libraries directory. If these libraries are not installed, they will be automatically loaded from a CDN.

    https://www.drupal.org/docs/contributed-modules/webform/webform-libraries β†’

    This issue is about blocking all CDN-usage, and I have updated the Issue Summary "Proposed resolution" to make it clearer.

  • @ressa convinced me in the forum β†’ to give this module a second try. After finding a few bugs and another GDPR violation ( πŸ› YouTube thumbnails are embedded on help page (performance, low bandwidth, GDPR compliance) Closed: works as designed ), I started to set some sane defaults via contrib module. This module acts as my learning module right now and it is hosted outside of drupal.org, but maybe it's interesting for others how I reduced the risk of GDPR violations.

    The module: rljutils

    The interesting bits (commits):

    More fixes and overrides might follow soon...

    Side note: I added the webform module to the list of problematic modules for GDPR compliance: #3075653-26: Drupal modules that may require extra work to be GDPR compliant β†’

  • πŸ‡©πŸ‡ͺGermany Anybody Porta Westfalica

    Thank you very much for your work @raffaelj

    I still think it would be much better (for people, webform and privacy) to solve this in webform itself and use opt-in instead of opt-out by default, but that's just my 2 cents. :)

  • πŸ‡©πŸ‡°Denmark ressa Copenhagen

    It looks good @raffaelj, but I do agree with @Anybody that it would be better to add directly in Webform, if only as a proof of concept, for a start.

    I have created a branch in this issue, ready for a "Block all CDN's"-feature, and maybe also your "Disable ads and third party content" feature :)

  • πŸ‡©πŸ‡ͺGermany Anybody Porta Westfalica

    @ressa: Clarification: "Best" from my perspective would be compliance by design, and opt-in for all other cases.

  • πŸ‡©πŸ‡°Denmark ressa Copenhagen

    Thanks for sharing @Anyone, so the wording under the settings could instead be something like this, and disabled by default?

    [ ] Allow loading libraries from a CDN

  • @ressa, @anybody: I agree, that these changes should be part of the webform module, but I don't see this coming:

    1. From looking at the history of the issue queue, I deduced that the core maintainer/owner @jrockowitz doesn't see loading third party code (from venture capital backed ad companies) as a problem.
    2. Multiple GDPR related issues were closed as "won't fix" or as "works as designed".
    3. The config form to opt-out is hidden in a sub tab. While navigating to this page, the third party providers are already contacted. Also that form has bugs, which makes it appear unimportant ( πŸ› Pressing Enter key on config/advanced form causes repair instead of save Active ).
    4. Disabling CDN usage broke over and over again in the past (e. g.: #3199336: Tippy 6 is always loaded from the CDN even if there is a local copy, because webform_library_info_alter is not rewriting its directory from the 5 version to the 6 version β†’ , #3254856: CKEditor Codemirror is still loaded from the CDN even if the library exists in /libraries. β†’ , #3316667: Tippy.js is loaded via CDN even when disabled β†’ ).
    5. To be honest: I don't care about GDPR. But I care about privacy and consent. Personally I can protect myself by using Firefox addons like uBlock Origin and LocalCDN. When running code on client projects it's another story. Now I have to protect the privacy of my clients and of their website visitors. And my clients have to care about GDPR. Using code from people, who don't value consent means, that I have to be very careful with every update. Otherwise some new code with GDPR violations could sneak in.
    6. Disabling CDN usage by default would be a breaking change. It would involve a config change to use included_libraries instead of excluded_libraries and the CDN keys would move from webform.libraries.yml to a preprocess or alter hook.
    7. The whole module feels a bit bloated: too much JavaScript, 1346 lines of code in webform.libraries.yml, thousands of files (to be fair, the biggest footprint are the tests folders)

    From there I concluded, that it's not worth investing my time in improving this module. It just happens to be the de facto standard form builder module and I have to use it until an alternative exists. Because I can't trust code from developers who don't value consent, I decided to reduce the risks with config overrides via contrib module.

    If there was a clear statement from @jrockowitz, that privacy has a high value, I might come back and could help fixing these issues.

  • I digged a bit deeper and wrote a module to disable libraries in general. As a bonus feature it disables the CDN usage of webform, too. Feel free to check it out: https://www.drupal.org/project/disable_libraries/ β†’

    @Anybody Your workaround in #8 re-introduced "No such file or directory in _locale_parse_js_file()" warnings in multilingual setups - see: πŸ› disabling CDN causes php warnings with webform in multilingual setup Fixed . I published a different method in my new disable_libraries module.

  • πŸ‡©πŸ‡°Denmark ressa Copenhagen

    Great work @raffaelj, thanks!

  • Status changed to Closed: won't fix 28 days ago
Production build 0.71.5 2024