flawopen.com/Deserialización insegura/TypeNameHandling
Newtonsoft.Json TypeNameHandling: configuración segura para JSON no confiable?
El JSON describe datos; tu código elige el tipo .NET. Con TypeNameHandling activado, $type puede influir en la resolución de tipos al deserializar. Usa None para entradas no confiables. Si necesitas polimorfismo, valida los tipos con un ISerializationBinder estricto o usa un mapeo cerrado de discriminadores declarado en el 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 qué los desarrolladores activan TypeNameHandling
El motivo habitual son los datos polimórficos: una colección Shape puede tener que conservarse como Circle o Square. Json.NET lee y escribe nombres de tipo mediante $type. Con entradas no confiables, esos metadatos pueden influir en el tipo resuelto; el riesgo depende de los tipos permitidos y su comportamiento al deserializar. Una cadena peligrosa requiere un tipo alcanzable con efectos secundarios; el JSON por sí solo no basta.
El límite de confianza debe funcionar al revés: el código selecciona un subtipo de un conjunto cerrado de discriminadores validados. System.Text.Json permite polimorfismo opt-in mediante atributos como [JsonDerivedType]; no activa nombres CLR arbitrarios del JSON. Consulta la guía de BinaryFormatter para un límite relacionado.
¿Basta con un ISerializationBinder personalizado?
Un ISerializationBinder estricto es la defensa requerida por Json.NET cuando TypeNameHandling no es None para datos externos. Asocia solo unos pocos nombres exactos, propios de la aplicación, y rechaza el resto. Revisa los tipos permitidos, convertidores, constructores, setters y callbacks. El binder limita la resolución, pero no vuelve inocuos los tipos arbitrarios. Si controlas el protocolo, prefiere None y el despacho explícito.
Preguntas frecuentes
No por sí solo. Auto puede leer $type al deserializar. Usa TypeNameHandling.None o un ISerializationBinder estricto que solo permita tipos revisados.
Sí, de forma opt-in, con discriminador y tipos derivados declarados en código, como [JsonDerivedType] en .NET 7+. El código limita el conjunto, no nombres CLR arbitrarios del contenido.
Busca TypeNameHandling, SerializationBinder y JsonConvert.DeserializeObject en toda la solución. Incluye el inicio de ASP.NET y la configuración compartida; sigue los endpoints que pasan JSON externo y confirma un binder estricto en cada ruta distinta de None.
Referencias
- Json.NET — Configuración de serialización: TypeNameHandling y SerializationBinder
- API de Json.NET — ISerializationBinder
- Microsoft Learn — Polimorfismo en System.Text.Json
- CWE-502 — Deserialización de datos no confiables
- FlawOpen — ¿Es seguro BinaryFormatter de .NET?