dsh
9a5a7fa929
fix: SECURITY_TODO #32 零碎加固(status 枚举校验/严格 uint 解析/危险扩展名补充)
...
- admin_user.go: UserCreate/UserUpdate 的 status 无枚举校验,可存任意
int(如 99)——新增 validUserStatus 限定 {0,1,2,3},非法 400
(i18n user_status_invalid 中英新增)
- attachment.go: parseUintParam/parseUintForm 由 fmt.Sscanf("%d") 改为
strconv.ParseUint 严格解析——"5abc" 不再被宽松解析为 5
- settings.go: dangerousUploadExtensions 补充 .xsl/.xslt/.shtml
(XSLT 可内嵌脚本、SSI 可包含文件;nosniff 已兜底,仅完整性)
- 测试: TestUserStatusEnumRejected / TestParseUintStrict /
TestAddUploadFileTypeRejectsDangerousExtensions 扩展用例
2026-08-27 21:48:27 +08:00
dsh
f39f0f4320
fix: SECURITY_TODO #30 最后管理员防线事务化,消除 TOCTOU 竞态
...
UserUpdate/UserDelete 的 adminCount<=1 计数与 Save/Delete 非原子,两个
并发的'降级/删除倒数第二位管理员'请求可同时通过检查,站点失去管理员
(MySQL 下真实窗口;SQLite 单写锁下窗口极小)。
- handlers/admin_user.go: 检查+写入包进 db.Transaction;
ensureNotLastAdmin 在事务内锁定管理员集合后再计数:
MySQL 用 SELECT ... FOR UPDATE(gorm clause.Locking)串行化
并发事务;SQLite 无 FOR UPDATE,叠加进程内互斥锁 lastAdminMu
(应用按设计单实例部署),计数在写锁串行化后重读
- 顺带修正:原实现中 f.Role 覆盖 user.Role 后检查恒为 true 的语义
保留(基于原角色判定),避免降级检查被新值掩盖
- 测试: TestConcurrentLastAdminDowngrade(两位管理员并发降级:
恰好 1 成功 1 拒绝、最终至少保留一位管理员;-race 通过)
2026-08-27 21:45:03 +08:00
kevin
856d414295
feat: 用户管理接口 JSON 化——/api/admin/users CRUD
...
- admin_user.go:userForm 加 json tags,parseUserFormJSON(绑定+去白,
ID 取路由参数);UserCreate/Update/Delete 校验错误改 APIError
(400 校验、409 user_username_exists、403 自防/最后管理员、404
user_not_found、500),成功 {ok,redirect:?saved=1&msg=...}
- i18n:新增 user_not_found(中英)
- main.go:旧 POST /admin/users/new|:id/edit|:id/delete 移除,
改 POST/PUT/DELETE /api/admin/users[/:id](自防屏障保留)
- user_form.html:表单改 blogAPI(FormID 分流 POST/PUT),错误内联
- user_list.html:删除改 blogDelete 委托
- p2/security 测试:环境路由同步 + 用户校验/注入用例改 JSON 断言
(TestAdminUserPasswordAndEmailEnforcement、TestAdminUserRoutesRejectNonNumericIDs)
- main_test 冒烟补用户 API 断言;go build/vet/test 全绿
2026-08-27 19:44:09 +08:00
kevin
f307781f58
docs: 全部 Go 代码注释汉化
...
- 48 个 Go 文件所有注释(行注释/块注释/行尾注释,含 _test.go)翻译为中文
- 保留技术标识符:SECURITY_TODO(n)、unsafe-inline、sqlite/mysql、路由参数等
- 代码、字符串字面量、日志消息保持英文原文,零逻辑改动
- go build/vet 通过,go test -count=1 ./... 全绿
2026-08-27 19:03:03 +08:00
kevin
c9f858b626
fix: 完成 P2 安全修复 #9-13 #22-25
...
- #9 CDN 本地化:marked/DOMPurify/highlight.js/cropperjs/easymde 入 static/vendor(go:embed),Tailwind 改静态构建(scripts/build_tailwind.sh),CSP 收紧为 default-src 'self'
- #10 登录限速:IP+用户名维度 5 次失败锁 15 分钟,内存实现有界(handlers/login_ratelimit.go)
- #25 计时侧信道:用户不存在时执行 dummy bcrypt 抹平时间差(随 #10 实施)
- #11 配置文件权限 0640
- #12 首启随机一次性密码(弃用 admin/admin)
- #13 unix socket 660 + 代理用户加组提示
- #22 storage_dir 路径穿越校验(单安全路径段)
- #23 密码最小长度统一(改密/建号/重置),#24 邮箱格式统一校验
- 新增 13 个单元测试;go test ./... 含 -race 全绿
2026-08-27 18:10:22 +08:00
kevin
f7870e8557
fix: 修复 P0 复审漏洞 #18 #19(数据库泄露 + SQL 注入)
...
- #18 /uploads 改为白名单子目录挂载(attachments/avatars/logos + 配置的
存储目录),存储根不再整体暴露,blog.db 不可被下载;禁用目录列表,
拒绝 .. 穿越与反斜杠
- #19 admin 用户管理三个 handler 的路由参数先解析为数值(uintFormID),
非数值直接 302,消除 GORM First() 字符串条件 SQL 注入
- 新增回归测试 main_test.go(4 用例)与 TestAdminUserRoutesRejectNonNumericIDs
(已变异验证:旧代码下注入用例失败)
- SECURITY_TODO.md 勾选 #18/#19 并更新执行顺序
2026-08-27 17:08:22 +08:00
kevin
cefaeac618
feat: add admin user management with role-based access and self-protection
...
- Add AdminRequired middleware for admin-role routes
- Add login status check to reject disabled/locked accounts
- Add CRUD handlers (list, create, edit, delete) for users
- Add user_list and user_form templates with role/status badges
- Add nav entry and dashboard button for user management
- Add dynamic user count on admin dashboard
- Fix userIDFromSession to handle all numeric session types
- Self-protection: cannot delete/disable self or demote last admin
- Add EN/ZH i18n keys for all user management strings
2026-06-22 18:11:39 +08:00