# 安全考虑
¥Security considerations
JSON Schema 如果使用得当,可以取代数据清理。它不会取代其他 API 安全注意事项。它还引入了需要考虑的其他安全方面。
¥JSON Schema, if properly used, can replace data sanitisation. It doesn't replace other API security considerations. It also introduces additional security aspects to consider.
# 安全联系人
¥Security contact
要报告安全漏洞,请使用 Tidelift 安全联系人 (opens new window)。Tidelift 将协调修复和披露。请不要通过 GitHub 问题报告安全漏洞。
¥To report a security vulnerability, please use the Tidelift security contact (opens new window). Tidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.
# 不受信任的结构
¥Untrusted schemas
Ajv 将 JSON 结构视为与应用代码一样可信。此安全模型基于最常见的用例,即结构是静态的并与应用打包在一起。
¥Ajv treats JSON schemas as trusted as your application code. This security model is based on the most common use case, when the schemas are static and bundled together with the application.
如果你的结构是从不受信任的来源接收的(或从不受信任的数据生成的),则需要防止以下几种情况:
¥If your schemas are received from untrusted sources (or generated from untrusted data) there are several scenarios you need to prevent:
编译结构可能会导致堆栈溢出(如果它们太深)
¥compiling schemas can cause stack overflow (if they are too deep)
编译结构可能会很慢(例如 #557 (opens new window))
¥compiling schemas can be slow (e.g. #557 (opens new window))
校验某些数据可能会很慢
¥validating certain data can be slow
很难预测所有场景,但至少它可能有助于限制不受信任结构的大小(例如限制 JSON 字符串长度)以及最大结构对象深度(对于相对较小的 JSON 字符串可能会很高)。你可能还希望缓解 pattern
和 patternProperties
关键字中的缓慢正则表达式。
¥It is difficult to predict all the scenarios, but at the very least it may help to limit the size of untrusted schemas (e.g. limit JSON string length) and also the maximum schema object depth (that can be high for relatively small JSON strings). You also may want to mitigate slow regular expressions in pattern
and patternProperties
keywords.
无论你采取什么措施,使用不受信任的结构都会增加安全风险。
¥Regardless the measures you take, using untrusted schemas increases security risks.
# JavaScript 对象中的循环引用
¥Circular references in JavaScript objects
Ajv 不支持对象中具有循环引用的结构和经过校验的数据。参见 问题 #802 (opens new window)。
¥Ajv does not support schemas and validated data that have circular references in objects. See issue #802 (opens new window).
尝试编译此类结构或校验此类数据将导致堆栈溢出(或者在异步校验的情况下将无法完成)。根据你使用的解析器,不受信任的数据可能会导致循环引用。
¥An attempt to compile such schemas or validate such data would cause stack overflow (or will not complete in case of asynchronous validation). Depending on the parser you use, untrusted data can lead to circular references.
# 可信结构的安全风险
¥Security risks of trusted schemas
JSON 结构中的某些关键字可能会导致某些数据的校验速度非常慢。这些关键词包括(但可能不限于):
¥Some keywords in JSON Schemas can lead to very slow validation for certain data. These keywords include (but may be not limited to):
pattern
和format
用于大字符串 - 在某些情况下,使用maxLength
可以帮助缓解这种情况,但某些正则表达式即使使用相对较短的字符串也会导致指数校验时间(请参阅 重拒绝攻击)。¥
pattern
andformat
for large strings - in some cases usingmaxLength
can help mitigate it, but certain regular expressions can lead to exponential validation time even with relatively short strings (see ReDoS attack).patternProperties
用于大型属性名称 - 使用propertyNames
来缓解,但某些正则表达式也可能具有指数计算时间。¥
patternProperties
for large property names - usepropertyNames
to mitigate, but some regular expressions can have exponential evaluation time as well.uniqueItems
用于大型非标量数组 - usemaxItems
to mitigate¥
uniqueItems
for large non-scalar arrays - usemaxItems
to mitigate
不要在生产中使用 allErrors
仅当你不在生产代码中使用 allErrors: true
时,上述防止缓慢校验的建议才有效(使用它将在校验错误后继续校验)。
¥The suggestions above to prevent slow validation would only work if you do NOT use allErrors: true
in production code (using it would continue validation after validation errors).
你可以根据 这个元结构 (opens new window) 校验你的 JSON 结构,以检查是否遵循了这些建议:
¥You can validate your JSON schemas against this meta-schema (opens new window) to check that these recommendations are followed:
ajv = new Ajv({strictTypes: false}) // this option is required for this schema
const isSchemaSecure = ajv.compile(require("ajv/lib/refs/json-schema-secure.json"))
const schema1 = {format: "email"}
isSchemaSecure(schema1) // false
const schema2 = {format: "email", maxLength: MAX_LENGTH}
isSchemaSecure(schema2) // true
不可信数据
遵循所有这些建议并不能保证使用不可信数据进行校验是安全的 - 它仍然可能导致一些不良结果。
¥Following all these recommendation is not a guarantee that validation using of untrusted data is safe - it can still lead to some undesirable results.
# 重拒绝攻击
¥ReDoS attack
即使字符串相对较短,某些正则表达式也会导致指数计算时间。
¥Certain regular expressions can lead to the exponential evaluation time even with relatively short strings.
请评估你在架构中使用的正则表达式是否容易受到此攻击 - see safe-regex (opens new window), for example.
¥Please assess the regular expressions you use in the schemas on their vulnerability to this attack - see safe-regex (opens new window), for example.
默认情况下,Ajv 使用 Node.js 内置的正则表达式引擎。该引擎在最坏情况下具有指数级的性能。这种性能(和 ReDoS 攻击)可以通过使用线性时间正则表达式引擎来缓解。Ajv 支持使用第三方正则表达式引擎来实现此目的。
¥By default, Ajv uses the regex engine built into Node.js. This engine has exponential worst-case performance. This performance (and ReDoS attacks) can be mitigated by using a linear-time regex engine. Ajv supports the use of a third-party regex engine for this purpose.
要在 Ajv 中使用第三方正则表达式引擎,请在实例化期间将 ajv.opts.code.regExp 属性设置为该正则表达式引擎。这里我们以 Google 的 RE2 引擎为例。
¥To use a third-party regex engine in Ajv, set the ajv.opts.code.regExp property to that regex engine during instantiation. Here we use Google’s RE2 engine as an example.
const Ajv = require("ajv")
const RE2 = require("re2")
const ajv = new Ajv({code: {regExp: RE2}})
regexp
选项的接口详细信息请参见 docs 文件夹下的 options.md。
¥For details about the interface of the regexp
option, see options.md under the docs folder.
尽管线性时间正则表达式引擎消除了 ReDoS 漏洞,但更改正则表达式引擎会带来一些风险,包括:
¥Although linear-time regex engines eliminate ReDoS vulnerabilities, changing a regex engine carries some risk, including:
正则表达式语法的微小变化。
¥Minor changes in regex syntax.
正则表达式语义的微小变化。例如,RE2 始终以 Unicode 解释正则表达式,并且与 JavaScript 对空格的定义不一致。为了避免回归,请在生产中使用的同一正则表达式引擎中开发和测试正则表达式。
¥Minor changes in regex semantics. For example, RE2 always interprets regexes in Unicode, and disagrees with JavaScript in its definition of whitespace. To avoid regressions, develop and test your regexes in the same regex engine that you use in production.
可能不支持某些高级功能,例如前瞻或后向引用。
¥May not support some advanced features, such as look-aheads or back-references.
可能会出现(轻微)常见情况下的性能下降。
¥May have (minor) common-case performance degradation.
增加可分发的大小(例如 RE2 包括一个重要的 C 组件)。
¥Increases size of distributable (e.g. RE2 includes a non-trivial C component).
重拒绝攻击
ajv-formats (opens new window) 包实现的某些格式使用容易受到 ReDoS 攻击的 常用表达 (opens new window)。
¥Some formats that ajv-formats (opens new window) package implements use regular expressions (opens new window) that can be vulnerable to ReDoS attack.
如果你使用 Ajv 校验来自不受信任来源的数据,强烈建议考虑以下事项:
¥If you use Ajv to validate data from untrusted sources it is strongly recommended to consider the following:
对 ajv-formats (opens new window) 年 "format" 的实现情况进行评估。
¥making assessment of "format" implementations in ajv-formats (opens new window).
将
"fast"
选项传递给 ajv-formats 插件(请参阅其文档),以简化一些正则表达式(尽管它不能保证它们是安全的)。¥passing
"fast"
option to ajv-formats plugin (see its docs) that simplifies some of the regular expressions (although it does not guarantee that they are safe).将 ajv-formats 提供的格式实现替换为你自己的 "format" 关键字实现,这些实现可以使用不同的正则表达式或其他格式校验方法。请参见 addFormat (opens new window) 方法。
¥replacing format implementations provided by ajv-formats with your own implementations of "format" keyword that either use different regular expressions or another approach to format validation. Please see addFormat (opens new window) method.
通过使用选项
format: false
忽略 "format" 关键字来禁用格式校验¥disabling format validation by ignoring "format" keyword with option
format: false
无论你选择哪种缓解措施,请假设 ajv-formats 提供的所有格式都可能不安全,并自行评估它们是否适合你的校验场景。
¥Whatever mitigation you choose, please assume all formats provided by ajv-formats as potentially unsafe and make your own assessment of their suitability for your validation scenarios.
# 内容安全政策
¥Content Security Policy
在启用了内容安全策略 (CSP) 的浏览器页面中使用 Ajv 时,script-src
指令必须包含 'unsafe-eval'
。
¥When using Ajv in a browser page with enabled Content Security Policy (CSP), script-src
directive must include 'unsafe-eval'
.
跨站脚本攻击
不建议在安全 CSP[1] (opens new window) 中使用 unsafe-eval
,因为它有可能使文档受到跨站点脚本 (XSS) 攻击。
¥unsafe-eval
is NOT recommended in a secure CSP[1] (opens new window), as it has the potential to open the document to cross-site scripting (XSS) attacks.
为了在不放松 CSP 的情况下使用 Ajv,你可以在构建代码中进行 使用 CLI 编译结构 (opens new window) 或以编程方式 - see 独立校验代码。编译后的 JavaScript 文件可以导出一个或多个与运行时编译的结构具有相同代码的校验函数。
¥In order to use Ajv without relaxing CSP, you can compile the schemas using CLI (opens new window) or programmatically in your build code - see Standalone validation code. Compiled JavaScript file can export one or several validation functions that have the same code as the schemas compiled at runtime.