← Journal technique

backend

La validation des DTO comme vraie frontière de sécurité

La validation des DTO comme vraie frontière de sécurité

class-transformer transforme un corps JSON entrant en une vraie instance de classe ; class-validator exécute contre elle des règles déclarées par décorateurs. Câblé dans le ValidationPipe de NestJS, un contrôleur déclare sa forme attendue une fois comme une classe et obtient la validation des requêtes gratuitement.

export class CreateApplicationDto {
  @IsUUID()
  program_id: string;

  @IsOptional()
  @IsUUID()
  child_id?: string;
}
app.useGlobalPipes(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }));

Les options de whitelist sont le cœur

whitelist: true retire toute propriété non déclarée sur le DTO avant qu'elle n'atteigne la couche service. forbidNonWhitelisted: true rejette toute la requête au lieu de retirer silencieusement les extras.

C'est une vraie frontière de sécurité, pas de la propreté. Sans elle, un client qui envoie { ..., role: "admin" } sur un endpoint de mise à jour d'utilisateur passe si le service étale négligemment le corps dans un appel de mise à jour. Le mass assignment, fermé à la validation plutôt que confié à chaque handler individuel qui doit s'en souvenir.

J'ai appris le revers de ça à la dure : un DTO avec import type au lieu de import, ou une propriété sans aucun décorateur, n'est pas reconnu sous whitelist: true — donc le pipe retire la charge entière et l'endpoint rejette chaque champ avec une erreur confuse « propriété non reconnue ». J'ai rencontré cette forme de bug dans trois fichiers différents pour trois raisons différentes avant d'arrêter de les corriger un par un et de greper toute la base de code pour le motif.

Au-delà des vérifications de champ : @ValidateNested() + @Type(() => NestedDto) pour les objets imbriqués, @ValidateIf pour les règles conditionnelles, et des validateurs personnalisés pour les formats propres au domaine — un motif de pièce d'identité, un format de téléphone — pas juste des vérifications de type génériques. Les DTO font aussi office de documentation, et NestJS peut générer du Swagger directement depuis les décorateurs.