Files
tamabox/outputs/p0-p1-fixes-2026-09-01.md
T
tamakyi e3e59e7c69 chore: baseline snapshot before moderation-strictness feature
Repo .git was damaged (refs/ missing, index truncated, object store near-empty).
Repaired via git init (rebuilt refs), stale index preserved as .git/index.corrupt-20260910.bak,
then full worktree committed as a rollback baseline.
2026-09-10 10:56:27 +08:00

78 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 上限等)尚未处理。