RssResponseCdata filtering out common html tags

Created on 6 January 2025, 15 days ago

Problem/Motivation

After upgrading to Drupal 10.4.0, I found that our RSS feed doesn't render div, img, and style tags. Doing so breaks our RSS email structurally (div) and visually (img and style).

Proposed resolution

Include those tags in the list of acceptable tags when filtering the RSS item description in the Xss::filter list in the wrapDescriptionCdata() function in Drupal\Core\EventSubscriber\RssResponseCdata.

We can extend the class and register our own service that overrides the function, but I would think that those tags would be common to include? Maybe the style tag isn't as necessary as the others since we can style it on the side that is pulling in the RSS feed.

πŸ› Bug report
Status

Active

Version

10.4 ✨

Component

views.module

Created by

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

Comments & Activities

  • Issue created by @wlofgren
  • πŸ‡¬πŸ‡§United Kingdom opsdemon

    I'm having the same issue. Since 10.4.0 all styles and images are getting stripped from our newsletter RSS feed and we ended up downgrading to 10.3 to get it working again.

    Is there any workaround for this?

  • It's obviously a temporary measure, but you could apply the reverse of the feature patch.

    git diff ebc8e0639e0e12391087d9abe0ad8eca0034d1ea ebc8e0639e0e12391087d9abe0ad8eca0034d1ea~1 >patches/3497758.patch

    I've attached that patch.

  • πŸ‡¬πŸ‡§United Kingdom opsdemon

    After some more investigation I found a workaround for the issue here: views_rss/issues/3079683#comment-15110037 πŸ’¬ Add CDATA tags at description field on D8 Closed: duplicate

    Applying the fix to the .theme file fixed the issue and the newsletter formatting looks ok now.

  • I ended up extending the RssResponseCdata class and register a service that decorates it in my module.

    module_name.services.yml

    services:
      module_name.response_filter.rss.cdata:
        class: Drupal\module_name\EventSubscriber\RssResponseCdata
        decorates: response_filter.rss.cdata
        decoration_priority: 10
    

    src/EventSubscriber/RssResponseCdata.php

    <?php
    
    namespace Drupal\module_name\EventSubscriber;
    
    use Drupal\Component\Utility\Xss;
    use Drupal\Core\EventSubscriber\RssResponseCdata as PrimaryRssResponseCdata;
    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    use Symfony\Component\HttpKernel\Event\ResponseEvent;
    use Symfony\Component\HttpKernel\KernelEvents;
    
    /**
     * Subscribes to wrap RSS descriptions in CDATA.
     */
    class RssResponseCdata extends PrimaryRssResponseCdata implements EventSubscriberInterface {
    
      /**
       * Converts description node to CDATA RSS markup.
       *
       * @param string $rss_markup
       *   The RSS markup to update.
       *
       * @return string|false
       *   The updated RSS XML or FALSE if there is an error saving the xml.
       */
      protected function wrapDescriptionCdata(string $rss_markup): string|false {
        $rss_dom = new \DOMDocument();
    
        // Load the RSS, if there are parsing errors, abort and return the unchanged
        // markup.
        $previous_value = libxml_use_internal_errors(TRUE);
        $rss_dom->loadXML($rss_markup);
        $errors = libxml_get_errors();
        libxml_use_internal_errors($previous_value);
        if ($errors) {
          return $rss_markup;
        }
    
        foreach ($rss_dom->getElementsByTagName('item') as $item) {
          foreach ($item->getElementsByTagName('description') as $node) {
            $html_markup = $node->nodeValue;
            if (!empty($html_markup)) {
              $tag_list = [
                'a', 'abbr', 'acronym', 'address',
                'b', 'bdo', 'big', 'blockquote', 'br',
                'caption', 'cite', 'code', 'col', 'colgroup',
                'dd', 'del', 'dfn', 'div', 'dl', 'dt', 'em',
                'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr',
                'i', 'img', 'ins', 'kbd', 'li', 'ol', 'p', 'pre', 'q',
                'samp', 'small', 'span', 'strong', 'sub', 'sup',
                'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'
              ];
              $html_markup = Xss::filter($html_markup, $tag_list);
              $new_node = $rss_dom->createCDATASection($html_markup);
              $node->replaceChild($new_node, $node->firstChild);
            }
          }
        }
    
        return $rss_dom->saveXML();
      }
    
    }
    
    
  • πŸ‡ΊπŸ‡ΈUnited States nicxvan

    You can also use the module posted at the end of the parent issue.

    It's easy to override, but as you can imagine we couldn't allow all html by default for security.

    At least we get valid rss feeds now, and if you need more you can decorate or override.

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    I too am getting hit by this on my blog πŸ˜… This explains why mysteriously I couldn't get feeds to work correctly after migrating from Drupal 7 to 10!

    The change record β†’ states:

    […] add the CDATA directive and provide XSS Filtering. Since this can be user entered data we use strict filtering.

    … but in my case, this is not data entered by an untrusted user. And isn't that quite often the case? It's content filtered through a text format, so any images that appear are explicitly allowed by the text format.

    AFAICT this was not considered in πŸ› Use CDATA in XML RSS Feeds Fixed 🫣

    How often are RSS feeds created that expose data from untrusted user input (e.g. a feed of comments) vs that what is the very purpose of the site (blog, photos, products …)?

  • πŸ‡ΊπŸ‡ΈUnited States nicxvan

    It was considered, initially I wanted to use the admin filter and @alexpott recommended a more strict filter since users can override it.

    I'd be happy changing the core if it passes security muster or we can release a module that overrides it like referenced so it's more secure in core and more eyes open contrib if you want more permissive.

Production build 0.71.5 2024