Closed qwang07 closed 1 year ago
I tried something like this, but all error details are combined together:
import Joi from "joi"
const text = `{"b": "abc", "c": true}`
const schema = Joi.custom(jsonParse(Joi.object({
a: Joi.string().required(),
b: Joi.number(),
c: Joi.bool(),
})))
const result = schema.validate(text, { abortEarly: false })
console.log(result.error)
function jsonParse(schema) {
return (value) => {
const json = JSON.parse(value)
const result = schema.validate(json, { abortEarly: false })
if (result.error) {
console.log(result.error)
throw result.error
}
return result.value
}
}
// Output:
[Error [ValidationError]: "value" failed custom validation because "a" is required. "b" must be a number] {
_original: '{"b": "abc", "c": true}',
details: [
{
message: '"value" failed custom validation because "a" is required. "b" must be a number',
path: [],
type: 'any.custom',
context: [Object]
}
]
}
I have done this with extend()
.
import Joi from 'joi'
const custom = Joi.extend(
{
type: 'object',
base: Joi.object(),
coerce: {
from: 'string',
method(value) {
if (value[0] !== '{' || !/^\s*\{/.test(value)) {
return
}
try {
return { value: JSON.parse(value) }
} catch (ignoreErr) { }
}
}
},
{
type: 'array',
base: Joi.array(),
coerce: {
from: 'string',
method(value) {
if (value[0] !== '[' || !/^\s*\[/.test(value)) {
return
}
try {
return { value: JSON.parse(value) }
} catch (ignoreErr) { }
}
}
}
)
export default custom
@qwang07 In the past joi
used to do this automatically for you (pre v16
). However there are security concerns that were overlooked at that time that led to a security vulnerability. You can find more information about this here: https://fastify.dev/docs/latest/Guides/Prototype-Poisoning/ as this was written by Eran Hammer after discovering the issue and fixing it.
With the current solution you posted above, you open yourself to a potential prototype pollution attack on your server. There are other conditions for such attack to be successful but at least you satisfy already one of the criteria. Eran wrote some examples for people that want to bring back such feature as you did, you can find a screenshot of it here: https://github.com/hapijs/joi/issues/2129#issuecomment-533004092 along with a link to the source. You'll notice that he doesn't use JSON.parse
but rather Bounce.parse
for that specific reason. If you read the Fastify article, you'll understand why.
I hope this helps.
Thanks a lot
You're welcome. 😉
Support plan
Context
How can we help?
In my project, some of the inputs are mixed with different types of input. The
object
to be validated is sent as astring
, so I need to convert them toJSON
using theJSON.parse
method before validation. Is there any way inJoi
to convert these inputs before validation?