flawopen.com/Desserialização insegura/TypeNameHandling
Newtonsoft.Json TypeNameHandling: configuração segura para JSON não confiável?
JSON comum descreve dados; seu código escolhe o tipo .NET. Com TypeNameHandling ativado, $type pode influenciar a resolução de tipos durante a desserialização. Use None para entradas não confiáveis. Se precisar de polimorfismo, valide tipos com um ISerializationBinder restrito ou use um mapeamento fechado de discriminadores declarado no código.
var settings = new JsonSerializerSettings {
// Any non-None mode needs a strict binder
TypeNameHandling = TypeNameHandling.Auto,
// No binder: input $type can resolve CLR types
};
var value = JsonConvert.DeserializeObject<Base>(
untrustedJson, settings);
// Safest default for untrusted JSON var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.None, }; // For polymorphism, dispatch over a closed set: var token = JObject.Parse(json); Base value = token["kind"]?.ToString() switch { "circle" => token.ToObject<Circle>(), "square" => token.ToObject<Square>(), _ => throw new JsonException("Unknown kind"), }; // System.Text.Json also supports opt-in derived // types through [JsonDerivedType] (.NET 7+).
Por que desenvolvedores ativam TypeNameHandling
Dados polimórficos são o motivo comum: uma coleção Shape pode precisar voltar como Circle ou Square. Json.NET lê e grava nomes de tipos por $type. Em entradas não confiáveis, esses metadados podem influenciar o tipo resolvido; o risco depende dos tipos permitidos e do comportamento na desserialização. Uma cadeia perigosa exige um tipo acessível com efeitos colaterais; JSON por si só não basta.
A fronteira de confiança deve funcionar no sentido oposto: o código escolhe um subtipo de um conjunto fechado de discriminadores validados. System.Text.Json oferece polimorfismo opt-in por atributos como [JsonDerivedType]; não ativa nomes CLR arbitrários do JSON. Consulte a orientação sobre BinaryFormatter para uma fronteira relacionada.
Um ISerializationBinder personalizado é suficiente?
Um ISerializationBinder restrito é a defesa exigida pelo Json.NET quando TypeNameHandling não é None para dados externos. Mapeie apenas poucos nomes exatos, pertencentes à aplicação, e rejeite os demais. Revise tipos, conversores, construtores, setters e callbacks. O binder restringe a resolução, mas não torna tipos arbitrários inofensivos. Prefira None e despacho explícito se controlar o protocolo.
Perguntas frequentes
Não por si só. Auto pode ler $type durante a desserialização. Use TypeNameHandling.None ou um ISerializationBinder restrito que permita apenas tipos revisados.
Sim, opt-in, com discriminador e tipos derivados declarados no código, como [JsonDerivedType] no .NET 7+. O conjunto é limitado pelo código, não por nomes CLR arbitrários no conteúdo.
Pesquise TypeNameHandling, SerializationBinder e JsonConvert.DeserializeObject em toda a solução. Inclua inicialização ASP.NET e configurações compartilhadas; rastreie endpoints que passam JSON externo e confirme binder estrito em todo caminho diferente de None.
Referências
- Json.NET — Configurações de serialização: TypeNameHandling e SerializationBinder
- API Json.NET — ISerializationBinder
- Microsoft Learn — Polimorfismo em System.Text.Json
- CWE-502 — Desserialização de dados não confiáveis
- FlawOpen — BinaryFormatter do .NET é seguro?