Validación segura de URL en JavaScript
Mannan Tirmizi
9 de mayo de 2023
0 minutos de lecturaNota del editor: 9 de mayo de 2023
Esta publicación, originalmente publicada el 18 de octubre de 2022, se actualizó para mostrar cómo Snyk puede ayudarte a establecer una validación segura de URL en JavaScript.
Cuando los desarrolladores necesitan trabajar con URL en distintos formatos y para diferentes propósitos —como la navegación por el historial del navegador, los destinos de anclaje, los parámetros de consulta, entre otros—, solemos recurrir a JavaScript. Sin embargo, su uso frecuente motiva a los atacantes a explotar sus vulnerabilidades. Este riesgo de explotación hace que debamos implementar la validación de URL en nuestras aplicaciones JavaScript.
La validación de URL comprueba si las URL siguen la sintaxis adecuada, es decir, la estructura que debe tener cada URL. Puede proteger nuestras aplicaciones contra vulnerabilidades relacionadas con URL, como la inyección de scripts maliciosos y la falsificación de solicitudes del lado del servidor (SSRF). Los actores maliciosos pueden llevar a cabo ataques SSRF cuando no aplicamos prácticas de codificación segura para validar las URL proporcionadas por los usuarios al obtener un recurso remoto. La SSRF sigue siendo una amenaza crítica para las aplicaciones basadas en JavaScript, tanto en el frontend como en las aplicaciones del lado del servidor con Node.js, y fue una categoría destacada en la lista OWASP Top 10 de 2021.
Validación de URL
La validación de URL fortalece la seguridad frente a posibles exploits y elimina la posibilidad de que surjan errores al ejecutar el código. Pero ¿cuándo debemos usar la validación de URL y qué validamos durante el proceso? Debemos implementar la validación de URL en todo software que deba identificar y verificar recursos como páginas, imágenes, GIF y videos.
Una URL típica consta de varios fragmentos, como el protocolo, el nombre de dominio, el nombre de host, el nombre del recurso, el origen, el puerto, entre otros. Estos le indican al navegador cómo obtener el recurso específico. Podemos usarlos para validar URL de varias maneras:
Uso de literales y constructores de expresiones regulares
Constructores de URL
Método
isValidURLElementos de entrada
Método de la etiqueta de anclaje
Un esquema típico de validación de URL recibe datos de un usuario y luego los analiza para identificar sus distintos componentes. El esquema puede verificar que todos los componentes de la URL cumplan con los estándares de Internet. Por ejemplo, si es necesario, puede comprobar si la URL usa un protocolo seguro.
La validación del nombre de host comienza por dividirlo en etiquetas separadas para verificar que cumplan con la especificación de nombres de dominio de nivel superior. Un nombre de host típico consta de al menos dos etiquetas separadas por puntos. Por ejemplo, www.snyk.com tiene las etiquetas “www”, “snyk” y “com”. Cada etiqueta solo puede contener caracteres alfanuméricos o guiones, sin importar si están en mayúsculas o minúsculas. Luego, el esquema de validación puede comprobar que el nombre de host coincida con una lista de URL permitidas, para asegurarse de que solo se admitan las URL designadas y no se rechacen por error las URL permitidas.
La mayoría de las rutas a los recursos que se usan en las URL están permitidas de forma predeterminada. Sin embargo, los puertos solo pueden estar en el rango de 1 a 65536. Cualquier valor fuera de ese rango debe generar un error. También podemos comprobar las direcciones IP numéricas para determinar si son IPv4 o IPv6.
Por último, aunque no sea evidente al principio, también podemos comprobar si las URL contienen nombres de usuario y contraseñas. Esta función ayuda a cumplir las políticas de la empresa y a proteger las credenciales.
Ahora que conoces los conceptos básicos, ¡veamos cómo validar URL con JavaScript!
Cómo validar una URL en JavaScript
La forma más sencilla de validar una URL en JavaScript es usar la función constructora new URL. Además de ser simple, es compatible con el entorno de ejecución de Node.js y con la mayoría de los navegadores.
La sintaxis básica es la siguiente:
JavaScript solo requiere el elemento base si proporcionamos una URL relativa. Si no lo hacemos, su valor predeterminado es undefined. Como alternativa, si proporcionamos un elemento base con una URL absoluta, JavaScript ignora el elemento base.
Para validar la URL, se puede usar la siguiente función:
Esta función comprueba si una URL es válida: devuelve true si lo es y false si no. Si le pasas www.urlcheck.com, devolverá false porque no contiene un esquema de URL válido. La versión correcta es https://urlcheck.com. Otro ejemplo es mailto:John.Doe@example.com. Esta es una URL válida, pero si quitas los dos puntos, JavaScript dejará de reconocerla como URL. Un tercer ejemplo es ftp://. No es válida porque no contiene un nombre de host. Si agregas dos puntos (..), será válida porque los puntos se considerarán un nombre de host; de esta manera, ftp://.. se convierte en una URL válida.
Es importante tener en cuenta que existen URL poco convencionales, pero perfectamente válidas. Puede que sorprendan a los desarrolladores que trabajan con ellas, pero son totalmente adecuadas. Por ejemplo, las dos URL siguientes devolverán TRUE:
new URL("youtube://a.b.c.d");
new URL ("a://1.2.3.4@1.2.3.4");
Estos ejemplos nos recuerdan que los desarrolladores deben basarse en los principios de validación de URL, en lugar de enfocarse en las convenciones.
Si quieres asegurarte de que la URL válida use un esquema específico, puedes usar la siguiente función:
Esta función valida la URL y luego comprueba si usa los esquemas HTTP o HTTPS. En este caso, ftp://.. no será válida porque no usa HTTP ni HTTPS, mientras que http://.. seguirá siendo válida. Otras formas de usar la función constructora URL incluyen:
El ejemplo anterior usa el elemento base. Al registrar el valor, obtenemos https://snyk.io/.
Para devolver un objeto URL sin especificar el parámetro base, la sintaxis es:
Para agregar una ruta al host, la estructura es la siguiente:
La URL almacenada en d es https://snyk.io/en-US/docs.
Otra funcionalidad del módulo URL es que implementa la API URL de WHATWG, que cumple con el estándar URL de WHATWG que usan los navegadores:
En el ejemplo anterior, creamos un objeto URL llamado adr. Luego, el código obtuvo el host y la ruta de la URL: snyk.io y /en-US/docs, respectivamente. Por último, podemos comparar la URL con una lista de permitidas o de bloqueadas para asegurarnos de que solo se admitan las URL designadas y no se rechacen por error las URL permitidas.
Cómo validar una URL con regex, aunque no deberías hacerlo
Otra forma de validar una URL es usar una expresión regular (regex), es decir, una cadena que define un patrón de búsqueda. Podemos usar regex para comprobar si la URL es válida.
La sintaxis de JavaScript para validar URL con regex es:
Para probar algunas URL:
La sintaxis de URL definida por regex comprueba si la URL comienza con los esquemas http:// o https://, o con un subdominio, y si contiene un nombre de dominio. La instrucción de la consola devuelve true porque cumple con la sintaxis de URL definida por regex. En cambio, la siguiente instrucción devolverá el valor false porque no comienza con ninguno de los esquemas permitidos ni con un subdominio, y tampoco contiene un nombre de dominio:
La regex anterior es relativamente simple, pero sigue siendo difícil de interpretar. También es un enfoque propenso a errores, porque una regex no puede manejar adecuadamente las reglas para validar una URL. Como máximo, puede coincidir con URL válidas. Además, ejecutar la comprobación de validación puede llevar mucho tiempo cuando una expresión regular incluye una lógica compleja o recibe una cadena de entrada extensa.
Para cumplir con las comprobaciones de validación definidas por regex, el navegador debe retroceder millones de veces a través de la cadena de entrada. Este nivel de retroceso podría provocar un “retroceso catastrófico”, un fenómeno en el que las expresiones regulares complejas pueden congelar el navegador o saturar los procesos del núcleo de la CPU.
Snyk detecta paquetes de código abierto vulnerables
Es probable que los encargados del mantenimiento también cometan errores al validar URL y, cuando eso ocurre, las aplicaciones de Node.js quedan en riesgo. El paquete npm keycloak-connect es un proyecto que supera las 50 000 descargas semanales, pero en marzo de 2023 se reveló que una práctica insegura de validación de URL permitía una vulnerabilidad de redireccionamiento abierto a través de CVE-2023-2237.
Te recomendamos ampliamente analizar tus proyectos gratis con Snyk para encontrar dependencias de código abierto vulnerables y corregirlas.

Las 10 principales vulnerabilidades de JavaScript según Snyk
Esta guía práctica analiza en profundidad las vulnerabilidades críticas y de alta gravedad más frecuentes en código abierto que Snyk detectó al analizar aplicaciones JavaScript en 2022.
Vulnerabilidades reales y soluciones
Node.js es un entorno de ejecución de JavaScript gratuito, de código abierto y multiplataforma que utiliza un administrador de paquetes llamado Node Package Manager (npm).
En 2019 ocurrió un incidente similar, cuando un atacante obtuvo por sí solo acceso no autorizado a datos de Capital One, uno de los bancos más grandes de Estados Unidos. Esa filtración de datos sigue siendo una de las más importantes del siglo. Según The New York Times, el atacante accedió a 100 millones de registros de clientes, 140 000 números de Seguro Social y 80 000 datos bancarios vinculados a clientes de Capital One.
El atacante accedió al servidor de Capital One alojado en Amazon Web Services (AWS). La demora en detectar el ataque indica que el atacante conocía a fondo la infraestructura de AWS y detectó una vulnerabilidad explotable en el firewall de aplicaciones web (WAF) del proveedor de servicios de seguridad administrados (MODSEC). Con este conocimiento, el atacante llevó a cabo el ataque SSRF y realizó nuevas solicitudes HTTP al manipular el servidor web vulnerable, con lo que logró acceder al servicio de metadatos de AWS.
Según los requisitos de la empresa, podemos evitar ataques SSRF si limitamos el sistema a unos pocos protocolos, como HTTP o HTTPS. Para aumentar la seguridad, debemos configurar la aplicación para que no procese el parámetro URL sin supervisión. Normalmente se usan listas de permitidas y de bloqueadas para filtrar y controlar el mecanismo, lo que reduce considerablemente la probabilidad de sufrir un ataque SSRF. Las listas de permitidas permiten que la aplicación use un conjunto predefinido de objetos y servidores. Por su parte, las listas de bloqueadas impiden que la aplicación obtenga nombres de host de uso común.
Uso seguro de JavaScript
Como demuestra la inclusión de SSRF en la nueva OWASP Top 10, la validación de URL se ha vuelto cada vez más importante para la seguridad de las aplicaciones JavaScript. Por suerte, podemos ayudar a mitigar estos ataques validando las URL en el servidor. Además, puede ser muy beneficioso usar la nueva función URL según las prácticas recomendadas para validar y trabajar con URL.
Después de revisar algunos casos de uso de las capacidades de la nueva función URL, aprendimos a validar una URL con regex y vimos por qué este enfoque es engorroso y propenso a errores. Para terminar, analizamos un caso práctico de la vulnerabilidad SSRF en JavaScript.
Los riesgos de seguridad relacionados con las URL tienen menos que ver con su validez y más con los esquemas de URL peligrosos. Por eso, debemos asegurarnos de que la aplicación del lado del servidor realice la validación. Un atacante puede evadir el mecanismo de validación del lado del cliente, así que no conviene depender únicamente de este.
Para obtener más información sobre cómo administrar la seguridad de tus aplicaciones y el producto de Snyk, visita Snyk hoy mismo.
Snyk para la seguridad de JavaScript
Desde la primera línea de código hasta la última dependencia de npm, Snyk protege tus aplicaciones de JavaScript directamente desde tu IDE, CLI y flujos de trabajo de Git.



