CVE-2021-41261 (PHP, published 2021-12-16T19:15Z)
Description: value: Galette is a membership management web application built for non profit organizations and released under GPLv3. Versions prior to 0.9.6 are subject to stored cross site scripting attacks via the preferences footer. The preference footer can only be altered by a site admin. This issue has been resolved in the 0.9.6 release and all users are advised to upgrade. There are no known workarounds.
Severity: LOW (CVSS v3 base score: 4.8)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/galette/galette
Files changed:
galette/composer.json
galette/composer.lock
galette/lib/Galette/Controllers/Crud/PaymentTypeController.php
galette/lib/Galette/Core/Preferences.php
galette/lib/Galette/Entity/Entitled.php
galette/lib/Galette/Entity/Title.php
galette/lib/Galette/Entity/Transaction.php
galette/templates/default/gestion_intitule_content.tpl
galette/templates/default/gestion_titres.tpl
galette/templates/default/gestion_transactions.tpl
Commit message: Fix XSS, prevent their storage

Use HTML purifier lib to sanitize preferences footer


Vulnerable code:
        "symfony/polyfill-php80": "^1.23"
    "content-hash": "abdb30cee5eeb0dad05c159a1c10880d",
 * Copyright © 2019-2020 The Galette Team
 * @copyright 2019-2020 The Galette Team
 * @copyright 2019-2020 The Galette Team
                        $ptype->name,
                        $ptype->name,
                        $ptype->name,
                        $ptype->name,
            'short_label'   => $this->short,
            'long_label'    => $this->long
                            $this->_description = $value;
                            {_T string="%s field" pattern="/%s/" replace=$entry.name}
                        <span class="sr-only">{_T string="Edit '%s' field" pattern="/%s/" replace=$entry.name}</span>
                        <span class="sr-only">{_T string="Delete '%s' field" pattern="/%s/" replace=$entry.name}</span>
                                        {_T string="%s title" pattern="/%s/" replace=$title->short}
                            <td class="left" data-title="{_T string="Short form"}">{$title->short}</td>
                            <td class="left" data-title="{_T string="Long form"}">{$title->long}</td>
                                    <span class="sr-only">{_T string="Edit '%s' title" pattern="/%s/" replace=$title->short}</span>
                                    <span class="sr-only">{_T string="Delete '%s' title" pattern="/%s/" replace=$title->short}</span>
                    <td class="{$cclass} nowrap" data-title="{_T string="Description"}">{$transaction->description}</td>

Fixed code:
        "symfony/polyfill-php80": "^1.23",
        "ezyang/htmlpurifier": "^4.13"
    "content-hash": "47d56d47701d9038105bd93cf3b44a02",
        {
            "name": "ezyang/htmlpurifier",
            "version": "v4.13.0",
            "source": {
                "type": "git",
                "url": "https://github.com/ezyang/htmlpurifier.git",
                "reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
                "reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
                "shasum": ""
            },
            "require": {
                "php": ">=5.2"
            },
            "require-dev": {
                "simpletest/simpletest": "dev-master#72de02a7b80c6bb8864ef9bf66d41d2f58f826bd"
            },
            "type": "library",
            "autoload": {
                "psr-0": {
                    "HTMLPurifier": "library/"
                },
                "files": [
                    "library/HTMLPurifier.composer.php"
                ],
                "exclude-from-classmap": [
                    "/library/HTMLPurifier/Language/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "LGPL-2.1-or-later"
            ],
            "authors": [
                {
                    "name": "Edward Z. Yang",
                    "email": "admin@htmlpurifier.org",
                    "homepage": "http://ezyang.com"
                }
            ],
            "description": "Standards compliant HTML filter written in PHP",
            "homepage": "http://htmlpurifier.org/",
            "keywords": [
                "html"
            ],
            "support": {
                "issues": "https://github.com/ezyang/htmlpurifier/issues",
                "source": "https://github.com/ezyang/htmlpurifier/tree/master"
            },
            "time": "2020-06-29T00:56:53+00:00"
        },
 * Copyright © 2019-2021 The Galette Team
 * @copyright 2019-2021 The Galette Team
 * @copyright 2019-2021 The Galette Team
                        $ptype->getName(),
                        $ptype->getName(),
                        $ptype->getName(),
                        $ptype->getName(),
            case 'pref_footer':
                $value = $this->cleanHtmlValue($value);
                break;
            } elseif ($name == 'pref_footer') {
                return $this->cleanHtmlValue($this->prefs[$name]);

    /**
     * Purify HTML value
     *
     * @param string $value Value to clean
     *
     * @return string
     */
    public function cleanHtmlValue(string $value): string
    {
        $config = \HTMLPurifier_Config::createDefault();
        $config->set('Cache.SerializerPath', GALETTE_CACHE_DIR);
        $purifier = new \HTMLPurifier($config);
        return $purifier->purify($value);
    }
        $label = strip_tags($label);
        $label = strip_tags($label);
            'short_label'   => strip_tags($this->short),
            'long_label'    => strip_tags($this->long)
                            $this->_description = strip_tags($value);
                            {_T string="%s field" pattern="/%s/" replace=$entry.name|escape}
                        <span class="sr-only">{_T string="Edit '%s' field" pattern="/%s/" replace=$entry.name|escape}</span>
                        <span class="sr-only">{_T string="Delete '%s' field" pattern="/%s/" replace=$entry.name|escape}</span>
                                        {_T string="%s title" pattern="/%s/" replace=$title->short|escape}
                            <td class="left" data-title="{_T string="Short form"}">{$title->short|escape}</td>
                            <td class="left" data-title="{_T string="Long form"}">{$title->long|escape}</td>
                                    <span class="sr-only">{_T string="Edit '%s' title" pattern="/%s/" replace=$title->short|escape}</span>
                                    <span class="sr-only">{_T string="Delete '%s' title" pattern="/%s/" replace=$title->short|escape}</span>
                    <td class="{$cclass} nowrap" data-title="{_T string="Description"}">{$transaction->description|escape}</td>