CVE-2023-38508 (PHP, published 2023-08-24T23:15Z)
Description: value: Tuleap is an open source suite to improve management of software developments and collaboration. In Tuleap Community Edition prior to version 14.11.99.28 and Tuleap Enterprise Edition prior to versions 14.10-6 and 14.11-3, the preview of an artifact link with a type does not respect the project, tracker and artifact level permissions. The issue occurs on the artifact view (not reproducible on the artifact modal). Users might get access to information they should not have access to. Only the title, status, assigned to and last update date fields as defined by the semantics are impacted. If those fields have strict permissions (e.g. the title is only visible to a specific user group) those permissions are still enforced. Tuleap Community Edition 14.11.99.28, Tuleap Enterprise Edition 14.10-6, and Tuleap Enterprise Edition 14.11-3 contain a fix for this issue.
Severity: nan (CVSS v3 base score: 4.3)
Weakness: CWE-862 \u2014 Missing Authorization
The product does not perform an authorization check when an actor attempts to access a resource or perform an action.
Repository: https://github.com/Enalean/tuleap
Files changed:
plugins/tracker/include/Tracker/FormElement/Field/ArtifactLink/Type/ArtifactInTypeTablePresenter.php
plugins/tracker/include/Tracker/FormElement/Field/ArtifactLink/Type/TypeTablePresenter.php
plugins/tracker/include/Tracker/FormElement/Tracker_FormElement_Field_ArtifactLink.php
Commit message: Fixes request #33608: Preview of a linked artifact with a type does not respect permissions

Change-Id: I94bab99f318a79e91f42b5fb67a6c2d45075ccba


Vulnerable code:
        $current_user       = \UserManager::instance()->getCurrentUser();
            $artifact               = $art_factory->getArtifactById($artifact_link->getArtifactId());
            $html .= $this->fetchTypeTables($artifact_links_to_render, $reverse_artifact_links);
    private function fetchTypeTables(ArtifactLinksToRender $artifact_links_to_render, $is_reverse_artifact_links)
                $this->appendTypeTable($request, $result, $is_reverse);
    private function appendTypeTable(Codendi_Request $request, array &$result, bool $is_reverse_artifact_links)
        $type_presenter        = $this->getTypePresenterFactory()->getFromShortname($type_shortname);
        $head_html             = '';
            $artifact = $art_factory->getArtifactById(trim($id));
            $are_links_deletable = $this->areLinksDeletable(
                $type_presenter,
                $is_reverse_artifact_links,
            );

            if (! is_null($artifact) && $artifact->getTracker()->isActive()) {
                $type_html .= $this->getTemplateRenderer()->renderToString(
                    'artifactlink-type-table-row',
                    new ArtifactInTypeTablePresenter(
                        $artifact,
                        $artifact_html_classes,
                        $this,
                        $are_links_deletable,
                    )
                );
                TypeTablePresenter::buildForHeader($type_presenter, $this, $are_links_deletable)

Fixed code:
        \PFUser $current_user,
        \PFUser $current_user,
            $artifact = $art_factory->getArtifactByIdUserCanView($current_user, $artifact_link->getArtifactId());
            if ($artifact === null) {
                continue;
            }
                $current_user,
        \PFUser $current_user,
            $current_user,
            $html .= $this->fetchTypeTables($current_user, $artifact_links_to_render, $reverse_artifact_links);
    private function fetchTypeTables(\PFUser $current_user, ArtifactLinksToRender $artifact_links_to_render, $is_reverse_artifact_links): string
                    $current_user,
                $this->appendTypeTable($current_user, $request, $result, $is_reverse);
    private function appendTypeTable(PFUser $current_user, Codendi_Request $request, array &$result, bool $is_reverse_artifact_links): void
        $type_presenter = $this->getTypePresenterFactory()->getFromShortname($type_shortname);
        if ($type_presenter === null) {
            return;
        }
        $are_links_deletable   = $this->areLinksDeletable(
            $type_presenter,
            $is_reverse_artifact_links,
        );
            $artifact = $art_factory->getArtifactByIdUserCanView($current_user, (int) trim($id));
            if ($artifact === null) {
                continue;

            $type_html .= $this->getTemplateRenderer()->renderToString(
                'artifactlink-type-table-row',
                new ArtifactInTypeTablePresenter(
                    $current_user,
                    $artifact,
                    $artifact_html_classes,
                    $this,
                    $are_links_deletable,
                )
            );
                TypeTablePresenter::buildForHeader($current_user, $type_presenter, $this, $are_links_deletable)