Skip to content

Commit

Permalink
docs: security considerations
Browse files Browse the repository at this point in the history
  • Loading branch information
epoberezkin committed Feb 2, 2019
1 parent 0bf7d38 commit 334071a
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 0 deletions.
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json'));
- [Defining custom keywords](#defining-custom-keywords)
- [Asynchronous schema compilation](#asynchronous-schema-compilation)
- [Asynchronous validation](#asynchronous-validation)
- [Security considerations](#security-considerations)
- Modifying data during validation
- [Filtering data](#filtering-data)
- [Assigning defaults](#assigning-defaults)
Expand Down Expand Up @@ -605,6 +606,54 @@ validate(data).then(successFunc).catch(errorFunc);
See [Options](#options).


## Security considerations

##### Untrusted schemas

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 may be several scenarios you may want to prevent:
- compiling schemas can cause stack overflow (if they are too deep)
- compiling schemas can be slow (e.g. [#557](https://github.com/epoberezkin/ajv/issues/557))
- validating certain data can be slow

It is difficult to predict all the scenarios, but at the very least it is recommended to limit the size of untrusted JSON Schemas (e.g. as JSON string length) and the maximum schema object depth (that can be high for relatively small JSON strings). Even that would not prevent slow regular expressions in schemas.

Regardless the measures you take, using untrusted schemas increases security risks.


##### Circular references in JavaScript objects

Ajv does not support schemas and validated data that have circular references in objects. See [issue #802](https://github.com/epoberezkin/ajv/issues/802).

An attempt to compile such schemas or validate such data would cause stack overflow (or will not complete in case of asynchronous validation). Untrusted data can lead to circular references, depending on the parser you use.


##### Security risks of trusted schemas

Some keywords in JSON Schemas can lead to very slow validation for certain data. These keywords include (but, most likely, not limited to):

- `pattern` and `format` for large strings - use `maxLength` to mitigate
- `uniqueItems` for large non-scalar arrays - use `maxItems` to mitigate
- `patternProperties` for large property names - use `propertyNames` to mitigate

__Please note__: 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).

You can validate your JSON schemas against [this meta-schema](https://github.com/epoberezkin/ajv/blob/master/lib/refs/json-schema-secure.json) to check that these recommendations are followed:

```
const isSchemaSecure = ajv.compile(require('ajv/lib/refs/json-schema-secure.json'));
const schema1 = {format: 'email'};
isSchemaSecure(schema1); // false
const schema2 = {format: 'email', maxLength: 256};
isSchemaSecure(schema2); // true
```

__Please note__: even following all these recommendation is not a guarantee that validation of untrusted data is absolutely safe - it can still lead to some undesirable situations.


## Filtering data

With [option `removeAdditional`](#options) (added by [andyscott](https://github.com/andyscott)) you can filter data during the validation.
Expand Down
100 changes: 100 additions & 0 deletions lib/refs/json-schema-secure.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/json-schema-secure.json#",
"title": "Meta-schema for the security assessment of JSON Schemas",
"description": "If a JSON Schema fails validation against this meta-schema, it may be unsafe to validate untrusted data",
"definitions": {
"schemaArray": {
"type": "array",
"minItems": 1,
"items": {"$ref": "#"}
}
},
"allOf": [
{
"description": "prevent slow validation of large property names",
"if": {
"required": ["patternProperties"]
},
"then": {
"required": ["propertyNames"],
"properties": {
"propertyNames": {
"required": ["maxLength"]
}
}
}
},
{
"description": "prevent slow validation of large non-scalar arrays",
"if": {
"required": ["uniqueItems"],
"properties": {
"uniqueItems": {"const": true},
"type": {
"anyOf": [
{
"enum": ["object", "array"]
},
{
"type": "array",
"contains": {"enum": ["object", "array"]}
}
]
}
}
},
"then": {
"required": ["maxItems"]
}
},
{
"description": "prevent slow validation of large strings",
"if": {
"anyOf": [
{"required": ["pattern"]},
{"required": ["format"]}
]
},
"then": {
"required": ["maxLength"]
}
}
],
"properties": {
"additionalItems": {"$ref": "#"},
"additionalProperties": {"$ref": "#"},
"dependencies": {
"additionalProperties": {
"anyOf": [
{"type": "array"},
{"$ref": "#"}
]
}
},
"items": {
"anyOf": [
{"$ref": "#"},
{"$ref": "#/definitions/schemaArray"}
]
},
"definitions": {
"additionalProperties": {"$ref": "#"}
},
"patternProperties": {
"additionalProperties": {"$ref": "#"}
},
"properties": {
"additionalProperties": {"$ref": "#"}
},
"if": {"$ref": "#"},
"then": {"$ref": "#"},
"else": {"$ref": "#"},
"allOf": {"$ref": "#/definitions/schemaArray"},
"anyOf": {"$ref": "#/definitions/schemaArray"},
"oneOf": {"$ref": "#/definitions/schemaArray"},
"not": {"$ref": "#"},
"contains": {"$ref": "#"},
"propertyNames": {"$ref": "#"}
}
}

0 comments on commit 334071a

Please sign in to comment.