zfile-dev / zfile-dev/zfile

[Security] Share Download Endpoint Bypasses shareEntries Filter - Unauthorized Access to Files Within Shared Directory

Open
#826 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Java
Stars
10.8k
Forks
2k
PR merge metrics
No merged PRs in 30d

Description

Add a description
Summary

ZFile's share link system exposes two endpoints for interacting with shared content:

  • POST /api/share/files — browse shared files (correctly enforces shareEntries filter)
  • GET /api/share/download/{shareKey}?path=<file> — download a file from a share

The download endpoint does not validate that the requested path belongs to the shareEntries list specified when the share was created. Any recipient of a share link can use the download endpoint to retrieve any file within the shared directory's base path (sharePath), not just the files the owner explicitly shared.

Details

When a user creates a share link in ZFile, they specify:

  • storageKey — which storage source to share from
  • sharePath — the base directory (e.g., /shared)
  • shareEntries — the specific files/folders within that directory to expose (e.g., ["public.txt"])

Browse endpoint (ShareLinkFileService.getShareFileList): correctly calls getFilteredRootFileList, which filters the file listing to only items in shareEntries.

Download endpoint (ShareLinkFileService.getShareFileDownloadUrl) at line ~90 of ShareLinkFileService.java:

public String getShareFileDownloadUrl(String shareKey, String filePath, String password) {
    ShareLink shareLink = getValidShareLink(shareKey);
    validateSharePassword(shareLink, password);

    AbstractBaseFileService<?> fileService = StorageSourceContext.getByStorageKey(shareLink.getStorageKey());
    // ...
    // ❌ No check: is filePath one of shareLink.getShareEntries()?
    return fileService.getDownloadUrl(StringUtils.concat(shareLink.getSharePath(), filePath));
}

The method validates the share key and password but never verifies that filePath corresponds to a file in shareEntries. Since filePath is a raw HTTP query parameter, an attacker who has a valid share key (e.g., as a legitimate recipient of a share) can request any arbitrary path within sharePath/.

PoC

(available upon request)

Impact

Any recipient of a ZFile share link (including unauthenticated users with the link) can download any file in the sharePath directory of that storage source, not just the files the owner chose to expose. In multi-user deployments, this allows:

  • Reading private files in the same directory as the shared file
  • Enumerating the directory content by guessing file names (since file listing is filtered but download is not)
  • On local storage backends, any file path within sharePath/ is accessible

The severity depends on how narrowly sharePath is scoped. If users share from / (the root), the attacker can access all files in the storage source.

Contributor guide

No contributing guide indexed for this repository

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 ShareLinkFileService.java at getShareFileDownloadUrl and compare its path handling with getFilteredRootFileList. Verify how shareEntries is represented and enforced, then confirm that downloads for listed entries still work while paths outside the shared entries are rejected.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api, backend, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.