Poluição de Protótipo
Bloqueie ataques de poluição de protótipo a partir de JSON não confiável - _.merge inseguro, Object.assign e parsers recursivos podem envenenar todos os objetos do seu processo.
Busque em todas as páginas da documentação
Bloqueie ataques de poluição de protótipo a partir de JSON não confiável - _.merge inseguro, Object.assign e parsers recursivos podem envenenar todos os objetos do seu processo.
Cartão de receita de referência rápida - pronto para copiar e colar.
import { z } from "zod";
// Prefira parse em vez de merge para modelagem de requisição
const SettingsSchema = z.object({
theme: z.enum(["light", "dark"]).optional(),
notifications: z.boolean().optional(),
});
function updateSettings(body: unknown) {
return SettingsSchema.parse(body);
}Quando usar isto:
_.merge, _.defaultsDeep, ou atribuição profunda personalizada em req.body.lodash para poluição de protótipo.?a[b][__proto__][x]=1).import { z } from "zod";
// VULNERÁVEL - não faça isso com entrada não confiável
function vulnerableMerge(target: Record<string, unknown>, source: unknown) {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const _ = require("lodash");
return _.merge(target, source);
}
// SEGURO - esquema explícito, sem chaves de protótipo
const PatchSchema = z.object({
displayName: z.string().min(1).max(80).optional(),
locale: z.string().regex(/^[a-z]{2}$/).optional(),
}).strict();
function safePatch(body: unknown) {
return PatchSchema.parse(body);
}
// SEGURO - atribuição superficial com lista de bloqueio se você precisar mesclar
function safeShallowAssign<T extends Record<string, unknown>>(
target: T,
source: unknown
): T {
if (typeof source !== "object" || source === null || Array.isArray(source)) {
throw new Error("Fonte inválida");
}
for (const key of Object.keys(source)) {
if (["__proto__", "constructor", "prototype"].includes(key)) continue;
target[key as keyof T] = (source as Record<string, unknown>)[key] as T[keyof T];
}
return target;
}
// Demonstração: tentativa de ataque falha Zod strict()
const attack = JSON.parse('{"displayName":"Ada","__proto__":{"isAdmin":true}}');
safePatch(attack); // lança erro - chave desconhecida em modo strictO que isso demonstra:
_.merge copia recursivamente chaves __proto__ para protótipos em versões vulneráveis..strict() rejeita chaves desconhecidas, incluindo __proto__.JSON.parse em si é seguro - o perigo está onde você atribui os valores analisados.Object.prototype.{"__proto__": {"polluted": true}} ou {"constructor": {"prototype": {"polluted": true}}}.Object.prototype.polluted = true.{} podem então parecer ter polluted - afetando verificações de autenticação, if (obj.isAdmin), etc.| API | Risco |
|---|---|
_.merge, _.defaultsDeep | CVEs históricos; evite em JSON de usuário |
Object.assign(target, userInput) | Copia a chave __proto__ em alguns motores/caminhos |
| Parsers recursivos personalizados | Devem pular __proto__, constructor, prototype |
Parsers de query flat | qs com allowPrototypes: false |
npm ls lodash
npm auditlodash 4.17.21+ corrigido.structuredClone de DTOs validados em vez de mesclagem._.mergeWith e rejeite chaves perigosas no customizador.if (Object.prototype.hasOwnProperty("isAdmin")) {
throw new Error("Poluição de protótipo detectada");
}merge(, defaultsDeep, Object.assign(req.body.req.body para Mongoose/Prisma create - atribuição em massa + poluição. Correção: Analise com Zod para DTO primeiro.allowPrototypes: true (padrão em configurações antigas) - poluição de query. Correção: allowPrototypes: false.additionalProperties: true - aceita __proto__. Correção: additionalProperties: false ou Zod strict.__proto__ - o caminho constructor.prototype também funciona. Correção: Bloqueie todas as três chaves.| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| Zod parse | Modelagem de corpo/query HTTP | Necessidade de patch profundo de arquivos de configuração aninhados (use esquema por caminho) |
| JSON Schema strict | Rotas Fastify | Chaves arbitrárias dinâmicas |
| Structured clone de árvore validada | Copiar objetos seguros | Antes da validação |
| Map em vez de objeto | Chaves de usuário arbitrárias | API JSON ainda usa objetos na fronteira |
Sim. A vulnerabilidade está em atribuir valores analisados a objetos existentes por meio de utilitários de mesclagem inseguros.
Congelar Object.prototype é possível em teoria, mas quebra muitas bibliotecas. Prefira validação de entrada.
JSON Schema com additionalProperties: false rejeita chaves extras. O mesmo que Zod strict.
Se o código verificar if (user.isAdmin) e o atacante poluir Object.prototype.isAdmin = true, sim. Raro, mas catastrófico.
Execute @lavamoat/lavapack ou vetores de teste de poluição de protótipo dedicados contra seus utilitários de mesclagem.
Qualquer biblioteca de definição profunda em caminhos não confiáveis é arriscada. Permita segmentos de caminho.
Valide variáveis com Zod ou graphql-constraint-directive antes que os resolvedores mesclem em objetos.
A mesclagem do ramda tem preocupações semelhantes. A validação de esquema na fronteira é a verdadeira correção.
Versões da Pilha: Esta página foi escrita para Node.js 24.18.0 (LTS Ativo), npm 10+, TypeScript 5.6+, Express 5, Fastify 5, e NestJS 11.
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026