静态站点不需要 JavaScript 才能站得住脚;<script> 标签的缺席本身就可能是重点。本文论证一个在线内容站点通过策略关闭脚本通道的工程依据,并用本站实际提供的请求头来证明这一论断。
论证分三部分:你删掉的攻击面;让删除可被观察的契约;以及确实该放弃这一层的情况。
你没有脚本通道,就删掉了一整类威胁面
一个不执行自身或第三方脚本的页面,一次性移除整类失败与滥用。跨站脚本存在于能运行注入代码的文档中;一个根本不能运行代码的文档,注入没有任何可升级的落点。第三方统计与挂件因为根本没有 <script> 标签可以嵌入而消失。浏览器包依赖漂移带来的供应链风险也随之消失,因为没有包。每一类都是有限、可命名的表面——也就是"小系统"那种"选择你能说清的边界"的特性。
这不是声称站点"安全",而是声称攻击面更窄,并且关键的是更容易推理,因为它是靠构造枚举的,而不是靠审计枚举的。
让边界可强制执行的响应头
口味不是策略。这里的区别是,无脚本契约是由服务器强制执行的,而不是靠开发者的自觉。本站的活动响应带:
content-security-policy: default-src 'self'; base-uri 'self'; form-action 'none'; frame-ancestors 'none'; object-src 'none'; script-src 'none'; style-src 'self'; img-src 'self' data:
其中 script-src 'none' 指令是可强制执行的部分。即使某个未来的发布在页面里漏进一个多余的 <script>,浏览器也拒绝执行它。因此"没有 JavaScript"是一项被服务的契约,每次构建都由校验器检查(script-free),而不是一次希望。这就是"我们不用 JS"和"公共边缘拒绝运行 JS"的区别。
移除之后静态结构带来的好处
没有脚本之后,内容模型回归到更接近已发布文档的东西。缓存更简单,因为静态文件有稳定的字节身份和一个 ETag,而不是一个可变的 DOM。在终端里读线上 HTML、用"查看源代码"、或索引整棵树都很直接,因为产量就是磁盘上的普通文件。这是这个站点接受的交换:没有交互状态、没有客户端渲染、没有需要视图模型的反馈。对文档与运维站点而言,这是正确的取舍,值得写下来。
什么时候"零 JS"的论断是错的
这是一层功能,不是一张纯净的标签。一个真正需要客户端交互的站点——实时仪表盘、文档编辑器、支付流程——不应该为了迁就约束就扭曲成提供静态 HTML 再硬塞变通方案。错误的应用是削足适履地把产品切成适应约束的形状。正确的应用是认识到:用来阅读、检索、归档的内容,从"成为文档"中收益;只有在文档本身不足时才需要脚本。
对这一性质,被服务的响应头就是证据,任何一次发布都可以通过读取公共边缘复现它。这正是偏好与已部署的决策之间的差别。
来源
- MDN:内容安全策略(
script-src),禁用脚本执行的指令,已核验 2026-08-13。 - PortSwigger:什么是跨站脚本(XSS)?,脚本无法运行时被移除的攻击类别,已核验 2026-08-13。
- OWASP:内容安全策略,CSP 作为纵深防御控件,已核验 2026-08-13。