Files
tamabox/.workbuddy/memory/2026-09-11.md
T

3.7 KiB
Raw Blame History

2026-09-11 工作日志

代码审阅(全库,安全/正确性/可优化)

结论:无 P0、无 P1 可利用漏洞;仅 P2(一致性 / 健壮性 / 性能)。

已验证「没问题」的项(勿重复排查)

  1. 越权:所有写接口均有归属校验 —— getOwnedVote 显式比对 vote.UserID != ctx.User.ID(vote.go:388-401); question 路由挂在 question.Questioner 中间件组(route.go:262-274),PublishAnswer 二次校验 question.UserID; follow-up 写操作以 question.ID 为作用域(AnswerByID/UpdateAnswerByID)。profile/password/harassment/tags/features 一律用 ctx.User.ID。
  2. SQL 注入:internal/db 全部用 ? 绑定参数;拼接仅出现在常量/配置(dedupeUniqueFields、tagCond、randomFunc)。
  3. XSS:internal/template/markdown.go 白名单消毒扎实 —— strip on*、禁 style、safeURL 协议白名单 (http/https/mailto/相对)、拒 // 协议相对、强制 rel="noopener noreferrer"。
  4. 竞态:follow-up 用事务 + FOR UPDATE 行锁;投票「一人一票」用复合唯一索引。
  5. GORM bool 默认值陷阱:已规避(Enabled 不加 gorm:"default:true",见 feature_control.go:79-81), 且 reconcileLegacyChatEnabled(:609-618)修复旧 backfill 脏行。
  6. 审核缓存回放无 fail-open:AliyunTextCensorParser(aliyun.go:433-461)与 QiniuTextCensorParser (qiniu.go:133-170)都会从 raw 重建 Details,故 Decide 仍能按当前档位裁决(改档位对历史缓存同样生效)。 ⚠️ text.go:66 注释称「回放缓存结果时为 nil」是错的,需修正。

P2 清单(待用户选批后落地)

# 文件:行 问题 建议
1 censor.go:72,111,118-125 缓存按原文 text 查,实际送审 RemoveTrustedURL(text),落库 Input 存原文 → 审计与实际送审不一致 + 归一化相同文本重复调 API 归一化一次,查找/送审/落库统一用归一化文本,原文另存字段
2 censor.go:85-102 qiniu 缓存命中仅 Pass 才返回,aliyun 命中即返回(不看 Pass)→ 依赖「aliyun 恒为链尾」隐式前提 两分支语义对齐,或显式固化链尾不变量
3 text.go:66 注释失真(称回放时 Details 为 nil,实际会重建) 修正注释
4 route/vote/vote.go:814-822 配额用「插入后计数」判定,非原子条件插入 → 并发可短暂超额(有界、自动结束自愈) 改 WHERE count<quota 条件插入或 DB 计数列
5 route/user/profile.go:194-215 Name/Intro/各 link 无长度校验直传 db.Users.Update 补 rune 长度校验(对齐 vote/block-word)
6 internal/db/users.go:89 User.Email 带 json:"email"(对比 Password/BlockWords 为 json:"-")→ 潜在 PII 泄露 改 json:"-"
7 internal/db/db.go:215-222 用 conf.Database.Schema 拼 CREATE SEQUENCE(配置来源,纵深防御) 校验/白名单 schema 标识符
8 text.go:114-141 RemoveTrustedURL 对 12 host × 2 protocol = 24 次整串重建 单次正则/一次遍历

另:question.go:214 提问人 token 在 URL 中(邮件链接),设计如此,会出现在邮件日志/Referer,可接受。

编译状态(延续 09-10)

  • 重包 ./route/user/ ./internal/route/ ./internal/db/ 再次 30 分钟超时(exit 124,无报错) → 判定为 1C1G 沙箱编译整图慢,非代码错误(注释改动不影响编译,20 文件 gofmt -e 均可解析)。
  • 已确认可编译:GROUP1(security/censor、conf、form、template、shared、captcha)EXIT=0;./internal/db/ EXIT=0。
  • 温缓存重试(task zGnX3L)仍在跑,25 分钟上限。