内容安全:摘要、来源信任和加密不能互相替代
自动关联目录:内容安全:摘要、来源信任和加密不能互相替代
核心判断:摘要证明字节是否变化,签名或可信来源证明谁发布了它,加密隐藏内容,沙箱限制内容能做什么。四者解决不同威胁,不能用“文件已加密”代替完整性与执行边界。
一、业务问题:客户端最终必须消费不可信输入
创作者内容会经过本地保存、构建、上传、下载、缓存和运行时加载。任一环节都可能出现截断、串版本、路径越界、缓存污染或恶意替换。尤其是脚本和字节码,验证“文件能打开”远远不够。
早期下载路径常把 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、旧版本重放、超大长度、路径穿越、临时文件残留和安装中断。安全验收也不能只看“攻击是否被拒绝”,还要确认拒绝发生在脚本执行、对象创建和资源注册之前。
这部分反思的重点不是堆安全名词,而是为每个威胁指定唯一负责的机制,并明确客户端加密能做什么、不能做什么。
许可协议:CC BY
作者:Davids
本文链接:https://hustjjd.github.io/09d73ca8.html
更新于:2026年10月14日