为什么 JSON.stringify 并不像看上去那么无害
开发人员每天都会使用 JSON.stringify 来序列化数据、通过网络发送对象、将状态存储在文件中或持久化配置。但是,如果数据在未经验证的情况下被重新注入,这种看似无害的 JSON.stringify 调用可能会引入不安全的反序列化。
问题不在于 JSON.stringify 本身,而在于我们如何滥用它。当你序列化复杂的对象(尤其是带有原型或类实例的对象)并盲目地反序列化它们时,使用 JSON.parse,您就有可能将恶意负载带入您的应用程序。
在 JavaScript 中,我们很容易认为序列化的内容是安全的,因为它“只是 JSON但 JSON 是数据,而不是逻辑。如果攻击者控制了这些数据,他们就能利用代码中的信任边界。这就是不安全的反序列化开始的地方。
导致不安全反序列化的常见开发人员错误
不安全的反序列化通常源于一些在代码审查中看起来无害的习惯。但如果不小心使用 JSON.stringify, 攻击面扩大.
不安全的做法:序列化未经验证的用户输入
⚠️警告: 此模式会在未经任何验证的情况下序列化攻击者控制的输入。如果数据之后被信任,则可能导致不安全的反序列化。
// Node.js example
const userData = req.body; // attacker-controlled
fs.writeFileSync('userdata.json', JSON.stringify(userData));
⚠️警告: 未经验证就反序列化相同的数据可能会将有效负载重新引入到您的应用程序中。
const input = JSON.parse(fs.readFileSync('userdata.json'));
doSomething(input); // Trusting it blindly
危险模式:跨信任边界重用 JSON
在一个服务(开发环境)中创建的序列化 JSON 未经验证就被另一个服务(生产环境)重用。这种情况经常发生在内部工具或微服务中。
无声风险的 Python 示例:
⚠️警告: 下面的序列化和反序列化步骤均无需验证即可处理潜在的不受信任的数据。
import json
def save_user_input(data):
with open('input.json', 'w') as f:
f.write(json.dumps(data))
def process_input():
with open('input.json') as f:
data = json.loads(f.read())
execute_logic(data) # Dangerous if data structure is assumed
这两个示例在序列化和反序列化用户控制的数据时,都没有强制执行模式。这很容易滋生不安全的反序列化漏洞,而这些漏洞是由于 JSON.stringify 的使用不当造成的。
真正的风险 Pipelines:从代码到 CI/CD 反序列化流程
现在把这种行为 pipeline. 当 JSON.stringify 在 CI/CD 工作流程会将构建过程暴露于不安全的反序列化风险中。这种情况通常发生在工件元数据、测试夹具和配置快照中。
相当常见 CI/CD 陷阱:
- 不安全的工件生成:构建工件包括序列化对象,这些对象可以在未经验证的情况下跨作业重复使用。
- 序列化环境变量:团队将环境变量存储为序列化的 JSON,并在步骤甚至项目之间重复使用它们。
- 注入的测试数据:来自不受信任的反序列化测试数据 commits 或分支无需类型检查即可执行。
这些模式使得攻击者很容易将有效载荷注入到受信任的 pipelines 使用操纵的 JSON 字符串化逻辑。
⚠️警告:此工作流程传递序列化数据时不进行验证。如果 test-runner.js 不验证输入,则存在不安全的反序列化风险。
# YAML example in GitHub Actions
steps:
- name: Load test data
run: |
echo '${{ secrets.TEST_JSON }}' > test.json
node test-runner.js test.json
If 测试运行器.js 在没有验证的情况下加载和解析 JSON,它可能会触发不安全的反序列化。
保护 JSON。stringify 具有验证和安全解析
解决方法不是避免使用 JSON.stringify,而是谨慎使用并始终应用安全检查。如果处理得当,它是安全的,但在现代 pipelines,假设很快就被打破了。
DevSecOps 实践确保 JSON.stringify:
- 使用 JSON 模式来验证序列化和反序列化的数据。
- 强制严格类型化,避免鸭子类型化或关于对象形状的假设。
- 使用支持模式强制或类型保护的安全解析库。
- 将序列化数据视为不受信任的数据,即使它来自受信任的存储库。
- 仪器 pipeline以便尽早捕获有风险的 JSON.stringify 模式。
最佳实践:此示例使用 JSON 模式验证来防止不安全的反序列化。示例使用 jv 在 Node.js 中:
const Ajv = require("ajv");
const ajv = new Ajv();
const schema = { type: "object", properties: { id: { type: "number" } }, required: ["id"] };
const validate = ajv.compile(schema);
const input = JSON.parse(fs.readFileSync('input.json'));
if (!validate(input)) throw new Error("Invalid input");
安全反序列化意味着验证 before 信任。不要依赖 JSON。stringify 默认会保证你的安全;定义安全是什么样子的。
使用 Xygeni 检测序列化风险
手动审计只能捕获有限的信息。 西吉尼 让您能够清楚地了解 JSON.stringify 在您的代码库中的使用方式, pipelines.
Xygeni 的功能:
- 痕迹 JSON.stringify 从源代码到部署的使用。
- 检测不安全的反序列化流程,尤其是跨微服务和 pipeline 阶段。
- 标记不安全数据(如环境变量、用户输入或工件)的序列化。
- 对模式偏差发出警报,显示序列化数据何时改变形状或跨越信任边界。
在处理 JSON.stringify 引入的不安全反序列化风险时,这种可见性至关重要,尤其是在 CI/CD 序列化数据快速且安静地移动的系统。
保护 JSON。stringify:抵御不安全反序列化的盾牌
JSON.stringify 本身并不安全。但如果使用不当,它就可能成为不安全反序列化的入口。
如果您是使用 JSON 的开发人员:
- 审核您在各项服务中的使用情况, pipeline和工具。
- 将反序列化的数据视为不受信任的数据。
- 应用架构验证、强制类型并将安全性集成到您的 CI/CD.
不要止步于最佳实践,使用 Xygeni 来追踪、检测和阻止不安全的反序列化风险,防止它们进入生产环境。 序列化不是中性的。使用 JSON.stringify 安全。





