3 Commits

Author SHA1 Message Date
wangjia f1ee537ab7 附件内容去重(hash):上传改为内容寻址 + store 按 hash 去重 [tsk_fTul9G4eutVn]
- types: Attachment 增 hash?/size? 可选字段(向后兼容,老数据零迁移)
- 上传端点 POST .../attachments 改为内容寻址:流式计算 sha256,写临时文件再
  按 <sha256>.<ext> 原子 rename;同 hash 已存在则丢弃临时文件(真去重);
  超限/异常清理临时文件不留垃圾。磁盘名仅由内容 hash 决定,杜绝撞名覆盖丢数据。
- store.addAttachments 去重键改为 hash ?? path(later-wins,老数据回退 path)。
- DELETE 端点补注释:附件按 task 隔离,无需跨任务 refcount。
- 安全保持并固化:GET inline 仅硬白名单图片,其余强制 attachment+octet-stream
  +nosniff+CSP sandbox;路径越界防护;hash 命名不含路径可控字符。
- 测试:新增同内容去重/不同内容同名各留一条/响应含 hash+size 等用例。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 07:22:15 +08:00
wangjia d9d3de26b8 fix(security): 附件 GET 端点防同源存储型 XSS——非白名单图片(svg/html等)强制下载+octet-stream+nosniff+CSP sandbox
maestro 双复审漏掉的真实 HIGH:上传文件与 API 同源,inline 渲染会在 console 源执行其脚本。只对 png/jpeg/gif/webp 允许 inline 预览,其余强制 attachment 下载并改 content-type 为 octet-stream,加 X-Content-Type-Options:nosniff + CSP sandbox 双重兜底。带 SVG 安全单测。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 01:59:34 +08:00
wangjia 2500e3e779 后端:附件读取/下载端点 + 删除端点 + addAttachments 落库去重 (tsk_tttdU3VLCy50)
- store.addAttachments:按 path 去重(later-wins),消除重传产生的悬空元数据
- store.removeAttachment:按磁盘文件名(basename(path))移除元数据,返回 removed
- GET /api/tasks/:id/attachments/:name:inline 预览,?download=1 触发下载(RFC5987 文件名)
- DELETE /api/tasks/:id/attachments/:name:先删元数据再尽力删磁盘文件
- 只服务元数据登记过的附件 + resolve/startsWith 前缀校验,杜绝目录穿越
- 新增 test/attachments.test.ts(去重/读取/下载/删除/穿越/丢失/端到端上传去重)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 01:29:42 +08:00