给定类 JSON 内容,JSON Sanitizer 会将其转换为有效的 JSON。
它可以附加在数据管道的任一端,以帮助遵循 Postel 原则:
对自己的行为要保守,对来自他人的输入要宽容
将其应用于来自他人的类 JSON 内容时,它会生成格式良好的 JSON,应该能满足你使用的任何解析器。
在发送前将其应用于你的输出时,它会纠正编码中的小错误,并使你的 JSON 更容易嵌入到 HTML 和 XML 中。

许多应用程序拥有大量使用临时(ad-hoc)方法生成 JSON 输出的代码。
这些输出通常在发送到网络之前都要经过少量框架代码。这少量框架代码可以使用本库来确保这些临时输出符合标准,并且可以安全地传递给(过于)强大的反序列化器,例如 Javascript 的 eval 运算符。
应用程序还经常拥有从各种来源接收 JSON 的 Web 服务 API。当这些 JSON 是使用临时方法创建时,本库可以将其整理成易于解析的形式。
通过将本库挂接到发送和接收请求与响应的代码中,本库可以帮助软件架构师确保系统范围的安全性和格式良好性保证。
该净化器接收类 JSON 内容,并像 JS eval 那样解释它。具体来说,它处理以下非标准构造。
| Construct | Policy |
|---|---|
'...' | 单引号字符串会被转换为 JSON 字符串。 |
\xAB | 十六进制转义会被转换为 JSON Unicode 转义。 |
\012 | 八进制转义会被转换为 JSON Unicode 转义。 |
0xAB | 十六进制整数字面量会被转换为 JSON 十进制数字。 |
012 | 八进制整数字面量会被转换为 JSON 十进制数字。 |
+.5 | 十进制数字会被强制转换为 JSON 更严格的格式。 |
[0,,2] | 数组中的空位会被填充为 null。 |
[1,2,3,] | 尾随逗号会被移除。 |
{foo:"bar"} | 未加引号的属性名会被加上引号。 |
//comments | JS 风格的行注释和块注释会被移除。 |
(...) | 分组括号会被移除。 |
该净化器会修复缺失的标点、结束引号,以及不匹配或缺失的闭合括号。如果输入仅包含空白字符,则会替换为有效的 JSON 字符串 null。
输出是符合 RFC 4627 定义的格式良好的 JSON。输出还满足以下附加属性:
"</script",因此无需额外编码即可嵌入到 HTML script 元素中。"]]>",因此无需额外编码即可嵌入到 XML CDATA 段中。eval(在外层包裹括号后)或 JSON.parse 解析。具体而言,输出不会包含任何内嵌 JS 换行符(U+2028 段落分隔符或 U+2029 行分隔符)的字符串字面量。由于输出是格式良好的 JSON,将其传递给 eval 不会产生副作用,也不包含自由变量,因此它既不是代码注入向量,也不是秘密数据外泄的向量。
本库仅确保 JSON 字符串 → Javascript 对象这一阶段没有副作用,也不解析自由变量,并且无法控制其他客户端代码之后如何解释生成的 Javascript 对象。因此,如果客户端代码获取由攻击者控制的解析数据的一部分,并将其传回 eval 或 innerHTML 等强大的解释器,那么该客户端代码可能会遭受意外的副作用。
var myValue = eval(sanitizedJsonString); // safe
var myEmbeddedValue = eval(myValue.foo); // possibly unsafe
此外,净化 JSON 无法保护应用程序免受混淆代理攻击
var myValue = JSON.parse(sanitizedJsonString);
addToAdminstratorsGroup(myValue.propertyFromUntrustedSource);
当输入已经是满足上述属性的有效 JSON 时,sanitize 方法将直接返回输入字符串,而不会分配新的缓冲区。因此,如果用于通常格式良好的输入,它只有极小的内存开销。
sanitize 方法的时间复杂度为 O(n),其中 n 是输入以 UTF-16 代码单元计的长度。