08 nov 2025·8 min de lectura

Validación del lado del servidor para APIs que rechazan datos sin sentido

La validación del lado del servidor para APIs evita que entren datos incorrectos. Aprende parsing seguro, esquemas, tipos estrictos y errores claros que realmente protegen la producción.

Validación del lado del servidor para APIs que rechazan datos sin sentido

Por qué tu API sigue aceptando datos sin sentido

La mayoría de las APIs que “aceptan cualquier cosa” se construyeron pensando en el caso feliz. El código asume que el cliente enviará los campos correctos, con la forma correcta y los tipos correctos. Así que cuando llega una petición con campos faltantes, campos extra, cadenas donde debería ir un número o un objeto totalmente distinto, el servidor lo fuerza en su sitio, sigue adelante y aun así devuelve 200.

Eso es especialmente común en endpoints generados por IA. A menudo deserializan JSON directamente en objetos, saltan comprobaciones estrictas y confían en que “funcionó en la demo”. El resultado es una API que parece bien en pruebas rápidas, pero se comporta de forma impredecible cuando aparecen usuarios reales, integraciones reales o atacantes.

Las comprobaciones del lado del cliente no te protegen. Los navegadores se pueden eludir, las apps móviles se pueden modificar y clientes de terceros pueden enviar cualquier payload. Incluso clientes bien intencionados pueden desincronizarse tras un lanzamiento y empezar a enviar campos que tu servidor nunca esperó.

En producción, una validación débil se transforma en problemas caros:

  • Caídas y timeouts cuando el código se encuentra con un tipo inesperado o un null
  • Registros corruptos que parecen válidos pero rompen reportes y flujos de trabajo más adelante
  • Fallos de seguridad cuando input no confiable llega a consultas, rutas de archivos o lógica de auth
  • Dolor al depurar porque la misma entrada mala falla de forma distinta en distintos puntos

El objetivo de la validación del lado del servidor para APIs es simple: rechazar la entrada mala temprano, de forma consistente y segura. Eso significa un único portón claro en el borde de tu API que compruebe forma, tipos y límites antes de que se ejecute la lógica de negocio.

A menudo los equipos acuden a FixMyMess con endpoints que “funcionan” pero aceptan basura como correos vacíos, cantidades negativas u objetos donde debería ir un ID. La solución rara vez es complicada: añadir validación estricta desde el principio para que lo absurdo nunca entre en el sistema.

Validación, sanitización y parsing: la diferencia simple

Si quieres que una API deje de aceptar tonterías, necesitas separar tres tareas que a menudo se mezclan: validación, sanitización y parsing.

La validación responde: “¿Está permitida esta entrada?” Comprueba forma y reglas: campos requeridos, tipos, rangos, longitudes, formatos y valores permitidos. Una buena validación del lado del servidor rechaza peticiones malas temprano, antes de tocar la base de datos, la lógica de auth o llamadas a terceros.

La sanitización responde: “Si esta entrada está permitida, ¿cómo la hacemos segura para almacenar o mostrar?” Ejemplos: escapar texto antes de renderizar en HTML, eliminar caracteres de control o quitar marcado inesperado. La sanitización no sustituye a la validación. Una cadena limpiada aún puede ser del tipo equivocado, demasiado larga o faltar campos clave.

El parsing (y la normalización) responden: “Convierte datos desconocidos en una forma conocida.” Decodificas JSON, conviertes cadenas a números, aplicas valores por defecto y normalizas formatos (como poner el email en minúsculas). El patrón seguro es parsear y luego usar. El patrón arriesgado es usar y luego esperar que todo vaya bien.

Un ejemplo simple: un endpoint de registro recibe age: "25" (cadena), email: "[email protected] " y role: "admin". Un flujo seguro es:

  • Parsear y normalizar: recortar el email, pasarlo a minúsculas, convertir age a número
  • Validar: age debe estar entre 13 y 120, role debe estar entre los valores permitidos
  • Solo entonces: crear el usuario

Ese “contrato de entrada estricto” (un esquema con tipos y límites claros) es la línea base. No puede prevenir todos los ataques por sí solo, pero bloquea la basura accidental, reduce bugs de casos límite y facilita acertar con las comprobaciones de seguridad.

Formas comunes en que la validación débil rompe sistemas reales

La validación débil rara vez falla de forma ordenada. Usualmente “funciona” en pruebas y luego se rompe con tráfico real porque usuarios reales, bots y clientes defectuosos envían entradas raras.

Un fallo común es el over-posting. Un cliente envía campos extra que no planeaste, y tu código los usa accidentalmente (o los almacena) porque vuelcas todo el body en una escritura de base de datos. Eso puede cambiar flags como isAdmin, modificar campos de precios o sobrescribir ajustes internos sin que nadie lo note.

Otro es la confusión de tipos. Si esperas un número pero aceptas una cadena, hay sorpresas: "10" se vuelve 10 en un sitio, sigue siendo cadena en otro, y de repente el orden, las comparaciones y las operaciones aritméticas están mal. Peor aún, "", "NaN" o "001" pueden colarse y crear casos límite difíciles de depurar.

Los límites son donde el código del “camino feliz” colapsa. Sin comprobaciones de tamaño, una sola petición puede enviar una cadena de 5 MB, un array de 50.000 ítems o JSON profundamente anidado que dispara CPU y memoria. La API puede que no caiga siempre, pero se ralentiza, hace timeouts y causa fallos en cascada.

Surgen problemas de seguridad cuando confías en la entrada demasiado pronto. Si datos no validados se usan en consultas SQL, filtros, rutas de archivos o output HTML, abres la puerta a inyecciones y fugas de datos.

Aquí hay patrones que vemos una y otra vez cuando falta validación del lado del servidor:

  • Escribir campos “desconocidos” en la base de datos porque el payload no está en una whitelist
  • Coerción implícita de tipos y luego tomar decisiones con el valor equivocado
  • Permitir cadenas/arrays sin límites, llevando a lentitud y caídas
  • Pasar input crudo a consultas o plantillas antes de comprobarlo y parsearlo

FixMyMess suele ver estos problemas en endpoints generados por IA: parecen limpios, pero aceptan casi cualquier JSON y esperan que el código downstream lo maneje. Los sistemas reales necesitan lo contrario: rechazar lo absurdo temprano, de forma clara y consistente.

Elige un enfoque de esquemas que encaje con tu stack

El objetivo de la validación del lado del servidor para APIs es simple: cada petición se comprueba contra un contrato claro antes de tocar la lógica de negocio. La forma más fácil de lograrlo es usar un esquema que valide y además parsee de forma segura las entradas a los tipos que espera tu código.

Si estás en JavaScript o TypeScript, librerías de esquemas como Zod o Joi son populares porque pueden coercer tipos cuidadosamente (cuando lo permites) y dar errores legibles. En Python, Pydantic es una elección común porque convierte datos entrantes en modelos estrictos con valores por defecto. Si ya usas un flujo OpenAPI-first o JSON Schema, mantener JSON Schema puede alinear docs y validación. Muchos frameworks también tienen validadores integrados, suficientes para APIs pequeñas.

Dónde ejecutas la validación importa. Dos patrones comunes son:

  • Middleware que valida body, query y params antes de que el handler se ejecute
  • Validación dentro de cada handler de ruta, cerca del código que usa los datos

El middleware es más fácil de mantener consistente. La validación por handler puede ser más clara cuando cada ruta tiene reglas especiales. Sea cual sea el caso, intenta hacer del esquema la única fuente de verdad para body, query strings y path params, para que no termines validando el body y olvidando los params.

Un ejemplo práctico: un endpoint espera limit (número) en la query y email (cadena) en el body. Sin un esquema, el código generado por IA a menudo acepta limit="ten" o email=[] y falla después de forma confusa. Con un esquema, eso se rechaza inmediatamente con un error limpio.

Finalmente, planifica el cambio. Cuando tu contrato de API evoluciona, versiona tus esquemas igual que versionas endpoints o clientes. Mantén esquemas antiguos para clientes antiguos e introduce nuevos esquemas con un corte claro. Esto es una corrección común que vemos en FixMyMess cuando equipos heredan prototipos hechos rápido y necesitan hacerlos seguros sin reescribir todo.

Paso a paso: añade validación del lado del servidor a un endpoint

Elige un endpoint que cause dolores, como POST /users o POST /checkout. El objetivo es que la validación del lado del servidor rechace lo absurdo antes de que se ejecute la lógica de negocio.

1) Define un esquema pequeño (solo lo que necesites)

Empieza con campos requeridos únicamente. Si el endpoint crea un usuario, quizá solo necesites email y password, no 12 campos opcionales “por si acaso”. Mantén el esquema estricto y explícito.

Valida cada fuente de entrada por separado: path params, query params y body. Trátalos como cubos distintos con riesgos distintos.

// Pseudocode schema
const bodySchema = {
  email: { type: "email", required: true, maxLen: 254 },
  password: { type: "string", required: true, minLen: 12, maxLen: 72 }
};
const querySchema = { invite: { type: "string", required: false, maxLen: 64 } };
const pathSchema = { orgId: { type: "uuid", required: true } };

2) Valida y parsea antes que cualquier otra cosa

Haz de la validación las primeras líneas en el handler. No “arregles” tipos al azar más tarde.

  • Parsear body, query y path por separado a valores tipados
  • Rechazar campos desconocidos (modo estricto) para que las claves extras no se cuelen
  • Añadir límites: min/max, límites de longitud y comprobaciones de formato simples

Un ejemplo concreto: si alguien manda { "email": [], "password": true, "role": "admin" }, el parseo estricto debe rechazarlo. No debe coercer tipos, y definitivamente no debe aceptar role si tu esquema no lo permitía.

3) Añade tests para entradas malas

Un buen test inválido vale por diez tests del camino feliz. Prueba campos faltantes, tipos erróneos, campos extra, strings enormes, números negativos y codificaciones raras. Aquí es donde el código generado por IA suele fallar, y es precisamente el tipo de arreglo que los equipos traen a FixMyMess cuando un prototipo llega a producción.

Patrones de parsing seguro que mantienen los bugs fuera

Cierra agujeros de seguridad temprano
Endurecemos endpoints contra vectores de inyección y flujos de entrada inseguros comunes en código generado por IA.

La mayoría de bugs no vienen solo de “falta de validación”, sino de lo que pasa después de validar. El hábito más seguro es parsear la entrada una vez, obtener un éxito o fallo claro, y luego trabajar únicamente con el resultado parseado.

Parsea primero y olvida la petición cruda

Una buena librería de esquemas te da una API de “safe parse”: devuelve o bien un valor parseado en el que confiar o bien un error que devolver al cliente. Esto es el núcleo de la validación del lado del servidor.

// Example shape, works similarly in many schema libraries
const result = UserCreateSchema.safeParse(req.body);
if (!result.success) {
  return res.status(400).json({ error: "Invalid input", fields: result.error.fields });
}

const input = result.data; // only use this from now on
// Never touch req.body again in this handler
createUser({ email: input.email, age: input.age });

Este cambio evita un bug común en endpoints generados por IA: el código valida, pero luego en algún punto sigue leyendo req.body y acepta campos extra, tipos equivocados o casos límite raros.

Normaliza solo cuando lo necesites

La normalización puede ayudar, pero debe ser una decisión deliberada, no un accidente.

  • Recorta strings solo para campos donde los espacios nunca tienen significado (emails, usernames).
  • Elige una regla de mayúsculas cuando las comparaciones importen (por ejemplo, emails en minúsculas).
  • Convierte fechas de cadenas a objetos Date solo si tu esquema garantiza el formato.
  • Conserva los IDs exactos; no los recortes ni los cambies salvo que tu sistema ya lo imponga.

Evita la “coerción mágica”

Ten cuidado con coerciones como convertir "123" en 123. Oculta inputs malos y dificulta detectar bugs o abusos del cliente. Coerce solo cuando realmente lo necesites (como query params que siempre son strings), y cuando lo hagas, aplica límites (min, max, solo enteros) para no aceptar tonterías como "999999999999".

Si heredaste una API generada por IA que “funciona” pero acepta basura, este patrón de parsear y luego usar únicamente los datos parseados es uno de los arreglos más rápidos y seguros.

Tipos estrictos, defaults y límites que importan

La validación estricta no es solo “¿está presente este campo?”. Se trata de hacer que tu API acepte solo las formas y valores que estás dispuesto a soportar. Una buena validación del lado del servidor empieza en el límite: body, query string y headers.

Los defaults pertenecen al borde

Establece defaults durante el parsing, no en lo profundo de la lógica de negocio. Así, todo lo que venga después puede asumir una forma completa y conocida.

Ejemplo: si falta page, asígnale 1 al parsear. No dejes que distintas partes del código decidan más tarde; acabarás con comportamientos distintos en distintos endpoints.

Decide también qué significa “faltante”. Un campo omitido no es lo mismo que un campo con null.

  • Opcional: el cliente puede omitirlo (ej.: middleName no provisto).
  • Nullable: el cliente puede enviar null (ej.: deletedAt: null cuando no está borrado).

Trátalos como casos distintos en tu esquema. Si no, tendrás bugs extraños como null pasando validación pero rompiendo código que espera una cadena.

Enums y límites evitan clases enteras de bugs

Si conoces los valores permitidos, decláralos. Los enums evitan cadenas “casi correctas” (como adminn) que crean estados ocultos.

Un ejemplo realista: un endpoint generado por IA toma status y sort de la query. Sin tipos estrictos, status=donee puede tratarse como truthy y devolver registros equivocados, y sort=DROP TABLE podría concatenarse en una consulta.

Añade límites que protejan tu base de datos y tu bolsillo:

  • Capar limit (por ejemplo, máximo 100)
  • Clampear page a 1+
  • Allowlist de campos sortBy (ej.: createdAt, name)
  • Restringir order a asc o desc
  • Poner longitudes máximas para strings (nombres, emails, términos de búsqueda)

Son arreglos comunes que aplicamos al reparar prototipos generados por IA en FixMyMess, porque el código del “camino feliz” normalmente acepta cualquier cosa y solo falla en producción cuando usuarios reales envían caos real.

Respuestas de error útiles sin revelar de más

Prevén la corrupción oculta de datos
Detectaremos over-posting, confusión de tipos y límites faltantes que causan corrupción silenciosa de datos.

Cuando la entrada está mal, tu API debe ser clara y aburrida: devuelve un 400, explica qué corregir y mantiene la forma de la respuesta igual cada vez. Una forma estable ayuda a los clientes a manejar errores sin casos especiales y evita que tu equipo filtre detalles por accidente.

Un patrón simple es un sobre de error con detalles por campo:

{
  "error": {
    "code": "INVALID_INPUT",
    "message": "Some fields are invalid.",
    "fields": [
      { "path": "email", "message": "Must be a valid email address." },
      { "path": "age", "message": "Must be an integer between 13 and 120." }
    ]
  }
}

Mantén los mensajes enfocados en lo que el llamante puede cambiar. Evita devolver el input crudo (especialmente strings que podrían contener HTML o SQL) y nunca incluyas stack traces, errores SQL, IDs internos o nombres de librerías. En lugar de "ZodError: Expected number, received string", di "age must be a number".

Las librerías de esquemas suelen dar errores detallados. Mapea esos errores a tu formato de API y mantiene los paths de campo previsibles (paths con puntos funcionan bien). Si hay muchos problemas, limita el número que devuelves (por ejemplo, los primeros 10) para que la respuesta siga siendo pequeña.

Para tu propio debugging, registra fallos de validación de forma segura. Guarda:

  • id de la petición y endpoint
  • paths de campo que fallaron (no los valores crudos)
  • metadata del llamante que ya confías (user ID, tenant)
  • una instantánea redacted del payload

Esto es un arreglo común en código generado por IA: la UI recibe feedback amigable, mientras tus logs siguen explicando por qué se rechazaron peticiones sin exponer secretos.

Trampas comunes al añadir validación

El mayor error es validar demasiado tarde. Si lees campos, construyes una consulta SQL o escribes en almacenamiento y luego compruebas los valores, el daño ya está hecho. La validación debe ocurrir en el borde: parsear, validar y solo entonces tocar el resto del código.

Otra trampa común es confiar en tipos que solo existen en tiempo de compilación. Código escrito por IA suele parecer “tipado” pero aceptar cualquier cosa en tiempo de ejecución. Una anotación UserId: string no impide que lleguen "", " " o "DROP TABLE". La validación en servidor debe ejecutarse en cada petición, no solo en tu editor.

“Permitir campos desconocidos para flexibilidad” también suele salir mal. Los campos extra se convierten en escondites para bugs, clientes confundidos y problemas de seguridad (como role: "admin" que se mezcla en tu objeto de usuario). Si necesitas compatibilidad futura, acepta solo campos conocidos y versiona la API cuando la forma cambie.

Los frameworks pueden socavar tu intención coaccionando tipos silenciosamente. Si "false" se vuelve true, o "123abc" se vuelve 123, enviarás lógica que es difícil de reproducir. Prefiere parseo estricto que falle rápido con un error claro.

Finalmente, muchos equipos olvidan los límites, así que la validación pasa pero el servidor sigue sufriendo. Unas pocas protecciones básicas previenen abusos y accidentes:

  • Limita el tamaño del body y rechaza payloads sobredimensionados temprano.
  • Pon máximos de longitud para strings (nombres, emails, IDs).
  • Limita arrays (ítems por petición) y la profundidad de anidamiento de objetos.
  • Requiere formatos explícitos (UUIDs, fechas ISO) y rechaza “cercano suficiente”.
  • Mantén defaults intencionales; no rellenes campos faltantes de formas que oculten bugs del cliente.

Un ejemplo práctico: un endpoint generado por IA que “actualiza perfil” podría aceptar un bio de 5MB, un objeto anidado donde se esperaba una cadena y claves desconocidas que sobrescriben datos almacenados. Ese es el tipo de limpieza que FixMyMess suele encontrar en auditorías: la validación existe, pero es permisiva en los lugares equivocados.

Lista rápida para entradas de API más seguras

Si quieres que la validación del lado del servidor bloquee datos malos, mantén una checklist corta y úsala en cada endpoint que toques. La mayoría de bugs “funciona en mi máquina” vienen de saltarse una de estas bases.

Empieza validando cada superficie de entrada, no solo bodies JSON. Query strings y route params también son no confiables y a menudo controlan filtros, IDs y paginación.

Usa esta checklist como tu mínimo:

  • Valida body, query y params antes de lógica de negocio o llamadas a la base de datos.
  • Prefiere allowlists: rechaza campos desconocidos a menos que necesites payloads flexibles.
  • Pon límites rígidos en todas partes: longitud máxima de strings, rangos numéricos, tamaños de arrays y límites de paginación.
  • Parsear a un objeto tipado y validado y usar solo ese output parseado. Si el parseo falla, falla cerrado.
  • Añadir unos cuantos casos de prueba desagradables por endpoint: tipos erróneos, campos obligatorios faltantes, campos extra y inputs sobredimensionados.

Un ejemplo rápido: tu endpoint espera { "email": "...", "age": 18 }. Una petición real podría mandar age: "18", age: -1, o añadir "isAdmin": true. Si coaccionas tipos en silencio o aceptas claves extra, estás entrenando a tu sistema a aceptar basura y, peor aún, a otorgar privilegios.

Si heredaste código de API generado por IA, esta checklist es el punto de partida. Los equipos que trabajan con FixMyMess suelen encontrar el mismo patrón: el camino feliz funciona, pero el servidor confía en lo que llega. Validación estricta más parseo estricto es una de las formas más rápidas de convertir un prototipo frágil en algo seguro para producción.

Ejemplo: arreglando un endpoint construido por IA que acepta basura

Auditoría de código gratuita para APIs
Revisamos tus rutas de mayor riesgo y entregamos un plan claro antes de cualquier compromiso.

Una historia común: una herramienta de IA genera un endpoint /signup que "funciona localmente" porque solo probaste el camino feliz. En producción empieza a aceptar tonterías y el daño es silencioso.

Aquí hay un patrón real de fallo. El endpoint espera:

  • email (string)
  • password (string)
  • plan ("starter" | "pro")

Pero la API acepta felizmente este payload:

{ "email": ["[email protected]"], "password": true, "plan": "pro ", "coupon": {"code":"FREE"} }

Lo que pasa luego es un caos: el email acaba como "[email protected]" (array stringificado), el password booleano se coacciona, el plan tiene un espacio final y la facturación usa el valor por defecto, y el objeto inesperado coupon podría almacenarse como "[object Object]" o hacer que un job posterior falle. Ves auth rota, facturación equivocada y filas corruptas difíciles de limpiar.

La solución no es "sanitizarlo todo". Es validación del lado del servidor con parseo estricto.

Paseo de la corrección

Define un esquema que rechace campos desconocidos, recorte y normalice strings y haga cumplir los tipos. Luego parsea antes de hacer cualquier trabajo.

  • Valida campos requeridos y tipos (sin coerción por defecto)
  • Normaliza valores seguros (trim a plan, lower-case a email)
  • Rechaza extras (fallar o denegar coupon)
  • Aplica límites (longitudes máximas, reglas de password)

Si el parseo falla, devuelve un 400 claro:

"Invalid request: plan must be one of starter, pro; email must be a string; unexpected field coupon"

Resultado final: menos incidentes en producción, datos más limpios y debugging más rápido porque las entradas malas se detienen en la puerta. Si heredaste un endpoint así, FixMyMess suele encontrar estos puntos débiles en una auditoría rápida y parchearlos sin reescribir toda la app.

Próximos pasos: mejorar la seguridad sin reescribir todo

Si quieres que la validación del lado del servidor te dé resultados rápidos, no empieces por "validar todo". Empieza donde las entradas malas causan daño real: endpoints que escriben datos o desencadenan trabajo caro.

Elige tres endpoints primero. Un buen conjunto es login o signup (auth), cualquier cosa que toque dinero (pagos) y cualquier acción de admin. Añade validación en el borde (request body, query, headers) antes de tocar tu base de datos, archivos, colas o APIs de terceros. Ese único movimiento evita la mayoría de bugs de “aceptar tonterías”.

Un plan de despliegue simple que evita rehacer todo:

  • Añadir un esquema por endpoint y rechazar campos desconocidos por defecto.
  • Poner límites estrictos (longitud de strings, tamaño de arrays, rangos numéricos, tamaño máximo de página).
  • Normalizar y parsear una vez (trim, parsing de fechas, coerción de números solo si es intencional).
  • Añadir monitorización para fallos de validación y ver qué están enviando los clientes.

Los clientes legacy son la parte complicada. Si no puedes romperlos de la noche a la mañana, permite una laxitud temporal controlada: acepta la forma vieja pero conviértela a la nueva forma estricta internamente y registra cada vez que tuviste que “rescatar” una entrada. Pon una fecha de deprecación explícita para que no se convierta en permanente.

Si tu API fue generada por una herramienta de IA y el código ya se siente enmarañado (handlers copiados, tipos inconsistentes, bugs ocultos de auth), una auditoría focalizada suele ser más rápida que parchear endpoint por endpoint. FixMyMess puede hacer una auditoría de código gratuita y luego reparar las rutas de mayor riesgo (validación, auth, secretos y seguridad) para que llegues a “seguro por defecto” sin un rebuild completo.