diff --git a/API.md b/API.md index 4109be326..ff749d6c0 100755 --- a/API.md +++ b/API.md @@ -3048,6 +3048,12 @@ Default value: `1048576` (1MB). Limits the size of incoming payloads to the specified byte count. Allowing very large payloads may cause the server to run out of memory. +#### `route.options.payload.maxParts` + +Default value: `1000`. + +Limits the number of parts allowed in multipart payloads. + #### `route.options.payload.multipart` Default value: `false`. diff --git a/lib/config.js b/lib/config.js index e3768aecf..2b668f97d 100755 --- a/lib/config.js +++ b/lib/config.js @@ -153,6 +153,7 @@ internals.routeBase = Validate.object({ override: Validate.string(), protoAction: Validate.valid('error', 'remove', 'ignore').default('error'), maxBytes: Validate.number().integer().positive().default(1024 * 1024), + maxParts: Validate.number().integer().positive().default(1000), uploads: Validate.string().default(Os.tmpdir()), failAction: internals.failAction, timeout: Validate.number().integer().positive().allow(false).default(10 * 1000), diff --git a/package.json b/package.json index aa5d1d32b..33f2e56bb 100755 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "@hapi/shot": "^6.0.1", "@hapi/somever": "^4.1.1", "@hapi/statehood": "^8.0.1", - "@hapi/subtext": "^8.0.1", + "@hapi/subtext": "^8.1.0", "@hapi/teamwork": "^6.0.0", "@hapi/topo": "^6.0.1", "@hapi/validate": "^2.0.1" diff --git a/test/payload.js b/test/payload.js index c13b9aafd..be049ac28 100755 --- a/test/payload.js +++ b/test/payload.js @@ -686,6 +686,19 @@ describe('Payload', () => { expect(res.result.pics).to.exist(); }); + it('places default limit on max parts in multipart payloads', async () => { + + const part = '--AaB03x\r\n' + 'content-disposition: form-data; name="x"\r\n\r\n' + 'x\r\n'; + const multipartPayload = part.repeat(1001) + '--AaB03x--\r\n'; + + const server = Hapi.server({ routes: { payload: { multipart: true } } }); + server.route({ method: 'POST', path: '/', handler: () => null }); + + const res = await server.inject({ method: 'POST', url: '/', payload: multipartPayload, headers: { 'content-type': 'multipart/form-data; boundary=AaB03x' } }); + expect(res.statusCode).to.equal(400); + expect(res.result.message).to.equal('Invalid multipart payload format'); + }); + it('signals connection close when payload is unconsumed', async () => { const payload = Buffer.alloc(1024);