Skip to content

🔒 限制 Agent OPFS 写操作至 workspace 并支持重命名与移动 - #1578

Merged
CodFrm merged 9 commits into
scriptscat:mainfrom
cyfung1031:codex/fix-1572-agent-opfs-permissions
Aug 27, 2026
Merged

🔒 限制 Agent OPFS 写操作至 workspace 并支持重命名与移动#1578
CodFrm merged 9 commits into
scriptscat:mainfrom
cyfung1031:codex/fix-1572-agent-opfs-permissions

Conversation

@cyfung1031

@cyfung1031 cyfung1031 commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator

Checklist / 检查清单

  • Fixes the Agent OPFS permission issue
  • Code reviewed by human / 代码通过人工检查
  • Changes tested / 已完成测试

背景

Agent OPFS 浏览器此前从 OPFS 根目录开始浏览,并在任意目录提供上传和删除操作。这样会暴露 ScriptCat 的系统数据,用户也可能误修改或删除系统资源,导致扩展无法正常运行。

本次改动

  • agents/workspace/** 设为唯一可修改范围;OPFS 根目录及其他系统目录保持只读。
  • 只读目录仍可浏览,文件仍可预览和下载,同时隐藏上传、删除、重命名和移动操作,并显示只读提示。
  • 在可编辑工作区内新增文件和目录的重命名、移动功能。
  • 在文件系统辅助层统一校验上传、删除、重命名和移动权限,避免只依赖 UI 隐藏操作。
  • 移动操作同时校验源目录和目标目录,任一路径不在 agents/workspace/** 内都会拒绝。
  • 增加非法路径、非法名称、目标同名冲突以及将目录移动到自身内部等边界校验。
  • 为所有支持的语言补充只读、重命名和移动相关文案。

实现说明

UI 与底层文件系统操作共享同一套 workspace 路径判断。writeFileremoveEntryrenameEntrymoveEntry 都会在执行前验证可编辑路径和条目名称。

重命名复用移动逻辑;移动通过递归复制后删除源条目实现,并在复制前检查目标是否已存在。源目录与目标目录都必须位于 agents/workspace/**,且不允许将目录移动到自身或其子目录中。

验证

  • OPFS 定向测试:21/21 通过。
  • 完整 Vitest:289 个测试文件、3,089 个测试通过。
  • TypeScript typecheck 通过。
  • ESLint、Prettier 和 git diff --check 通过。

建议审查重点

  • 系统目录是否始终只读,同时保留浏览、预览和下载能力。
  • UI 与底层辅助函数是否一致限制所有修改操作至 agents/workspace/**
  • 移动时源目录和目标目录的双重权限检查。
  • 重命名、目录递归移动、同名目标和目录自包含移动的边界行为。

Closes #1572

@cyfung1031 cyfung1031 changed the title 🔒 限制 Agent OPFS 浏览器的修改权限 🔒 限制 Agent OPFS 写操作至 workspace 并支持重命名与移动 Jul 12, 2026
@cyfung1031 cyfung1031 added enhancement New feature or request security labels Jul 12, 2026

Copy link
Copy Markdown
Collaborator Author

已基于最新 main(base 88e73d8a)重新审计并修正本 PR;PR 标题和正文未修改。原始 PR head 为 5f541ea6,当前发布 head 为 7b44c12a

修正 commit:

  • 7b44c12a 🐛 修复 Agent OPFS 移动回滚与加载状态
    • 移动/重命名复制或删除源条目失败时清理新建目标,避免留下阻塞后续重试的部分目录。
    • 读取失败与真实空目录分开显示,并处理 OPFS 根目录初始化失败;增加可重试错误态和加载态。
    • 重命名/移动提交期间显示忙碌状态并阻止重复提交;移动端只读目录不再显示空操作菜单。
    • 增加对应的 UI、失败回滚和重复提交回归测试。

本地验证:

  • pnpm test:327 个测试文件、3,727 个测试通过。
  • 两个 OPFS 定向测试文件:25 个测试通过。
  • pnpm run typecheck:通过。
  • pnpm run check:i18n:通过。
  • 受影响文件的 Prettier、ESLint、git diff --check:通过。

尚未验证:真实浏览器 OPFS 环境中的权限异常、进程崩溃或目标清理本身失败时的底层原子性;GitHub 远端 checks 以 PR 页面当前状态为准。

@cyfung1031

Copy link
Copy Markdown
Collaborator Author

@CodFrm 有空就测试一下。随便改

@cyfung1031
cyfung1031 marked this pull request as ready for review August 22, 2026 02:58
评审 PR scriptscat#1578 时发现的四个问题,均在本 PR 范围内修掉:

1. moveEntry 的回滚会掩盖真正的失败原因。复制可能在创建目标之前就失败
   (例如源文件 getFile() 抛错),此时目标条目根本不存在,cleanup 的
   removeEntry 抛 NotFoundError,被包成 AggregateError("Failed to roll
   back a move") 抛出,UI 只取 error.message,用户看到的是"回滚失败"而不是
   "read failure"。现在把 NotFoundError 视为"无需回滚",原始错误照常抛出。

2. 移动目标从自由文本框改为目录选择器。原实现要求用户手打完整路径,打
   "workspace" 而不是 "agents/workspace" 就会撞上 read-only 报错。新增
   listMoveDestinations() 递归列出 workspace 下的目录,并排除条目所在目录、
   条目自身及其子目录,选项恒为合法目标;workspace 下无其他目录时直接提示,
   不再打开一个没有可选项的对话框。

3. 重命名未修改名称时不再提示"重命名成功"。原实现走到 renameEntry 的早返回
   分支后仍然弹成功提示。

4. 刷新时保留已加载列表,spinner 只在没有内容可显示时出现,避免每次刷新/每次
   操作后列表整块闪烁。加载失败与真实空目录的区分保持不变。

另:copyEntry 递归时去掉 `handle.name || name` 的无谓兜底。

i18n:opfs_move_destination_placeholder(文本框占位符)已无对应控件,替换为
opfs_move_destination,并新增 opfs_move_no_destination,10 个语言包同步。

测试:补 opfs_fs 的"目标创建前失败保留原始错误"与 listMoveDestinations 排除
规则用例;补回 workspace 内上传按钮的桌面/移动端覆盖(此前被改成断言按钮不存在,
只剩系统目录一侧);新增重命名无改动、移动选择器、无可选目标、刷新保留列表四条
页面用例。
@CodFrm
CodFrm merged commit eee7d71 into scriptscat:main Aug 27, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request security

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Proposal] Agent OPFS Browser should not have the access / edit right to entire ScriptCat OPFS

2 participants