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.
4.2 KiB
4.2 KiB
P1 修复落地记录(P1-3 / 4 / 5 / 7 / 8 / 9 / 10)
- 日期:2026-08-31
- 范围:按用户要求顺序实施 7 个 P1 项(P1-6 密码比较不在本次范围;P1-3 按要求不使用 Turnstile/recaptcha)。
- P0-1(IP 伪造)暂缓,按用户指示留待后续。
1. P1-3 验证码限流 + 常量时间比较
文件:internal/captcha/math.go、internal/route/route.go
- 答案比对改为
crypto/subtle.ConstantTimeCompare,消除时序侧信道。 VerifyOnly(模态框预校验)累加尝试次数,达到maxCaptchaAttempts=5即销毁该验证码,防止无限轮询爆破。GenerateMath处理rand.Int错误(不再忽略)。/api/captcha/generate、/api/captcha/verify加上rateLimitMiddleware(20, 1m)。- ⚠️ 这是缓解而非根治:数学答案仍返回给客户端,脚本理论上可读题。根治依赖 P0-1(IP 信任校验)落地后整体提权。
2. P1-4 追问"等主人回复"服务端校验
文件:internal/db/follow_ups.go、route/question/follow_up.go
- 新增
FollowUps.GetLatestByQuestionID(Order(created_at DESC) Limit 1)。 PublishFollowUp在计数校验后,取该问题最新一条追问;若其Answer == ""直接拒绝(不再仅依赖前端waitingFollowUpReply隐藏表单)。
3. P1-5 审核可信域名精确匹配
文件:internal/security/censor/text.go
RemoveTrustedURL改为边界感知:仅当可信域名后紧跟/、?、#或位于字符串结尾时才剥离,避免https://github.com.evil.tld被误判为github.com子域而漏审。
4. P1-7 删除回退功能配额计数
文件:internal/db/feature_control.go、internal/db/questions.go、internal/db/conversation.go
IncrementQuota负 delta 增加WHERE quota_count > 0守卫,防止计数减到负数。questions.DeleteByID删除提问后回退FeatureQuestion配额 -1。conversations.MarkDeletedByOwner删除私聊会话后回退FeatureChat配额 -1(并先取 OwnerID,已删除/不存在时幂等返回)。
5. P1-8 自动封禁仅计真正 404
文件:internal/route/autoban.go、internal/route/route.go
autobanMiddleware改为接收共享*autoban.Autoban实例(由New()创建一次)。- 真正的 404 探测计数移入
f.NotFound处理器单独记录;不再把业务性302 → /(语言切换 / 登出 / 投票不存在 / 黑名单跳转)误判为路径扫描导致误封。
6. P1-9 服务反代路径穿越 / query / 超时
文件:route/service/proxy.go
forwardPath经path.Clean归一化,singleJoiningSlash安全拼接,杜绝../越出白名单前缀。- 透传原始
RawQuery(此前静默丢弃)。 - 复用带超时的共享
Transport(ResponseHeaderTimeout=15s、IdleConnTimeout=30s),不再每请求新建。
7. P1-10 像素追踪路由收紧
文件:internal/route/route.go、internal/context/context.go、route/pixel/pixel.go
/api/v1/pixel/{**}由f.Any改为f.Get+rateLimitMiddleware(30, 1m),仅放行只读 GET,并补限流。context.go去掉对/api/v1/pixel/的 CSRF 豁免(GET 本不需 CSRF,写方法已被路由层禁止)。pixel.go:路径path.Clean后必须仍在/api/之下,否则拒绝;响应头仅透传白名单(Content-Type/Length/Encoding/Disposition/Cache-Control/ETag/Expires/Last-Modified/Pragma/Vary),不透传 Set-Cookie 等。
验证状态
- ✅
go build/go vet全绿(不依赖 storage 的 5 个包):internal/captcha、internal/security/censor、internal/db、route/pixel、route/service。 - ✅ 单元测试通过:
internal/security/censor、internal/security/autoban。 - ✅ 12 个改动文件
gofmt -w已格式化。 - ⚠️
internal/route/route.go、internal/route/autoban.go、internal/context/context.go、route/question/follow_up.go因传递依赖internal/storage(github.com/chai2010/webp缺 libwebp,Windows 沙箱 CGO 限制)无法在此环境完整编译;已用gofmt -e确认无语法错误,请在 Linux / 带 libwebp 环境做完整go build ./...验证。