CVE-2023-32072 (PHP, published 2023-05-29T21:15Z)
Description: value: Tuleap is an open source tool for end to end traceability of application and system developments. Tuleap Community Edition prior to version 14.8.99.60 and Tuleap Enterprise edition prior to 14.8-3 and 14.7-7, the logs of the triggered Jenkins job URLs are not properly escaped. A malicious Git administrator can setup a malicious Jenkins hook to make a victim, also a Git administrator, execute uncontrolled code. Tuleap Community Edition 14.8.99.60, Tuleap Enterprise Edition 14.8-3, and Tuleap Enterprise Edition 14.7-7 contain a patch for this issue.
Severity: nan (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/Enalean/tuleap
Files changed:
plugins/hudson_git/include/HudsonGit/GitWebhooksSettingsEnhancer.php
plugins/hudson_git/include/HudsonGit/JenkinsWebhookPresenter.php
plugins/hudson_git/include/hudson_gitPlugin.php
Commit message: Fix request #31923 Broken link when more than 10 Jenkins jobs are triggered by one Jenkins hook

Given a Git repository that have a Jenkins webhook configured to trigger Git polling jobs,
and if there are more than 10 polling jobs triggered after a push, then there is a <x more>
returned by Jenkins after the 10th triggered job. This <x more> must not be clickable in the job list.

Change-Id: Ia8283f57c4352a85f65318a34980d028668ae95a


Vulnerable code:
                        $this->csrf
class JenkinsWebhookPresenter extends GenericWebhookPresenter
    public function __construct(GitRepository $repository, $url, array $hooklogs, CSRFSynchronizerToken $csrf)
    {
        $hp = Codendi_HTMLPurifier::instance();
                    $purfied_job_url       = $hp->purify($triggered_job_url);
                    $purified_information .= '<a href="' . $purfied_job_url . '">' . $purfied_job_url . '</a><br>';
                $purified_information .= $log->getStatusCode();
                self::getJenkinsServerFactory()

Fixed code:
use Codendi_HTMLPurifier;
use Tuleap\Sanitizer\URISanitizer;
        private readonly Codendi_HTMLPurifier $html_purifier,
        private readonly URISanitizer $uri_sanitizer,
                        $this->csrf,
                        $this->html_purifier,
                        $this->uri_sanitizer,
use Tuleap\Sanitizer\URISanitizer;
final class JenkinsWebhookPresenter extends GenericWebhookPresenter
    public function __construct(
        GitRepository $repository,
        string $url,
        array $hooklogs,
        CSRFSynchronizerToken $csrf,
        private readonly Codendi_HTMLPurifier $html_purifier,
        private readonly URISanitizer $uri_sanitizer,
    ) {
                    $sanitized_job_url = $this->uri_sanitizer->sanitizeForHTMLAttribute($triggered_job_url);
                    if ($sanitized_job_url !== '' && $triggered_job_url !== '') {
                        $purified_information .= '<a href="' . $this->html_purifier->purify($sanitized_job_url) . '">' . $this->html_purifier->purify($triggered_job_url) . '</a><br>';
                    } else {
                        $purified_information .= $this->html_purifier->purify($triggered_job_url);
                    }
                $purified_information .= $this->html_purifier->purify((string) $log->getStatusCode());
                self::getJenkinsServerFactory(),
                Codendi_HTMLPurifier::instance(),
                new \Tuleap\Sanitizer\URISanitizer(new Valid_HTTPURI()),