ampproject / ampproject/amphtml
Data validation for Premutating State in AMP Bind
- Dominant language
- JavaScript
- Stars
- 14.9k
- Forks
- 4.1k
- PR merge metrics
- No merged PRs in 30d
Description
The premutate feature currently does not check the data being passed into the premutate operation. This means that if the premutate state can be specified in the query params, an attacker can send a user a link that puts the document in a dangerous initial state, that the developer has not planned for.
**Objectives:**
Since Premutate State is an input to the AMP document often derived from (untrusted) user input, it must be validated against the expected preconditions of the the AMP document before being used within. By requiring developers to define the full expected format (schema) of the Premutate State JSON, we can ensure:
1. Only expected parts of AMP State are modifiable by the Premutate State, including nested JSON, not just top level AMP State keys. It's clear to developers which parts of the AMP State are input and to what extent that part can be trusted (based on the detail of the schema validation).
The developer can enforce common expectations on the input data (e.g. type, range, etc), so it can be used without complex amp-bind logic or extra round trips to their servers to validate, even though it originated from untrusted sources.
2. Of course some types of input validation cannot be performed by schema validation (e.g. "is this a valid widget ID?"). Such validation is a non-goal here, since that will likely require a call to the third party server to validate, which can be done during the or call, as usual, without additional runtime support. Developers must still take care to do this as appropriate.
**Proposed Solution:**
Since the Premutate State is a JSON object, it's natural to describe the expected input to the AMP document by including a schema for the Premutate State JSON.
[JSON Schema](http://json-schema.org) is a draft standard for specifying the format of JSON documents analogous to XSD for XML, where the schema itself is a JSON object. In addition to simple structural validation, JSON schema allows more powerful validations, including range, regex, enum, and even semantic types, like date-time, etc.
To use Premutate State, instead of marking specific as overrideable an AMP Document would include a block with a JSON Schema describing the expected Premutate State:
```html
<script id="amp-bind-premutate-schema" type="application/schema+json">{
"type": "object",
"properties": {
"numTickets": {
"type": "integer",
"minimum": 1,
"maximum": 10,
"default": 1
},
"showtime": {
"$ref": "https://schema.googleapis.com/ScreeningEvent#"
},
"required": [
"showTime"
],
"additionalProperties": false
}
}
```
In the example above, the Premutate State could override a with an integer from 1-10 and an with a JSON Object of type ScreeningEvent (defined externally by us). The showTime input would be required, whereas numTickets is optional.
**Implementation:**
My proposed solution is that when the [premutate](https://github.com/ampproject/amphtml/blob/89e1beba030becff2026611d92ce32a6c58322c1/extensions/amp-bind/0.1/bind-impl.js#L487) function is called, the premutate schema is lazily parsed by doing a JSON parse on the text of the element with id="amp-bind-premutate-schema".
Then, a JSON Schema validator can be used to validate this schema against the passed in data for the premutate call.
On candidate for a validator is AJV (https://github.com/epoberezkin/ajv), which we can add under the third_party directory.
Thanks to ianbaker@google, who proposed this means of validation for our viewer. While in the process of implementation, I thought that this would be a useful security feature for the runtime.
Contributor guide
Assessment
This issue has not been assessed yet.