feat: auditoría de seguridad en APIs, deuda Next 16 y pnpm como gestor
Cierra autenticación en /api/deployer, POST /api/modules, /api/stats y /verify (assertIT + validación de slugs/nombres). GET /api/modules público sanitizado (solo visibles, sin repoUrl ni logs). Corrige estado unhealthy, XSS en plantillas, open redirect en login. Sesión HMAC en tiempo constante, secret obligatorio, 503 si el backend cae, cookie secure solo en prod. Migra middleware a proxy, rate-limit en login, vitest + typecheck, Tailwind/CDN fuera, Boxicons local, polling pausado y código muerto eliminado. Estandariza pnpm (lock, Dockerfile, packageManager).
This commit is contained in:
1 parent
ba71c4daa6
commit
8f30b1c1ec
27 files changed
+5708
-7328
No files matched your search
@@ -4,9 +4,16 @@ import { useState, Suspense } from "react";
|
||||
import Image from "next/image";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
|
||||
function safeNext(v: string | null): string {
|
||||
if (!v || !v.startsWith("/") || v.startsWith("//") || v.startsWith("/\\")) {
|
||||
return "/tablero";
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
function LoginForm() {
|
||||
const router = useRouter();
|
||||
const next = useSearchParams().get("next") || "/tablero";
|
||||
const next = safeNext(useSearchParams().get("next"));
|
||||
const [rut, setRut] = useState("");
|
||||
const [clave, setClave] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
@@ -24,7 +31,7 @@ function LoginForm() {
|
||||
});
|
||||
const j = await res.json();
|
||||
if (!res.ok) throw new Error(j.error || `HTTP ${res.status}`);
|
||||
router.push(next.startsWith("/") ? next : "/tablero");
|
||||
router.push(safeNext(next));
|
||||
router.refresh();
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : "Error al ingresar");
|
||||
|
||||
Reference in new issue
Block a user