Falsos positivos de viaje imposible: VPN, tiempos y datos de ubicación
El viaje imposible compara la ubicación derivada de la IP de un inicio de sesión con el punto anterior almacenado para ese usuario y marca una velocidad implícita que sería físicamente imposible de recorrer en el tiempo transcurrido. Un resultado high significa que el cálculo bruto de distancia entre tiempo superó un umbral; por sí solo no es prueba de que la cuenta haya sido comprometida, y varias situaciones ordinarias pueden desencadenarlo.
El cálculo detrás de la puntuación
POST /v1/risk/check calcula la distancia ortodrómica entre la ubicación anterior almacenada de un usuario y la actual, la divide entre el tiempo transcurrido desde esa observación anterior y clasifica la velocidad implícita: por debajo de 500 km/h es low, entre 500 y 900 km/h es medium, y por encima de 900 km/h es high (impossibleTravel: true). Un vuelo de larga distancia real puede acercarse al límite entre medium y high, motivo por el cual los umbrales existen como rangos y no como un único corte; pero el propio cálculo no tiene ningún concepto de «vuelo», «VPN» o «red compartida»: solo ve dos puntos y una duración.
La primera observación nunca se marca
La primera comprobación de un usuario no tiene nada con qué compararse: siempre devuelve risk: "low" con un previousLocation nulo y valores nulos de distancia, velocidad y tiempo transcurrido, y (salvo que commit: false) se convierte en la nueva referencia almacenada. Esto significa que el primerísimo inicio de sesión desde un dispositivo o red nuevos genera confianza por defecto; conviene saberlo, porque la primera acción de un atacante tampoco se marca, por exactamente el mismo motivo estructural.
Situaciones que suelen desencadenar un falso positivo
Cambiar de nodo de salida de VPN o de puerta de enlace de red móvil entre inicios de sesión puede desplazar la ubicación resuelta una distancia larga sin que haya habido ningún desplazamiento real: la v1 no tiene ninguna supresión consciente de VPN o centros de datos, así que esto se lee de forma idéntica a un viaje imposible genuino. La rotación habitual de IP de los operadores móviles (la misma ubicación física resolviéndose hacia una ciudad de puerta de enlace distinta en solicitudes diferentes) y los rangos de IP compartidos o anycast pueden producir el mismo efecto. Ninguno de estos casos implica un atacante; son artefactos de cómo funciona la ubicación derivada de IP, tratados con más profundidad en el artículo sobre precisión.
Lo que una puntuación alta no demuestra
risk: "high" es una señal en bruto de un cálculo de distancia entre tiempo, no un evento de toma de cuenta verificado, ni evidencia sobre quién inició el inicio de sesión, ni información sobre si las credenciales del usuario se vieron realmente comprometidas. Trátalo como una señal más para tu propia decisión de revisión o de autenticación reforzada, combinada con la evidencia de autenticación que ya tengas, no como un veredicto independiente sobre el que actuar por sí solo.
Un ejemplo con dos observaciones
La referencia almacenada de un usuario es Toronto, observada a las 09:00 UTC. Un inicio de sesión llega desde una IP que resuelve a Fráncfort a las 09:45 UTC, unos 6400 km en 45 minutos, una velocidad implícita muy por encima de 900 km/h, por lo que se devuelve risk: "high" e impossibleTravel: true. Ese resultado es compatible tanto con una cuenta comprometida usada desde otro continente como con que el tráfico del mismo usuario legítimo empiece a enrutarse de repente por un nodo de salida de VPN en Fráncfort por un motivo no relacionado; la API devuelve la misma clasificación en cualquiera de los dos casos, que es exactamente por lo que está diseñada como una señal más para revisión, no como un bloqueo automático.
Lo que este artículo no afirma
Esto describe la implementación propia de Watch-IP en su versión v1. No afirma una detección integral de toma de cuentas, análisis de comportamiento ni huella digital de dispositivos; son técnicas distintas que este endpoint no intenta abordar. La disponibilidad y la aplicación independiente por familia de planes de este endpoint no están confirmadas; contáctanos antes de depender de él en producción.
Fuentes
Escrito por el equipo editorial de Watch-IP, 6 de septiembre de 2026. Revisado frente a apps/api/src/lib/risk.ts y apps/api/src/durable-objects/session-risk.ts.