From 1f29d3eb2e20c9063d4e9b93ac340c3607c8344b Mon Sep 17 00:00:00 2001 From: tamakyi Date: Wed, 21 Oct 2026 18:53:10 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E8=AE=BE=E7=BD=AE=E9=A1=B5=E4=B8=BB?= =?UTF-8?q?=E9=A2=98=E8=89=B2=E5=9D=97=E8=A2=AB=E6=A8=A1=E6=9D=BF=E8=BF=87?= =?UTF-8?q?=E6=BB=A4=E5=99=A8=E6=9B=BF=E6=8D=A2=E6=88=90=20ZgotmplZ?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit html/template 对 style 属性做 CSS 过滤,linear-gradient(...) 未标记安全会被整体替换成 ZgotmplZ —— 线上设置页四个主题色块一直是灰底(既有问题,不是这次配色改动引入)。 - FuncMap 新增 safeCSS(string → template.CSS);值只来自 internal/theme.swatchOf, 由两个已校验的色值拼成,不接受用户输入,所以这里放开是安全的 - user/profile.html 的色块改 {{ safeCSS .Swatch }} - 新增 TestThemeSwatchRenders:渲染 user/profile,断言不含 ZgotmplZ 且含渐变串; 已做变异验证(去掉 safeCSS 后该用例失败) --- .workbuddy/memory/2026-10-21.md | 16 ++++++++++++++++ internal/template/template.go | 7 +++++++ templates/render_test.go | 23 +++++++++++++++++++++++ templates/user/profile.html | 2 +- 4 files changed, 47 insertions(+), 1 deletion(-) diff --git a/.workbuddy/memory/2026-10-21.md b/.workbuddy/memory/2026-10-21.md index 514e9dc..1fb882f 100644 --- a/.workbuddy/memory/2026-10-21.md +++ b/.workbuddy/memory/2026-10-21.md @@ -496,3 +496,19 @@ shiroko `#4a7fc1`(3.69) → **`#3b6dac`**(4.74),sakura `#e5678f`(2.80) → **` `_scaffold.css` 令牌数 29 → 30。`StaticVersion` → **`20261021c`**。 最终审计 8 种组合(base 亮暗 + 三主题亮暗)全部 ≥4.5。⚠️ 写 CSS 用 python 改时注意:`git checkout` 会把 base.css 还原成 CRLF,插入行要用同一行尾,否则变 MIXED。 + +## 18:5x 检查测试环境部署 → 抓到设置页色块 ZgotmplZ + +**部署核对(都对)**:`base.css?v=20261021c`、三份 CSS(base/sakura/shiroko)与本地**逐字节一致**; +设置页主题列表 = 跟随站点默认 / 基础外观 / 樱花 / 砂狼白子,**test01 已消失**、名称无 `theme.name.*` key; +登录按钮是新蓝(#0e6fd0)白字,箱主页排版正常。 +⚠️ **admin6 的主题被重置成「跟随站点默认」**(它原来选的是已删除的 test01)→ 箱主页 `` 没有 +`data-theme-style`,现在是基础外观。要验证主题得重新选 sakura/shiroko。 + +**P1 缺陷(既有,非本次改动引入)**:设置页四个主题色块全是 `style="background: ZgotmplZ"`。 +`html/template` 会对 `style` 属性做 CSS 过滤,未标记安全的 `linear-gradient(...)` 一律替换成 ZgotmplZ。 +`swatchOf` 一直在生成渐变串,所以这个色块**从来没显示过**。 +修法:FuncMap 加 `safeCSS` → `template.CSS`,模板 `{{ safeCSS .Swatch }}`(值只来自 swatchOf,不接受用户输入)。 +加了 `TestThemeSwatchRenders`(渲染 user/profile,断言不含 ZgotmplZ 且含渐变串),并做变异验证: +把 `safeCSS` 去掉 → 测试如期 FAIL。 +⚠️ 教训:任何 `style="..."` 里塞模板值都要过一遍这个过滤器;模板名在测试里**不带 `.html`**(`user/profile`)。 diff --git a/internal/template/template.go b/internal/template/template.go index 284364b..ff6e4d7 100644 --- a/internal/template/template.go +++ b/internal/template/template.go @@ -199,6 +199,13 @@ func FuncMap() []template.FuncMap { "themeName": func(lang, slug string) string { return theme.DisplayName(lang, slug) }, + // safeCSS 把受控的 CSS 值标成安全,用于主题色块的 inline background。 + // ⚠️ html/template 会过滤 style 属性里的值,linear-gradient(...) 直接被替换成 + // ZgotmplZ —— 设置页每个主题的色块都会变成灰底(线上就是这样)。 + // 值只来自 internal/theme.swatchOf(由两个已校验的色值拼成),不接受用户输入。 + "safeCSS": func(s string) template.CSS { + return template.CSS(s) + }, // moderationStrictness 返回账号「最终生效」的审核严格度档位(lax / standard / strict)。 // diff --git a/templates/render_test.go b/templates/render_test.go index e9fce52..cd98d3d 100644 --- a/templates/render_test.go +++ b/templates/render_test.go @@ -17,6 +17,7 @@ import ( "github.com/tamakyi/TamaBox/internal/i18n" "github.com/tamakyi/TamaBox/internal/security/moderation" templatepkg "github.com/tamakyi/TamaBox/internal/template" + "github.com/tamakyi/TamaBox/internal/theme" ) // 审核严格度下拉框的解析:不依赖属性的书写顺序或是否存在额外属性 @@ -423,3 +424,25 @@ func TestRenderUserQuestionList(t *testing.T) { t.Fatal("restriction banner should show expiry date") } } + +// TestThemeSwatchRenders 主题色块走的是 inline style="background: "。 +// html/template 对 style 属性做 CSS 过滤,未标记安全的 linear-gradient(...) 会被换成 +// ZgotmplZ —— 设置页每个主题的色块都变成灰底。这个用例钉住「色块真的渲染出来」。 +func TestThemeSwatchRenders(t *testing.T) { + base := profileBaseData() + base["Themes"] = []theme.Theme{ + {Slug: "sakura", Swatch: "linear-gradient(135deg, #fceef3 0 45%, #ba3e66 45% 100%)"}, + } + base["CurrentTheme"] = "sakura" + + out, err := renderToString(t, "user/profile", base) + if err != nil { + t.Fatalf("render: %v", err) + } + if strings.Contains(out, "ZgotmplZ") { + t.Fatal("色块被 html/template 过滤成 ZgotmplZ(检查是否漏了 safeCSS)") + } + if !strings.Contains(out, "linear-gradient(135deg, #fceef3 0 45%, #ba3e66 45% 100%)") { + t.Fatal("渲染结果里找不到主题色块的渐变") + } +} diff --git a/templates/user/profile.html b/templates/user/profile.html index e575005..4f77b40 100644 --- a/templates/user/profile.html +++ b/templates/user/profile.html @@ -804,7 +804,7 @@ {{ range .Themes }} {{ end }}