La redirección que se fía de una barra inicial
TypeScript · La redirección después del login en una API Express · Seguridad · dificultad 1/3 · ~5 min
Después de un login correcto, la API redirige al usuario a la página que había pedido originalmente. El destino viene de un parámetro de query ?next=, así que lo controla el usuario. Un compañero de equipo le pidió al asistente de IA: "Escribe resolveRedirect(target, fallback) para nuestro endpoint de login. Permite solo redirecciones a páginas de nuestro propio sitio; cualquier otra cosa debe ir al fallback."
El código llegó con tests que pasan. El contrato que promete el docstring:
resolveRedirect(target, fallback)devuelvetargetcuando es una ruta local de este sitio, yfallbacken caso contrario.- Un
targetausente, vacío o formado solo por espacios en blanco usa el fallback. - Las URL absolutas hacia otros hosts (
https://evil.example) nunca deben devolverse. isLocalPath(url)es el predicado que hay detrás:truesolo para rutas que el navegador resolverá en el origen actual.
Ten en cuenta cómo interpreta un navegador una cabecera Location: no solo busca http://. Revisa el código antes de que salga a producción.
Repara el código hasta que pasen las pruebas ocultas.
code.ts
Pruebas visibles (pasan con el código tal como está)
import { describe, it, expect } from "@debunk/harness";
import { resolveRedirect, isLocalPath } from "./code";
describe("resolveRedirect", () => {
it("keeps a local path", () => {
expect(resolveRedirect("/settings/profile?tab=security")).toBe("/settings/profile?tab=security");
});
it("falls back for an absolute URL to another host", () => {
expect(resolveRedirect("https://evil.example/login")).toBe("/dashboard");
expect(isLocalPath("http://evil.example")).toBe(false);
});
it("falls back when the target is missing", () => {
expect(resolveRedirect(null)).toBe("/dashboard");
expect(resolveRedirect(" ", "/home")).toBe("/home");
});
});