whitelist strips any property that has no validation decorator from the incoming object. forbidNonWhitelisted turns that stripping into an error response. Together they stop clients from sneaking extra fields, like role or isAdmin, into your DTOs. Turn them on globally with app.useGlobalPipes.
Definitions
According to the NestJS validation documentation:
| Option | Effect |
|---|---|
| whitelist | Properties not included in the whitelist are stripped from the resulting object. With true, properties without any validation decorator are removed |
| forbidNonWhitelisted | Used with whitelist. Instead of stripping, the validator throws an exception |
| transform | Converts payloads into instances of their DTO classes, and converts primitive route params such as a string id to a number |
| disableErrorMessages | Validation errors are not returned to the client |
The docs say to start by binding ValidationPipe at the application level so every endpoint is protected from invalid data.
Why extra fields are a security issue
Mass assignment happens when code copies a whole request body into a model. If the body contains a field you never meant to be settable, it gets written. Whitelisting is a guardrail at the edge: only declared fields survive. It is not a replacement for authorization checks, but it removes a whole class of accidents.
A global setup
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
transform: true,
disableErrorMessages: true,
}),
);
This mirrors the example in the NestJS docs. Think about each flag before copying it.
Choosing between strip and reject
| Choice | Pros | Cons |
|---|---|---|
| whitelist only | Tolerant of older clients that send extra fields | Silent, so mistakes go unnoticed |
| plus forbidNonWhitelisted | Loud, finds integration bugs and probing | Breaks clients that send harmless extras |
For a public API, rejecting is a useful signal, since a request with unknown fields is either a bug or a probe. Log those rejections.
disableErrorMessages tradeoff
Returning detailed validation messages helps legitimate developers fix requests, and also helps attackers learn your schema. The docs note some production environments prefer to hide them. A middle path: detailed errors in development and staging, generic ones in production, plus request ids for support.
Steps
- Put a class with decorators on every request DTO. A DTO with no decorators is whitelisted down to nothing under whitelist true.
- Enable the global pipe in main.ts.
- Add a test that posts an unexpected field and checks the response.
- Review nested objects. Nested DTOs need their own validation setup to be checked.
- Keep authorization separate. Validation says what shape is acceptable, not who may send it.
Try it yourself
Click through it at your own pace, or open it full screen.
Click through the findings and look for ones about input validation and unexpected fields.
Safeguard's API security scanning and dependency scanning can check your endpoints and the class validation packages behind them. Free scan: gold.safeguard.sh/scan. For broader framework guidance see NestJS security guide.
Quick check
Does whitelist true protect against prototype pollution?
It strips undeclared properties on validated DTOs, which helps, but pollution depends on how you merge data. See the prototype pollution posts for object handling.
Why did my DTO become empty after enabling whitelist?
Properties without any validation decorator are removed. Add at least one decorator to each field you want to keep.
Sources
Last reviewed: 19 October 2026.