CVE-2022-31128 (PHP, published 2022-08-01T17:15Z)
Description: value: Tuleap is a Free & Open Source Suite to improve management of software developments and collaboration. In affected versions Tuleap does not properly verify permissions when creating branches with the REST API in Git repositories using the fine grained permissions. Users can create branches via the REST endpoint `POST git/:id/branches` regardless of the permissions set on the repository. This issue has been fixed in version 13.10.99.82 Tuleap Community Edition as well as in version 13.10-3 of Tuleap Enterprise Edition. Users are advised to upgrade. There are no known workarounds for this issue.
Severity: nan (CVSS v3 base score: 5.4)
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/git/include/REST/v1/Branch/BranchCreator.php
plugins/git/include/REST/v1/RepositoryResource.class.php
plugins/git/tests/unit/REST/v1/Branch/BranchCreatorTest.php
Commit message: fix: Fine grained permissions must be well handled in POST git/:id/branches

This fixes request #27538 Fine grained permissions are not checked when creating a branch with REST API

The fine grained permissions were not taken into account in the previous
checks.

Change-Id: I1fa72ab34e4f41d5ea3ec9dd21e990ce330d780f


Vulnerable code:
use Git;
    public function __construct(private \Git_Exec $git_exec, private BranchCreationExecutor $branch_creation_executor)
    {
        if (
            ! $user->hasPermission(Git::PERM_WRITE, $repository->getId(), $repository->getProjectId())
            && ! $user->hasPermission(Git::PERM_WPLUS, $repository->getId(), $repository->getProjectId())
        ) {
            throw new RestException(
                403,
                "User cannot update the content of the repository"
            );
        }

        (new BranchCreator(new Git_Exec($repository->getFullPath(), $repository->getFullPath()), new BranchCreationExecutor()))->createBranch(
use Git;
            $this->branch_creation_executor
        $this->expectExceptionMessage("User cannot update the content of the repository");
        $user = $this->createMock(\PFUser::class);
        $user->method('hasPermission')->willReturnMap([
            [Git::PERM_WRITE, self::REPO_ID, self::PROJECT_ID, true],
            [Git::PERM_WPLUS, self::REPO_ID, self::PROJECT_ID, true],
        ]);
        $user = $this->createMock(\PFUser::class);
        $user->method('hasPermission')->willReturnMap([
            [Git::PERM_WRITE, self::REPO_ID, self::PROJECT_ID, false],
            [Git::PERM_WPLUS, self::REPO_ID, self::PROJECT_ID, false],
        ]);

Fixed code:
use Tuleap\Git\Permissions\AccessControlVerifier;
    public function __construct(
        private \Git_Exec $git_exec,
        private BranchCreationExecutor $branch_creation_executor,
        private AccessControlVerifier $access_control_verifier,
    ) {
        if (! $this->access_control_verifier->canWrite($user, $repository, self::BRANCH_PREFIX . $representation->branch_name)) {
            throw new RestException(
                403,
                sprintf(
                    "You are not allowed to create the branch %s in repository %s",
                    $representation->branch_name,
                    $repository->getName()
                )
            );
        }

use Tuleap\Git\Permissions\AccessControlVerifier;
        $branch_creator = new BranchCreator(
            new Git_Exec($repository->getFullPath(), $repository->getFullPath()),
            new BranchCreationExecutor(),
            new AccessControlVerifier(
                new FineGrainedRetriever(
                    new FineGrainedDao(),
                ),
                new \System_Command(),
            )
        );

        $branch_creator->createBranch(
use Tuleap\Git\Permissions\AccessControlVerifier;
use Tuleap\Test\Builders\UserTestBuilder;
    /**
     * @var AccessControlVerifier&\PHPUnit\Framework\MockObject\MockObject
     */
    private $access_control_verifier;
        $this->access_control_verifier  = $this->createMock(AccessControlVerifier::class);
            $this->branch_creation_executor,
            $this->access_control_verifier
        $this->expectExceptionMessage("You are not allowed to create the branch new_branch in repository repo01");
        $user = UserTestBuilder::anActiveUser()->build();
        $this->access_control_verifier->method('canWrite')->willReturn(true);
        $user = UserTestBuilder::anActiveUser()->build();
        $this->access_control_verifier->method('canWrite')->willReturn(false);