a1dc1ff7a3
Co-Authored-By: Claude Code <noreply@anthropic.com>
44 lines
1.6 KiB
Python
44 lines
1.6 KiB
Python
"""chat.html 静态面前缀守卫(spec 2026-10-19 §4):页面级 __BASE_PATH__ 引导。
|
|
|
|
chat 是页面而非嵌入脚本(与 widget.js 的脚本地址自推导不同),由 chat.html
|
|
head 内联引导脚本按 location.pathname 推导 basePath 并动态装载 css/js/
|
|
avatar;Host 模式(根路径 "/")推导为空串,所有引用零变化。守卫四点:
|
|
引导脚本在场且走正则白名单 match、静态标签不再绝对引用、引导块零
|
|
innerHTML(拼接安全防线 §2/§3)、chat.js 端点构造全部经 __BASE_PATH__。
|
|
"""
|
|
from pathlib import Path
|
|
|
|
STATIC = Path(__file__).resolve().parent.parent / "static"
|
|
|
|
|
|
def read(rel):
|
|
return (STATIC / rel).read_text(encoding="utf-8")
|
|
|
|
|
|
def test_引导脚本存在且定义_BASE_PATH():
|
|
src = read("chat.html")
|
|
assert "__BASE_PATH__" in src
|
|
# 代码锚(非注释):base 推导必须走正则白名单 match
|
|
assert "location.pathname.match(" in src
|
|
|
|
|
|
def test_不再有静态绝对引用标签():
|
|
src = read("chat.html")
|
|
assert 'href="/static/' not in src
|
|
assert 'src="/static/js/' not in src
|
|
assert 'src="/api/public/avatar"' not in src
|
|
|
|
|
|
def test_引导脚本零innerHTML_拼接安全防线():
|
|
# 安全防线 §2/§3:base 只做 URL 属性赋值,绝不拼 HTML——
|
|
# 断言首个内联 <script>...</script> 块(引导脚本)内无 innerHTML
|
|
src = read("chat.html")
|
|
boot = src.split("<script>", 1)[1].split("</script>", 1)[0]
|
|
assert "innerHTML" not in boot
|
|
|
|
|
|
def test_chatjs_端点全部走_BASE_PATH():
|
|
src = read("js/chat.js")
|
|
assert "__BASE_PATH__" in src
|
|
assert 'fetch("/api/' not in src
|