nextcloud / nextcloud/server

[Bug]: PR #54814 Incomplete fix allows to move shares into subdirectories

Open
#56,761 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

0. Needs triage 30-feedback bug
Dominant language
PHP
Stars
36.9k
Forks
5.2k
Avg merge
2d 3h
Merged PRs (30d)
713

Description

⚠️ This issue respects the following points: ⚠️
Bug description

The permission validation logic in PR #54814 contains a flaw. While move/copy operations to the root directory of shared folders are correctly denied, operations targeting subdirectories bypass validation and are improperly allowed.

Steps to reproduce
  1. User A creates folder "/share" and shares it with User B (sharing permission disabled, only edit and delete permissions enabled)
  2. User A uploads file "/share/test.txt"
  3. User B creates folder "/re-share" and shares it with User C (all permissions enabled)
  4. User B attempts operations:
    • Move/copy to "/re-share/" → Correctly rejected (403 error)
    • Move/copy to "/re-share/subfolder/" → Incorrectly allowed
Expected behavior

Both operations should be denied since User B lacks share permissions on the source folder "/share".

Nextcloud Server version

30

Operating system

None

PHP engine version

None

Web server

None

Database engine version

None

Is this bug present after an update or on a fresh install?

None

Are you using the Nextcloud Server Encryption module?

None

What user-backends are you using?
  • Default user-backend (database)
  • LDAP/ Active Directory
  • SSO - SAML
  • Other
Configuration report

List of activated Apps

Nextcloud Signing status

Nextcloud Logs

Additional info

Root Cause
Current code only validates the share status of the target node itself:
Code Path: apps/dav/lib/Connector/Sabre/SharesPlugin.php
$targetShares = $this->getShare($targetNode->getNode());
Required fix is to validate the share status of the entire path chain:
$targetShares = $this->getSharesInPath($target);
New Helper Function:

/**
 * Check if the path is within any shared folder (stops at first found share)
    */
private function getSharesInPath(string $path): array {
    $currentPath = $path;
    while ($currentPath !== '' && $currentPath !== '/') {
        try {
            $node = $this->tree->getNodeForPath($currentPath);
            if ($node instanceof DavNode) {
                $nodeShares = $this->getShare($node->getNode());
                if (!empty($nodeShares)) {
                    // Return immediately when share is found
                    return $nodeShares;
                }
            }
        } catch (\Exception $e) {
                // Path doesn't exist, continue to parent directory
        }
        // Move up to parent directory
        $currentPath = dirname($currentPath);
        if ($currentPath === '.') {
            $currentPath = '';
        }
    }
    return [];
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in apps/dav/lib/Connector/Sabre/SharesPlugin.php at the target share validation and compare it with the reported getSharesInPath approach. Reproduce the move/copy cases for /re-share/ and /re-share/subfolder/, then verify both are rejected when the source share lacks sharing permission.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
authorization, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.