- 地图脚本:localStorage 读写走 lsGet/lsSet 兜底(隐私模式下裸访问会打断整段脚本); preview() 在 /api/map-config 还没回来时不丢点(previewQueue 在 if (live) 之前排队); 异步回包一律发序号作废,取消后回来的包不再画 - photo-exif.js:EXIF 时间全 0 不再变成 1899-11-30 写进到访时间;读 count 前先按版本卡宽度 - 数据编辑页:三个筛选表单都把其余条件用隐藏域原样带上,提交不再把别的列表的筛选清掉 - 补全页:sessionStorage 的读写一律包 try(脏数据/隐私模式都会抛) - 窄屏:删掉被后面同特异性规则盖掉的死内边距;宽表堆叠类名成对、判据扩到所有 tb 表 - 无障碍:图片删除按钮补 aria-label,访客画廊图片补 alt - report.html 补上漏掉的 </tr>,fog-mask 的宽表带 tb-stack 本批不碰数据库与导出路径:往返包 823/323/8/30/791/557/2246 全等、 坐标偏差 0.000000000、时间偏差 0s、迷雾 8701 块一致。
58 lines
2.3 KiB
Go
58 lines
2.3 KiB
Go
package web
|
||
|
||
import (
|
||
"strings"
|
||
"testing"
|
||
)
|
||
|
||
// mapHTMLSinks 是「可编辑字段被裸拼进 HTML」的具体写法。这些值来自地点名、交通方式名、
|
||
// 城市名、GPX 轨迹名——站长自己可编辑,但访客页也会一起渲染。
|
||
//
|
||
// Leaflet 的 bindTooltip / bindPopup 把字符串参数按 **HTML** 解析,innerHTML 同理,
|
||
// 所以少一层 esc() 就是一次注入。同文件里的 popup() 早就用 esc() 了,
|
||
// 这四处漏掉纯属不一致(2026-09-21 审计 P1-4)。
|
||
var mapHTMLSinks = []string{
|
||
"bindTooltip(p.n", // 地点名
|
||
"bindTooltip((s.m", // 交通方式名(轨迹 tooltip)
|
||
"bindTooltip(t.name", // GPX 轨迹名
|
||
"'<b>' + c.city", // 城市名(城市气泡)
|
||
"+ m.name +", // 交通方式名(图例)
|
||
"+ (m.color ||", // 交通方式的颜色值,进了 style 属性
|
||
}
|
||
|
||
// TestMapTooltipsEscapeEditableFields 守住地图 JS 的 HTML 出口:
|
||
// 1. 已知的裸拼接写法一个都不许出现;
|
||
// 2. 每一个 bindTooltip / bindPopup 的调用行要么走 esc(),要么传的是 function(自己建 DOM)。
|
||
//
|
||
// 判据放在源码文本上而不是浏览器里,是因为这四处的注入后果很轻(站长可编辑的数据偏「自伤」),
|
||
// 但渲染错乱是实打实的——用 CDP 起浏览器只为了证明一句 esc() 太贵。
|
||
func TestMapTooltipsEscapeEditableFields(t *testing.T) {
|
||
raw, err := staticFS.ReadFile("static/js/rond-map.js")
|
||
if err != nil {
|
||
t.Fatalf("读取 rond-map.js 失败: %v", err)
|
||
}
|
||
src := string(raw)
|
||
|
||
for _, bad := range mapHTMLSinks {
|
||
if strings.Contains(src, bad) {
|
||
t.Errorf("rond-map.js 里出现未转义的 HTML 拼接 %q:该字段可编辑,须过 esc()", bad)
|
||
}
|
||
}
|
||
|
||
checked := 0
|
||
for i, line := range strings.Split(src, "\n") {
|
||
if !strings.Contains(line, ".bindTooltip(") && !strings.Contains(line, ".bindPopup(") {
|
||
continue
|
||
}
|
||
checked++
|
||
if !strings.Contains(line, "esc(") && !strings.Contains(line, "function") {
|
||
t.Errorf("rond-map.js:%d 的 tooltip/popup 参数既没过 esc() 也不是 function,"+
|
||
"Leaflet 会按 HTML 渲染:%s", i+1, strings.TrimSpace(line))
|
||
}
|
||
}
|
||
if checked == 0 {
|
||
t.Fatal("一个 bindTooltip/bindPopup 都没扫到:写法变了,这条守卫就失效了")
|
||
}
|
||
t.Logf("扫了 %d 处 tooltip/popup", checked)
|
||
}
|