Files
tamabox/outputs/p0-p1-fixes-2026-09-01.md
T
2026-09-08 10:10:44 +08:00

4.4 KiB
Raw Blame History

TamaBox-v4 P0/P1 修复报告(2026-09-01)

第三轮审计的全部 P0×2 + P1×6 已修复,并在验证过程中额外发现并修复了一处 被 webp 屏障遮蔽的隐藏编译回归(见「额外发现」)。全模块构建/vet/测试全绿。

🔴 P0 修复

P0-1 profile.go 导出函数编译错误

  • route/user/profile.go:personalData 是 [][]interface{},原代码把 interface{} 直接传给 sanitizeCell(string) 导致编译失败。
  • 改为逐单元格类型断言:字符串净化防公式注入,非字符串(time.Time 等)原样写入。

P0-2 history-template 复合游标未同步(翻页损坏)

  • 采用更彻底的方案:route/question/page.go 的 ListAPI 响应改为 {data: [...], next_cursor: "..."},由服务端直接下发 EncodePinCursor 编码的复合游标。
  • 前端 JS 不再用 new Date().getTime()*1e6 自行拼游标——JS 双精度浮点无法精确表示纳秒级 UnixNano(毫秒以下精度丢失),时间戳相同的提问会在翻页边界被跳过。
  • JS 层已适配 ctx.JSON 的统一包装 {code, data, message}(内层才是分页负载)。

🟠 P1 修复

P1-1 upload_images.go 级联删除查询不存在的列

  • DeleteByQuestionID 重写:先查 upload_image_questions 关联行拿 imageID, 再事务内软删 UploadImage 主体并删除关联行(原代码直接在错误表上 WHERE question_id)。

P1-2 conversation.go 重复删除二次回退配额

  • MarkDeletedByOwner 增加幂等守卫:conv.IsDeletedByOwner == true 直接返回, 不再重复 IncrementQuota(-1)。

P1-3 questions.go 非 PinFirst 游标 PG 报错 + ASC 方向反

  • 游标改用 strconv.ParseUint 校验(原 id < ? 传 string,PG 下 integer < text 无操作符)。
  • 排序方向规范化提前,ASC 用 id > ?、DESC 用 id < ?;解析失败忽略游标(与 PinFirst 一致)。

P1-4 home.html 供应链 XSS

  • 远程公告改 x-text 纯文本渲染,移除 x-html;meta 行与正文拆成两个元素分别渲染。

P1-5 tracing span 泄露 query string

  • span 名从 RequestURI 改为 URL.Path,?t=<token>、?code= 等不再落入 trace。

P1-6 password.go(第一轮遗留项)

  • legacy HMAC-SHA1 比较改用 crypto/subtle.ConstantTimeCompare(常量时间,防时序侧信道)。
  • encodePasswordBcrypt 失败不再静默降级为 HMAC-SHA1 弱哈希:密码超 72 字节按 bcrypt 原生语义截断;bcrypt 生成失败记日志并返回空串(账号校验失败比弱哈希安全,且 users.go:390 的 newHash != "" 守卫保证空串不会被写库)。

⚠️ 额外发现:internal/route 隐藏编译回归(P0 级)

P1-8 批次(autoban 重构)引入、一直被 webp 屏障遮蔽的编译错误,本次通过 go build -overlay 全模块类型检查暴露:

  • internal/route/route.go:使用 autoban / mail / shared 三个标识符但缺少 import;
  • internal/route/autoban.go:autoban.Autoban 类型不存在,应为 autoban.Banner。

若不修复,Linux 上的完整构建同样会失败。 两处已修复。

验证方式(重要)

Windows 沙箱缺 libwebp,internal/storage 及其依赖包无法正常编译,导致其中的类型错误 (P0-1、internal/route 回归)在常规 go build 下被遮蔽。本次引入 overlay 桩验证法:

  • dev/webpstub/:chai2010/webp 的签名兼容桩(仅 Encode/Options),保留在仓库供复用;
  • go build -overlay=<临时 overlay.json> ./route/... ./internal/... . 将 internal/storage/s3.go 的 import 临时替换为桩包,实现全模块完整类型检查。

验证结果:

  • 全模块 go build(overlay)✅
  • 全模块 go vet(overlay)✅
  • 全部可运行测试通过(templates/form/i18n/cache/autoban/censor 等,go test sweep)✅
    • 含 TestTemplatesParse / TestRenderPublicQuestionList / TestRenderPublicQuestionItem / TestRenderUserQuestionList / TestTemplateCrossReferences
  • internal/db 测试需 DB_TYPE 环境变量 + 真实数据库,属既有环境限制,非回归。

待办提醒

  1. Linux/CI 环境跑一次 go build ./... + go test ./... 最终确认(overlay 桩只覆盖类型检查, webp CGO 真实编译仍需 libwebp 环境)。
  2. P2 9 项(mail header、上传后缀白名单、孤儿文件、dbutil pageSize 上限等)尚未处理。