class-validator: fix: "an unknown value was passed to the validate function"
Description
After updating class-validator from 0.13.2 to 0.14.0, we get an error when consuming GraphQL API:
error: "Bad Request"
message: ["an unknown value was passed to the validate function"]
statusCode: 400
Minimal code-snippet showcasing the problem
import {
Field,
InputType,
Int,
ObjectType,
ReturnTypeFuncValue,
} from '@nestjs/graphql'
import { IsOptional, IsPositive } from 'class-validator'
@InputType()
export class PaginationInfo {
@Field(() => String, { nullable: true })
before: string | undefined
@Field(() => String, { nullable: true })
after: string | undefined
@IsOptional()
@IsPositive()
@Field(() => Int, { nullable: true })
first: number | undefined
@IsOptional()
@IsPositive()
@Field(() => Int, { nullable: true })
last: number | undefined
}
Expected behavior
We expect to get a response, as with 0.13.2
Actual behavior
An error described above is thrown
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 65
- Comments: 42 (8 by maintainers)
Commits related to this issue
- fix: disable forbid unknow values (#750) Due to [a deserialization issue](https://github.com/typestack/class-validator/issues/1873) caused by `class-validator` `0.14.0`, disable `forbidUnknownValue... — committed to apitable/apitable by deleted user a year ago
- fix(json-api-nestjs): fix enum and class validator 1. Fix correct ajv schema for enum type of type orm 2. Add forbidUnknownValues for class-validator(https://github.com/typestack/class-validator/issu... — committed to klerick/nestjs-json-api by klerick a year ago
In my case, my class property has a nested validation. Typing with class transformer
@Typedecorator resolved.seems updating @nestjs/common to 9.3.9 will fix the problem
+1
In NestJs, I got the same error but I was sending correct payload, without Unkown values, that makes no sense.
Why the value of
forbidUnknownValueschanged between 0.13 and 0.14 that caused a breaking change for everyone is in a minor version and not in a major?We have several microservices using NestJS and this was happening to us for one particular endpoint. In our scenario, we had a property on our DTO that had no validation decorators on it. So for example:
became:
Which resolved the issue. Hope that helps
as you’re using nestjs, in your main.ts you can update your ValidationPipe creation as follow :
app.useGlobalPipes(new ValidationPipe({ forbidUnknownValues: false }))please add a 👍 in the PR description instead of spamming with +1 comments 😃
I agree with @marlon-chagas - even with correct payload I had to disable
forbidUnknownValues- something wrong here I think…Yes. It is total mess, and solutions are available only for NestJS.
Downgrade to:
fix problem.
The Changelog mentions the
forbidUnknownValuesParameter to has a new default:true. (https://github.com/typestack/class-validator/blob/develop/CHANGELOG.md#breaking-changes). So you’ll have to set it tofalsemanually in your respective options.Edit; Please read the comments below. This could lead to a vulnerability.
Hello guys, i found i guess the solution, in my DTO after add a class-validator this work very well.
wihout the validator in the DTO fields, i receve the error.
what about non-NestJs users, it still makes no sense to set
forbidUnknownValues: false, is there a solution for that? in the0.13.xwe could send context in thevalidationOptionsat least can we have this back?Nice find!
I’m no security expert, but the implication of allowing unknown values is that attackers could attach some sneaky extra stuff into an otherwise valid payload. Depending on the architecture of your application this could potentially allow them to give themselves heightened access or just simply corrupt the integrity of your database. Document databases like MongoDB and Firestore will typically allow you to save anything in there since there’s no strict schema to adhere to.
Of course, it’s entirely possible that your application discards any extra fields from the input and I don’t see a security issue in that case:, but in a way it’s a bit scary to have to rely on future developers to remember this quirk when designing the code and it is arguably quite tedious:
See Semantic Versioning’s specification for version zero:
On top of that I believe there is an unwritten convention for version zero releases to use minor version changes (0.13 -> 0.14) to reflect breaking changes, and patch versions (0.13.1 -> 0.13.2) for non-breaking changes. This gives users some predictability.
@Hatko – does the issue still persist even if your validation classes are set up to respect
forbidUnknownValues?I suppose it is possible that production builds is attaching something. Need to check the output.
I was facing this issue too, on NestJS, here is what was wrong First of all for easier debugging use this
app.useGlobalPipes( new ValidationPipe({ exceptionFactory: (e) => console.log(e), whitelist: true, transform: true, forbidUnknownValues: true, validateCustomDecorators: true, disableErrorMessages: isProduction, forbidNonWhitelisted: true, transformOptions: { enableImplicitConversion: true, }, }), );And I would attach a debugger to figure out more info about the issue.My issue was using a custom MongoDB ID pipe to transform params, here is the implementation
` import { PipeTransform, Injectable, ArgumentMetadata, HttpException, HttpStatus, } from ‘@nestjs/common’; import { Types } from ‘mongoose’;
@Injectable() export class MongoDBIDPipe implements PipeTransform { transform(mongoDBID: string, _: ArgumentMetadata) { if (!Types.ObjectId.isValid(mongoDBID)) { throw new HttpException(
validation.invalidMongoDBID, HttpStatus.NOT_ACCEPTABLE, ); } return mongoDBID; } }`
this returns a string because that’s how it arrives at the controller handler, but I wrote the type as Types.ObjectId, like this
` @UserID(new ValidationPipe({ validateCustomDecorators: true })) userID: string,
` and that was causing the error to be thrown but I still didn’t figure out how it relates to the DTO
Similarly, if you are doing some mapping from the input types onto another type after validation, you will have to be careful never to use the spread operator:
I think the preferable option is to forbid unknown values since you will know that the shape of the object is what you think it is after validation.
It doesn’t make sense to close the issue when there are plenty of people having this issue.
I understand the semantic version but I didn’t know that increasing a version would break something that was working correctly. It seems you’re stating that this breaking change was on purpose, if so, could you please point out which one is it and how to address it?
I’ll try to create a sample of an app emulating this issue and I’ll share it later here.
Thanks!
I’m having the same error when using version
0.14.0, but not when moving to0.13.2, however this version has a critical severity vulnerability, any idea when a patched version will be released?In my case I’m using NestJS with class-validator and when the backend tries to validate the object an error with the message
an unknown value was passed to the validate functionis being raised.Thanks!
@eneilson thank you for pointing the way to dig. Your suggestion fixes the issue and seems like it’s because by default
class-validatordoesn’t transform nested objects to class instances.In my case, the fix was a bit more complicated because I have a field containing a JSON string that I parse to an object using another decorator based on
Transformfromclass-transformer. Adding theTypedecorator did nothing because it seems to conflict withTransform(what it actually uses under the hood).The simplest way to debug if the nested objects were parsed correctly is to log the parent DTO to the console and examine the value of the nested field. If it’s just a plain object then
class-validatorwill throw the “unknown value” error. If there’s something likefoo: FooClass { foo: 'bar' }then everything should work as expected.