内容安全:摘要、来源信任和加密不能互相替代

自动关联目录:内容安全:摘要、来源信任和加密不能互相替代

核心判断:摘要证明字节是否变化,签名或可信来源证明谁发布了它,加密隐藏内容,沙箱限制内容能做什么。四者解决不同威胁,不能用“文件已加密”代替完整性与执行边界。

一、业务问题:客户端最终必须消费不可信输入

创作者内容会经过本地保存、构建、上传、下载、缓存和运行时加载。任一环节都可能出现截断、串版本、路径越界、缓存污染或恶意替换。尤其是脚本和字节码,验证“文件能打开”远远不够。

早期下载路径常把 HTTP Payload 直接写入目标文件,只检查请求完成、响应非空和写文件成功。它能完成业务闭环,却不能证明字节属于期望版本,也不能防止半安装结果被后续读取。

二、实际演进:先证明将要消费的准确字节

后续读取链路已经形成更强的完整性边界:

  • 所有相对路径先经过项目根所有权校验,拒绝目录穿越;
  • 读取前限制文件与注册表大小,避免异常输入造成无界内存分配;
  • Manifest 绑定期望大小和 SHA-256,Reader 对实际读取的字节重新计算;
  • 二进制还绑定源摘要、关卡身份、编译器指纹和 Payload 摘要;
  • 字节码只有在已验证发布制品、可验证来源或受信本地构建上下文中才允许执行。

值得保留的原则是:校验发生在物化之前,并作用于真正被消费的字节,而不是某个更早阶段的临时文件。

三、加密边界:客户端密钥不能创造永久机密

当前代码证据最充分的是完整性与来源信任,不应把它包装成“通用加密方案”。如果运行时必须在客户端解密,攻击者最终可以观察密钥或明文;加密更适合降低静态抓取和链路窃听风险,不能证明文件可信,也不能阻止合法内容执行越权行为。

威胁与机制应明确对应:

威胁主要机制
下载损坏、缓存串版本内容摘要、大小、原子安装
Manifest 被替换签名、可信根、反回滚版本
路径穿越规范化路径与根目录所有权
静态内容被直接读取传输加密、按制品加密
创作者脚本越权能力沙箱、配额、协议校验
重放旧制品发布身份、generation、有效期策略

四、推荐安装协议

download -> private temp
verify(size, contentDigest, signedManifest)
decode/scan in constrained context
fsync temp and metadata
atomicActivate(contentAddressedPath)
publish small index pointer

失败只删除私有临时文件,不覆盖当前可用版本。缓存键至少包含逻辑内容、修订、目标平台和格式;仅以 URL 或文件名作为键,无法区分同名不同制品。

五、验证结论

故障测试要覆盖截断、字节翻转、伪造 Manifest、旧版本重放、超大长度、路径穿越、临时文件残留和安装中断。安全验收也不能只看“攻击是否被拒绝”,还要确认拒绝发生在脚本执行、对象创建和资源注册之前。

这部分反思的重点不是堆安全名词,而是为每个威胁指定唯一负责的机制,并明确客户端加密能做什么、不能做什么。