CVE-2024-39902 (TypeScript, published 2024-07-22T14:15Z)
Description: value: Tuleap is an open source suite to improve management of software developments and collaboration. Prior to Tuleap Community Edition 15.10.99.128 and Tuleap Enterprise Edition 15.10-6 and 15.9-8, the checkbox "Apply same permissions to all sub-items of this folder" in the document manager permissions modal is not taken into account and always considered as unchecked. In situations where the permissions are being restricted some users might still keep, incorrectly, the possibility to edit or manage items. Only change made via the web UI are affected, changes directly made via the REST API are not impacted. This vulnerability is fixed in Tuleap Community Edition 15.10.99.128 and Tuleap Enterprise Edition 15.10-6 and 15.9-8.
Severity: nan (CVSS v3 base score: )
Weakness: NVD-CWE-noinfo \u2014 Insufficient Information
There is insufficient information about the issue to classify it; details are unkown or unspecified.
Repository: https://github.com/Enalean/tuleap
Files changed:
plugins/document/scripts/document/components/Folder/Permissions/PermissionsUpdateFolderSubItems.test.ts
plugins/document/scripts/document/components/Folder/Permissions/PermissionsUpdateFolderSubItems.vue
plugins/document/scripts/document/components/Folder/Permissions/PermissionsUpdateModal.test.js
plugins/document/scripts/document/components/Folder/Permissions/PermissionsUpdateModal.vue
plugins/document/scripts/document/helpers/emitter.ts
Commit message: fix: Recursive permissions to document manager folder are not properly applied

Closes request #38675 Recursive permissions to document manager folder are not properly applied

How to test:
- Pick up a folder containing some folders and documents
- Open its permissions modal
- Set some permissions and click "Apply permissions to all sub-items"
- Submit
--> The permissions have been set on the current folder and all its
descendants.

Change-Id: Id10c3eb04677f21cb4b2ec237622022e84491e1e


Vulnerable code:
            <input type="checkbox" v-bind:value="props.value" v-on:input="onInput" />
const emit = defineEmits<{
    (e: "input", value: string): void;
}>();

        emit("input", event_target.value);
                <permissions-update-folder-sub-items
                    v-bind:item="item"
                    v-model="updated_permissions.apply_permissions_on_children"
                />

Fixed code:
import emitter from "../../../helpers/emitter";

    it.each([
        ["checked", true],
        ["unchecked", false],
    ])(
        'When the checkbox is %s, then it should emit a "update-apply-permissions-on-children" event containing the checkbox state.',
        (state, is_checked) => {
            const emit = jest.spyOn(emitter, "emit");
            const wrapper = getWrapper({ type: TYPE_FOLDER } as Folder);
            const checkbox = wrapper.find<HTMLInputElement>(
                "[data-test=checkbox-apply-permissions-on-children]",
            );

            checkbox.setValue(is_checked);
            checkbox.trigger("input");
            expect(emit).toHaveBeenCalledWith("update-apply-permissions-on-children", {
                do_permissions_apply_on_children: is_checked,
            });
        },
    );
            <input
                type="checkbox"
                v-on:input="onInput"
                data-test="checkbox-apply-permissions-on-children"
            />
import emitter from "../../../helpers/emitter";
        emitter.emit("update-apply-permissions-on-children", {
            do_permissions_apply_on_children: event_target.checked,
        });

    it('When an event "update-apply-permissions-on-children" is received, then it should update do_permissions_apply_on_children', () => {
        const item = {
            id: 104,
            title: "My item",
            permissions_for_groups: {
                can_read: [],
                can_write: [],
                can_manage: [],
            },
        };

        const wrapper = factory({ item });

        wrapper.setData({
            updated_permissions: {
                ...item.permissions_for_groups,
                apply_permissions_on_children: false,
            },
        });

        emitter.emit("update-apply-permissions-on-children", {
            do_permissions_apply_on_children: true,
        });

        expect(wrapper.vm.updated_permissions).toStrictEqual({
            ...item.permissions_for_groups,
            apply_permissions_on_children: true,
        });
    });
                <permissions-update-folder-sub-items v-bind:item="item" />
        emitter.on("update-apply-permissions-on-children", this.setApplyPermissionsOnChildren);

        setApplyPermissionsOnChildren(event) {
            this.updated_permissions = {
                ...this.updated_permissions,
                apply_permissions_on_children: event.do_permissions_apply_on_children,
            };
        },
export type UpdateApplyPermissionsOnChildren = {
    do_permissions_apply_on_children: boolean;
};

    "update-apply-permissions-on-children": UpdateApplyPermissionsOnChildren;