提交前确认
ZFile 版本
5.0.5
部署方式
源码运行
问题发生在哪些存储源
本地存储
设备类型
PC
运行环境
curl / any browser
问题复现步骤
- Complete the install wizard, log in as admin, add a local storage source
local01 containing secret/confidential.txt.
- Keep default storage permissions (anonymous users are NOT authorized), and set a folder password on
/secret.
- Control (protections work):
- Anonymous
POST /api/storage/files for local01 -> 41018 unauthorized operation.
- Listing
/secret with a wrong password -> 41021 wrong password.
- Direct
GET /pd/local01/secret/confidential.txt without a signature -> rejected ("invalid signature").
- Attack: open a private window (not logged in) and visit:
http://localhost:8080/directlink/local01/secret/confidential.txt
-> 302 to /pd/local01/secret/confidential.txt?signature=... (server signs the URL for this anonymous request) -> 200, full contents of the password-protected file.
Same result via short-link generation (POST /api/short-link/batch/generate) and share creation (POST /api/share/create) - see additional context.
预期行为
The direct-link / short-link / share-download endpoints should enforce the same authorization rules as the file-list chain: an anonymous (unauthorized) request for a path inside a password-protected folder, or inside a storage source the user has no AVAILABLE permission for, should be rejected before any signed download URL is issued.
实际行为
ZFile 5.0.0-5.0.5 issues a valid signed download URL (302 to /pd/...?signature=...) and returns the full file contents (200) for anonymous requests to password-protected / unauthorized paths. 100% reproducible.
Root cause: the download link generation chain (LinkDownloadService.handlerDirectLink L66-73 -> handlerDownloadGetUrl L127-204) only checks the showPathLink system switch (default ON) and that the storage source is enabled. Permission checks (FileOperatorCheckAspect) and folder-password verification (FolderPasswordVerifyCommand) only run on the file-list chain (/api/storage/files). Additionally POST /api/short-link/batch/generate is annotated @StoragePermissionCheck(SHARE_LINK) but FileOperatorCheckAspect.annotationCheck (L54-60) only handles LINK-type annotations - SHARE_LINK falls through (annotation present, check empty). And POST /api/share/create (ShareLinkService.validateAndGetFileService L492-511) only validates the storage source exists - anonymous users can create a share pointing at any path.
Note: the AES signature mechanism added in 5.0.0 (fix for #821) guarantees authenticity, not authorization - the issuance endpoints sign download capabilities for anonymous requests to protected paths, so the unauthorized download works while the signature check is functioning correctly.
补充信息
Suggested fix: validate at signature/link issuance time (the three entry points above) that the requesting identity is allowed to access the path - reusing the same FileChain permission/password checks the list endpoint applies - instead of only validating the signature at download time.
Regression test idea: issue a direct link for a password-protected path anonymously and assert it is rejected.
Scope: affects all enabled storage source types (verified on local storage; the check gap is storage-agnostic - it is in the link/service layer, not the storage driver layer). Verified on 5.0.5 (latest release, 2026-08-13); introduced by the 5.0 architecture (4.5.0 and earlier have no proxy-download signature mechanism).
Found during a systematic review of the download chain. Happy to provide more details if useful.
提交前确认
ZFile 版本
5.0.5
部署方式
源码运行
问题发生在哪些存储源
本地存储
设备类型
PC
运行环境
curl / any browser
问题复现步骤
local01containingsecret/confidential.txt./secret.POST /api/storage/filesforlocal01->41018 unauthorized operation./secretwith a wrong password ->41021 wrong password.GET /pd/local01/secret/confidential.txtwithout a signature -> rejected ("invalid signature").http://localhost:8080/directlink/local01/secret/confidential.txt->
302to/pd/local01/secret/confidential.txt?signature=...(server signs the URL for this anonymous request) ->200, full contents of the password-protected file.Same result via short-link generation (
POST /api/short-link/batch/generate) and share creation (POST /api/share/create) - see additional context.预期行为
The direct-link / short-link / share-download endpoints should enforce the same authorization rules as the file-list chain: an anonymous (unauthorized) request for a path inside a password-protected folder, or inside a storage source the user has no
AVAILABLEpermission for, should be rejected before any signed download URL is issued.实际行为
ZFile 5.0.0-5.0.5 issues a valid signed download URL (
302to/pd/...?signature=...) and returns the full file contents (200) for anonymous requests to password-protected / unauthorized paths. 100% reproducible.Root cause: the download link generation chain (
LinkDownloadService.handlerDirectLinkL66-73 ->handlerDownloadGetUrlL127-204) only checks theshowPathLinksystem switch (default ON) and that the storage source is enabled. Permission checks (FileOperatorCheckAspect) and folder-password verification (FolderPasswordVerifyCommand) only run on the file-list chain (/api/storage/files). AdditionallyPOST /api/short-link/batch/generateis annotated@StoragePermissionCheck(SHARE_LINK)butFileOperatorCheckAspect.annotationCheck(L54-60) only handles LINK-type annotations - SHARE_LINK falls through (annotation present, check empty). AndPOST /api/share/create(ShareLinkService.validateAndGetFileServiceL492-511) only validates the storage source exists - anonymous users can create a share pointing at any path.Note: the AES signature mechanism added in 5.0.0 (fix for #821) guarantees authenticity, not authorization - the issuance endpoints sign download capabilities for anonymous requests to protected paths, so the unauthorized download works while the signature check is functioning correctly.
补充信息
Suggested fix: validate at signature/link issuance time (the three entry points above) that the requesting identity is allowed to access the path - reusing the same
FileChainpermission/password checks the list endpoint applies - instead of only validating the signature at download time.Regression test idea: issue a direct link for a password-protected path anonymously and assert it is rejected.
Scope: affects all enabled storage source types (verified on local storage; the check gap is storage-agnostic - it is in the link/service layer, not the storage driver layer). Verified on 5.0.5 (latest release, 2026-08-13); introduced by the 5.0 architecture (4.5.0 and earlier have no proxy-download signature mechanism).
Found during a systematic review of the download chain. Happy to provide more details if useful.