La validación de entrada es el proceso de comprobar que los datos entrantes cumplen el formato, el tipo y el rango de valores esperados antes de que la aplicación los procese. Según la OWASP Input Validation Cheat Sheet (2025), la ausencia de validación es la causa raíz de la mayoría de las vulnerabilidades críticas. Comprobar los datos entrantes es la primera línea de defensa, que impide que datos incorrectos o maliciosos entren en el sistema.
Puntos clave
La validación de entrada consiste en comprobar que los datos que llegan a la aplicación desde un usuario, un servicio externo u otro componente cumplen los criterios esperados. Estos criterios incluyen el tipo de datos (cadena, número, fecha), el formato (email, URL, teléfono), el rango de valores (edad de 18 a 120), la longitud (contraseña de 8 a 128 caracteres) y los caracteres permitidos (solo letras latinas, dígitos, guion). Sin validación, la aplicación puede procesar datos que provoquen errores de ejecución, daños en los datos o vulnerabilidades de seguridad.
La ausencia de validación de entrada es la causa raíz de vulnerabilidades como SQL Injection, XSS, Command Injection, Path Traversal y Buffer Overflow. Según MITRE CWE (2025), CWE-20 (Improper Input Validation) ocupa el segundo lugar en el ranking de los errores de software más peligrosos. La validación es la primera línea de defensa en el modelo de seguridad Defense in Depth: corta los datos incorrectos antes de que lleguen a otros componentes del sistema.
La validación rechaza los datos que no cumplen los criterios. La sanitización (limpieza) modifica los datos eliminando o escapando las partes peligrosas. Por ejemplo, al introducir contenido HTML, la validación puede comprobar la longitud del texto y la sanitización eliminar las etiquetas script mediante la biblioteca HTML Purifier o DOMPurify. La sanitización no sustituye a la validación: ambas trabajan en conjunto. La validación es una política de "permitido/prohibido", mientras que la sanitización es "limpiado antes de usar".
La validación se clasifica por la profundidad de la comprobación. La validación de formato es la más sencilla y rápida, mientras que la validación de negocio es la más compleja y dependiente del contexto. Los tres niveles deben aplicarse en secuencia: primero el formato, luego la semántica y después la lógica de negocio. Omitir cualquier nivel puede provocar un funcionamiento incorrecto del sistema o vulnerabilidades.
| Nivel | Qué comprueba | Ejemplo |
|---|---|---|
| Formato | Tipo de datos, longitud, expresión regular | El email contiene @, longitud 5-100 |
| Semántica | Corrección lógica del valor | La fecha de nacimiento no es en el futuro |
| Validación de negocio | Cumplimiento de las reglas de negocio | El importe de la transferencia no supera el saldo |
Comprobación del tipo de datos, el tamaño, el formato y los caracteres permitidos. Se implementa mediante expresiones regulares, tipos integrados de los lenguajes y bibliotecas de validación. Ejemplos: comprobar un UUID (formato de 8-4-4-4-12 dígitos hexadecimales), comprobar un número de teléfono (solo dígitos, + al principio, de 7 a 15 caracteres), comprobar un número entero (valor dentro del rango Integer.MIN_VALUE — Integer.MAX_VALUE). La validación de formato es el nivel mínimo necesario para cualquier campo de entrada.
Comprobación de la corrección lógica de los datos en el contexto del dominio. Por ejemplo: la fecha de inicio no es posterior a la fecha de fin, la edad está dentro de límites razonables para el sistema, las coordenadas están dentro del área de servicio. La validación semántica requiere comprensión del contexto de negocio y no puede realizarse solo por el formato. Por ejemplo, el campo "número de entradas" puede pasar la validación de formato (entero, > 0), pero semánticamente no puede superar el número de asientos disponibles.
El nivel más complejo: comprobar que los datos cumplen las reglas de negocio de la aplicación. Ejemplos: un usuario no puede eliminar al único administrador, el importe del pedido no supera el límite de crédito, un producto solo se puede pedir si está en stock. La validación de negocio suele requerir consultas a la base de datos o a servicios externos y se realiza después de las comprobaciones de formato y semántica. Los errores de validación de negocio son la causa más frecuente de insatisfacción de los usuarios.
La validación en el cliente (en el navegador o en la aplicación móvil) sirve para la comodidad del usuario: retroalimentación inmediata sin enviar datos al servidor. Sin embargo, la validación en el servidor es la única fiable, porque el código del cliente siempre se puede eludir. Envíe las solicitudes mediante las herramientas de desarrollo, Postman o un proxy (Burp Suite), y la validación en el cliente deja de existir. Según PortSwigger Research (2025), más del 90% de las aplicaciones web probadas dependen únicamente de la validación en el cliente para al menos un campo.
La validación en el cliente puede desactivar el botón de envío, resaltar errores y mostrar pistas. La validación en el servidor es una comprobación obligatoria de cada parámetro, incluso si el cliente ya lo ha comprobado. Duplicar la validación en ambos niveles es una práctica estándar. El servidor debe comprobar los datos como si el cliente no existiera. Esto garantiza la protección frente a solicitudes modificadas, ataques automatizados y clientes maliciosos.
En la web: atributos HTML5 (required, pattern, min/max, type="email") y JavaScript. En aplicaciones móviles: validadores nativos de campos de texto (InputFilter en Android, textField(:shouldChangeCharactersIn:) en iOS). React Hook Form y Formik para React, Vuelidate para Vue, Angular Reactive Forms — bibliotecas populares para la validación en el cliente. Todas admiten reglas personalizadas y validación asíncrona (comprobación de la unicidad del inicio de sesión en el servidor).
// Ejemplo de validación en el servidor con Express y Joi
const Joi = require('joi');
const userSchema = Joi.object({
email: Joi.string()
.email()
.required()
.max(255),
age: Joi.number()
.integer()
.min(18)
.max(120)
.required(),
password: Joi.string()
.pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,128}$/)
.required()
});
app.post('/api/users', async (req, res) => {
const { error, value } = userSchema.validate(req.body);
if (error) {
return res.status(400).json({
error: error.details[0].message
});
}
// value — datos ya validados y seguros
const user = await User.create(value);
res.status(201).json(user);
});
Las aplicaciones móviles imponen requisitos especiales a la validación de datos. La pantalla es más pequeña: los errores deben ser concisos, el teclado contextual (numérico para introducir números) y la comprobación asíncrona para no bloquear la interfaz. Las plataformas nativas proporcionan mecanismos integrados de validación que deben usarse por defecto. Las Material Design Guidelines para Android y las Human Interface Guidelines para iOS contienen recomendaciones detalladas para mostrar errores de validación.
Jetpack Compose ofrece un enfoque declarativo de la validación mediante la gestión de estado. Cada campo de entrada está vinculado a un estado (MutableState) y el error se calcula a partir del valor actual. La biblioteca Compose Validator simplifica la creación de reglas: required, email, min/max length, pattern. La validación se activa al cambiar el texto (onValueChange) o al intentar enviar el formulario. Se recomienda mostrar el error solo después del primer envío o después de que el usuario haya terminado de escribir (debounce 300-500ms).
SwiftUI no tiene un mecanismo integrado de validación de formularios, pero permite implementarlo fácilmente mediante Combine y property wrappers. Use @State para el valor del campo y una propiedad calculada para el error. El framework ValidatedPropertyKit proporciona decoradores listos: @Validated().email(), @Validated().range(18...120). Recomendación de iOS: usar los tipos de teclado (UIKeyboardType.emailAddress, .numberPad) y la auto-mayúsculas para reducir la cantidad de errores a nivel de entrada.
Flutter proporciona la clase Form y TextFormField con validación integrada mediante un callback de validador. Cada campo devuelve un error como cadena o null si los datos son correctos. FormState.validate() ejecuta la comprobación de todos los campos del formulario. El paquete reactive_forms para casos complejos: validadores personalizados, comprobación asíncrona, reglas dinámicas. Flutter Web y la versión móvil usan la misma API, lo que simplifica el mantenimiento.
// Ejemplo de validación de formulario en Flutter
Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText: 'Email'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Email is required';
}
if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$')
.hasMatch(value)) {
return 'Enter a valid email';
}
return null;
},
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
// Procesar datos válidos
}
},
child: Text('Enviar'),
),
],
),
)
Los frameworks modernos proporcionan validadores integrados que cubren el 80% de las necesidades. El 20% restante requiere reglas personalizadas, expresiones regulares o la composición de las existentes. El principio clave es que la validación debe ser declarativa para poder leerse, probarse y mantenerse fácilmente. Evite la lógica de validación dispersa por controladores y pantallas: sáquela a clases o esquemas separados.
| Herramienta | Plataforma | Características |
|---|---|---|
| Joi | Node.js | Esquemas declarativos, mensajes personalizados |
| Pydantic | Python | Type hints, validación automática del modelo |
| Zod | TypeScript | Inferencia de tipos, tipado estricto |
| javax.validation | Java | Bean Validation, @NotNull, @Size, @Pattern |
| FluentValidation | .NET | API fluida, rulesets, reglas condicionales |
La lista blanca (white-list) define qué datos están permitidos; todo lo demás se rechaza. La lista negra (black-list) define qué datos están prohibidos; todo lo demás se permite. La lista blanca siempre es más fiable: sabe exactamente qué datos pasarán. La lista negra exige prever todos los ataques posibles, lo que es imposible. Ejemplo: al comprobar la edad, use la lista blanca (solo números del 18 al 120) y no la lista negra (prohibir "0", "-1", "999999").
Las expresiones regulares son una herramienta eficaz para la validación de formato, pero pueden ser fuente de ataques ReDoS (Regular Expression Denial of Service). Algunos patrones (por ejemplo, (a+)+b) provocan un retroceso catastrófico en cadenas largas, cargando por completo la CPU del servidor. Use bibliotecas regex probadas y limite la longitud de la cadena antes de aplicar una expresión regular. Para casos complejos (email, URL), use los analizadores integrados de los lenguajes en lugar de expresiones regulares caseras.
Incluso los desarrolladores con experiencia cometen errores al implementar la validación. Los más frecuentes: validación solo en el cliente, reglas demasiado estrictas (contraseña "Must contain uppercase, lowercase, digit, special char, >= 12 chars, must not repeat characters"), mensajes de error poco informativos ("Error: invalid input") e ignorar casos límite (espacios al inicio/fin, caracteres Unicode, cadenas vacías). Cada uno de estos errores empeora la UX y puede reducir la conversión de los formularios.
if (value) no distingue una cadena vacía de cero, false o "0"La mejor práctica es un sistema centralizado de validación cubierto por pruebas unitarias. Cada regla debe probarse por separado: valores límite, datos correctos, ataques típicos (intentos de SQLi, payloads XSS, cadenas muy largas). Las pruebas de regresión sobre la validación evitan el debilitamiento accidental de las reglas durante la refactorización. Use pruebas basadas en propiedades (QuickCheck, fast-check) para generar datos aleatorios y verificar que la validación no falla con una excepción.
Preguntas frecuentes
La validación rechaza los datos incorrectos, mientras que la sanitización los limpia. Por ejemplo, al introducir texto HTML, la validación comprueba la longitud máxima y la sanitización elimina las etiquetas script mediante DOMPurify. Ambos procesos son obligatorios: la validación para el control de formato y la sanitización para la seguridad de la salida.
No, nunca. La validación en el cliente se elude fácilmente mediante la interceptación y modificación de solicitudes. Use herramientas como Burp Suite o simplemente curl. La validación en el servidor es la única forma fiable de proteger el sistema. La validación en el cliente solo sirve para mejorar la experiencia del usuario.
Compruebe el tipo MIME (no solo la extensión), el tamaño del archivo y la firma (bytes mágicos al inicio del archivo) mediante la validación de firma de archivo. Nunca confíe en la extensión: renombre el archivo al guardarlo. Para las imágenes, re-codifíquelas con una biblioteca de servidor (ImageMagick, Sharp), lo que elimina el código incrustado de los datos EXIF.
ReDoS (Regular Expression Denial of Service) es un ataque en el que un atacante envía una cadena especialmente construida que provoca un retroceso catastrófico en una expresión regular. Como resultado, la CPU del servidor se carga al 100% y no se genera respuesta. Protección: limitar la longitud de la cadena, tiempos de espera para regex y usar patrones probados.
Sí, si los datos se muestran en una WebView o se usan en un contexto HTML. Si el backend está comprometido, los datos pueden contener código malicioso. Valide y sanite cualquier dato que se muestre al usuario, independientemente de la fuente. En las aplicaciones móviles, esto es especialmente importante para los componentes híbridos.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también