Skip to content

Commit

Permalink
Expose bourne settings. Closes #3917
Browse files Browse the repository at this point in the history
  • Loading branch information
hueniverse committed Feb 4, 2019
1 parent 3378e78 commit 7578f61
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 0 deletions.
15 changes: 15 additions & 0 deletions API.md
Expand Up @@ -130,6 +130,7 @@
- [`route.options.payload.output`](#route.options.payload.output)
- [`route.options.payload.override`](#route.options.payload.override)
- [`route.options.payload.parse`](#route.options.payload.parse)
- [`route.options.payload.protoAction`](#route.options.payload.protoAction)
- [`route.options.payload.timeout`](#route.options.payload.timeout)
- [`route.options.payload.uploads`](#route.options.payload.uploads)
- [`route.options.plugins`](#route.options.plugins)
Expand Down Expand Up @@ -3258,6 +3259,20 @@ Determines if the incoming payload is processed or presented raw. Available valu

- `'gunzip'` - the raw payload is returned unmodified after any known content encoding is decoded.

#### <a name="route.options.payload.protoAction" /> `route.options.payload.protoAction`

Default value: `'error'`.

Sets handling of incoming payload that may contain a prototype poisoning security attach. Available
values:

- `'error'` - returns a `400` bad request error when the payload contains a prototype.

- `'remove'` - sanitizes the payload to remove the prototype.

- `'ignore'` - disables the protection and allows the payload to pass as received. Use this option
only when you are sure that such incoming data cannot pose any risks to your application.

#### <a name="route.options.payload.timeout" /> `route.options.payload.timeout`

Default value: to `10000` (10 seconds).
Expand Down
1 change: 1 addition & 0 deletions lib/config.js
Expand Up @@ -145,6 +145,7 @@ internals.routeBase = Joi.object({
.allow(false),
allow: Joi.array().items(Joi.string()).single(),
override: Joi.string(),
protoAction: Joi.valid('error', 'remove', 'ignore').default('error'),
maxBytes: Joi.number().integer().positive().default(1024 * 1024),
uploads: Joi.string().default(Os.tmpdir()),
failAction: internals.failAction,
Expand Down
50 changes: 50 additions & 0 deletions test/payload.js
Expand Up @@ -125,6 +125,56 @@ describe('Payload', () => {
expect(res.result.message).to.equal('Payload content length greater than maximum allowed: 10');
});

it('errors when payload contains prototype poisoning', async () => {

const server = Hapi.server();
server.route({ method: 'POST', path: '/', handler: (request) => request.payload.x });

const payload = '{"x":"1","y":"2","z":"3","__proto__":{"x":"4"}}';
const res = await server.inject({ method: 'POST', url: '/', payload });
expect(res.statusCode).to.equal(400);
});

it('ignores when payload contains prototype poisoning', async () => {

const server = Hapi.server();
server.route({
method: 'POST',
path: '/',
options: {
payload: {
protoAction: 'ignore'
},
handler: (request) => request.payload.__proto__
}
});

const payload = '{"x":"1","y":"2","z":"3","__proto__":{"x":"4"}}';
const res = await server.inject({ method: 'POST', url: '/', payload });
expect(res.statusCode).to.equal(200);
expect(res.result).to.equal({ x: '4' });
});

it('sanitizes when payload contains prototype poisoning', async () => {

const server = Hapi.server();
server.route({
method: 'POST',
path: '/',
options: {
payload: {
protoAction: 'remove'
},
handler: (request) => request.payload.__proto__
}
});

const payload = '{"x":"1","y":"2","z":"3","__proto__":{"x":"4"}}';
const res = await server.inject({ method: 'POST', url: '/', payload });
expect(res.statusCode).to.equal(200);
expect(res.result).to.equal({});
});

it('returns 413 with response when payload is not consumed', async () => {

const payload = Buffer.alloc(10 * 1024 * 1024).toString();
Expand Down

0 comments on commit 7578f61

Please sign in to comment.