Skip to content

fix: restrict path traversal check to file scheme in DEnumerator buildUrl - #377

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
Johnson-zs:agent/bugfix/02144741
Aug 5, 2026
Merged

fix: restrict path traversal check to file scheme in DEnumerator buildUrl#377
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
Johnson-zs:agent/bugfix/02144741

Conversation

@Johnson-zs

@Johnson-zs Johnson-zs commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

根因分析

DEnumeratorPrivate::buildUrl() 中的路径遍历安全检查 fileNameBa.contains('\\') 对 gio trash:/// 后端使用反斜杠分隔的扁平文件名(如 \media\user\dev\.Trash-1000\files\x)返回空 QUrl(""),导致 /media 挂载点的回收站文件无法显示和清空。

  • 回归来源: commit fd494fb(PMS #367075, 2026-07-16)引入了该检查
  • 证据: 运行时日志显示第 2 个回收站文件 URL 为 QUrl(""),触发 kIsNotTrashFileError

修复方案

将路径遍历检查限制为仅对 file:/// 或无 scheme 的本地文件系统生效,trash:/// 等 gio 虚拟文件系统跳过该检查。

改动安全评估

低风险。修改仅限制检查的适用 scheme 范围,不改变 buildUrl() 签名或返回值语义。对 file:/// scheme 行为完全不变。

Summary by Sourcery

Bug Fixes:

  • Allow gio trash:/// backend entries with backslash-separated flat filenames to be built into valid URLs instead of being dropped by the path traversal check.

…dUrl

1. DEnumeratorPrivate::buildUrl() 对所有 scheme 的文件名做路径遍历检查,导致 gio trash:/// 后端使用反斜杠分隔的扁平文件名被误判为恶意路径并返回空 URL;
2. 将路径遍历检查限制为仅对 file:/// 或无 scheme 的本地文件系统生效,gio trash:/// 等虚拟文件系统的合法文件名不受影响;
3. 修复手动分区场景下 /media 挂载点的回收站文件无法显示和清空的问题;

Log: 修复 buildUrl 路径遍历安全检查误伤 gio trash 反斜杠文件名导致回收站无法显示和清空的问题

PMS: BUG-372733
Bug: https://pms.uniontech.com/bug-view-372733.html

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @Johnson-zs, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Johnson-zs

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@sourcery-ai

sourcery-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Restricts the path traversal filename check in DEnumeratorPrivate::buildUrl to only local file (file:/// or no-scheme) URLs so gio trash:/// backends using backslash-separated flat names are not incorrectly rejected, while preserving behavior for real local files.

Flow diagram for updated path traversal check in buildUrl

flowchart TD
    A[buildUrl url,fileName] --> B[create QByteArray fileNameBa]
    B --> C[get scheme from url]
    C --> D{scheme is empty or file}
    D -- yes --> E{fileNameBa contains /, contains \\, equals ., or equals ..}
    E -- yes --> F[return empty QUrl]
    E -- no --> G[continue building path]
    D -- no --> G
    G --> H[return constructed QUrl]
Loading

File-Level Changes

Change Details Files
Restrict path traversal filename validation to file:/// or no-scheme URLs to avoid rejecting valid gio trash:/// entries.
  • Refactors fileNameBa path traversal check to be guarded by a scheme check on the input QUrl
  • Introduces scheme extraction from url and restricts validation to empty or file schemes
  • Documents in comments that gio trash:/// backends may legally use backslash-separated flat names and should bypass this security filter
src/dfm-io/dfm-io/denumerator.cpp

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

★ 总体评分:100分

■ 【总体评价】

代码精准修复了GIO回收站后端路径误拦截问题,逻辑严密且无安全风险
修复方案直击痛点,注释详尽,性能无损,且未引入任何安全漏洞

■ 【详细分析】

  • 1.语法逻辑(完全正确)✓

通过 url.scheme() 准确获取当前 URL 的协议类型,将路径遍历拦截逻辑严格限定在本地文件系统(file:// 或无 scheme),完美解决了 trash:/// 等 GVFS 挂载方案因合法反斜杠路径被误杀而返回空 QUrl 的问题
建议:保持当前逻辑即可

  • 2.代码质量(优秀)✓

注释详尽且具有高度的业务解释性,清晰说明了 GIO trash:/// 后端使用反斜杠分隔扁平路径的根本原因,使用 QLatin1String 进行字符串比较避免了隐式类型转换,完全符合 Qt 编码规范
建议:保持当前注释风格

  • 3.代码性能(高效)✓

QUrl::scheme() 调用开销极低,引入的 QLatin1String 比较消除了临时 QString 对象的堆内存分配开销,整体性能表现优异
建议:无需优化

  • 4.代码安全(存在0个安全漏洞)✓

漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个
修复代码准确区分了本地文件系统与虚拟文件系统的安全边界,本地文件系统的路径遍历防护能力未受任何削弱,同时正确放开了由 GIO 底层保证安全的虚拟文件系统合法路径,未引入任何安全风险

  • 建议:无需额外安全加固措施

■ 【改进建议代码示例】

diff --git a/src/dfm-io/dfm-io/denumerator.cpp b/src/dfm-io/dfm-io/denumerator.cpp
index d2fe3501..c5aaa639 100644
--- a/src/dfm-io/dfm-io/denumerator.cpp
+++ b/src/dfm-io/dfm-io/denumerator.cpp
@@ -455,10 +455,17 @@ QUrl DEnumeratorPrivate::buildUrl(const QUrl &url, const char *fileName)
         return QUrl();
     }
 
-    // 拦截路径遍历攻击,防止恶意文件名越权
     QByteArray fileNameBa(fileName);
-    if (fileNameBa.contains('/') || fileNameBa.contains('\\') || fileNameBa == "." || fileNameBa == "..") {
-        return QUrl();
+
+    // 路径遍历检查仅对本地文件系统 (file:/// 或无 scheme) 生效
+    // gio 的 trash:/// 后端对非用户主目录挂载点的回收站文件,使用反斜杠分隔的扁平路径
+    // 作为 GFileInfo 的 standard::name(例如 "\media\user\dev\.Trash-1000\files\x"),
+    // 这是合法的 trash 文件名而非恶意路径,故不应对其做路径遍历拦截。
+    const QString scheme = url.scheme();
+    if (scheme.isEmpty() || scheme == QLatin1String("file")) {
+        if (fileNameBa.contains('/') || fileNameBa.contains('\\') || fileNameBa == "." || fileNameBa == "..") {
+            return QUrl();
+        }
     }
 
     QByteArray path;

@Johnson-zs

Copy link
Copy Markdown
Contributor Author

/forcemerge

@deepin-bot

deepin-bot Bot commented Aug 5, 2026

Copy link
Copy Markdown

This pr force merged! (status: blocked)

@deepin-bot
deepin-bot Bot merged commit 5df304d into linuxdeepin:master Aug 5, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants