Saltar al contenido
← Todos los ejercicios

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) devuelve target cuando es una ruta local de este sitio, y fallback en caso contrario.
  • Un target ausente, 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: true solo 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");
  });
});