Línea Base de Seguridad
Resumen
Una referencia completa vive en references/baseline.md (secciones §0–§18, buscar por ## N.). Este archivo es el procedimiento operativo. Principio central: igualar el rigor al nivel de amenaza, luego probar cada hallazgo con evidencia. Tres leyes: nunca confíes en el cliente, nunca confíes en el código del modelo, nunca confíes en los valores predeterminados.
Elegir el modo
| Solicitud | Modo | Leer en baseline.md |
|---|---|---|
| "Planificar / iniciar un proyecto de forma segura", escribir reglas de agente | Planificar | §0, §2, §3, §16 |
| "Revisar / auditar esta aplicación / repositorio / PR" | Revisión de código | §1.3, §4–§11, §15.2 |
| "Auditar mi servidor / laboratorio doméstico / VPS", "¿está actualizado?" | Auditoría de host | §3.3, §8.3, §12, §13 |
| "Nos piratearon / filtraron una clave" | Incidente | §17, §8.2 |
Una auditoría de host incluye una breve revisión de código de cada aplicación orientada a internet que maneje cuentas o datos personales.
Paso 1 — Clasificar el nivel (siempre primero, indíquelo en el informe)
Decida a partir de hechos observables, no de cómo lo llame el propietario:
| Nivel | Predicado | Aplicar |
|---|---|---|
| T0 Juguete | Sin usuarios reales ni datos Y no accesible desde internet (solo LAN, o detrás de SSO) | §2, §8 |
| T1 Público, sin cuentas | Accesible por internet, sin inicio de sesión, sin almacenar datos personales | T0 + §9, §10 |
| T2 Cuentas / datos de usuario | Cualquier inicio de sesión, cualquier dato personal (nombres, correos electrónicos, listas de invitados), cualquier clave API o token que maneje | Todo |
| T3 Dinero / PII a escala / regulado | Pagos, salud, bóvedas de credenciales, finanzas, datos de >1k personas, contratos con clientes | T2 + revisión externa + §14 |
Un host de laboratorio doméstico se califica según el nivel más alto de cualquier cosa que ejecute. Un agregador de credenciales (gestor de contraseñas, n8n, Home Assistant, Portainer, titular de docker.sock) es T3 por radio de explosión.
Paso 2 — Recopilar evidencia (solo lectura)
Ejecute los scripts empaquetados a través de bash. En un host remoto, transmítalos por SSH: ssh host 'bash -s -- --remote-digests' < scripts/audit-docker-host.sh y ssh host 'bash -s -- <directorio-proyecto>' < scripts/scan-code.sh.
bash scripts/audit-docker-host.sh --remote-digests— Parches del SO, indicador de reinicio, sockets en escucha, cortafuegos, sshd, usuario/privilegio/puertos publicados/docker.sock de cada contenedor, NOMBRES de variables de entorno que parezcan secretos, actualidad de la imagen (UP-TO-DATE / OUTDATED / local-build).bash scripts/scan-code.sh <directorio-proyecto>— grep por posibles secretos, inyección, XSS, asignación masiva, IDs de inquilino proporcionados por el cliente, capturas abiertas, criptografía débil, archivos de bloqueo, riesgos de Dockerfile/compose, inventario de rutas.
Luego, haga lo que los scripts no pueden:
- Inventario de proxy inverso: enumere cada nombre de host público, su destino y si la autenticación está al frente (NPM DB / Caddy / etiquetas de Traefik). Interfaces de administración (lista §3.3) en un nombre de host público sin SSO/lista de acceso = hallazgo.
- Vista externa: desde fuera de la ruta LAN,
curl -sI https://<host>para cabeceras (§10.2), y sondee/.env,/.git/config,/admin,/apisolo con GET. - Traza de autorización para cada aplicación T2+: para cada ruta, nombre la comprobación de autorización y de dónde proviene el ID del principal/inquilino (§4.3). Aplique la pregunta de §1.3.
- Confianza del proxy: si una aplicación lee
X-Forwarded-For, verifique qué salto confía ($proxy_add_x_forwarded_forañade; el primer valor está controlado por el atacante). - Fortaleza de credencial por rol: para cada rol (admin, personal, voluntario, token de API/MCP), encuentre cómo se establece su secreto, incluyendo semilla, rutas heredadas y de migración que omiten la verificación de longitud normal. Verifique la longitud real de los valores de
.envconawk -F= '{print $1, length($2)}', nunca imprimiéndolos. Un secreto débil más un límite de velocidad eludible es un hallazgo, no dos. - Versiones vs. avisos: para cada aplicación orientada a internet, compare la versión en ejecución con el lanzamiento actual y los CVE conocidos. Use búsqueda web para los avisos de seguridad del producto.
Compuerta de host (la lista de verificación §16 es por proyecto; use esta para un host)
- Cada nombre de host público está listado, y cada interfaz de administración (§3.3) tiene SSO, una lista de acceso o VPN al frente, o no es pública
- Hipervisor, Docker, administración de NPM/proxy, administración de bóveda de contraseñas: nunca públicos
- Registro abierto deshabilitado en cada aplicación auto-alojada que no lo necesite (Vaultwarden, Open WebUI, Gitea, Immich, …)
- Puertos accesibles desde WAN = solo 80/443 (+ VPN). Los puertos publicados por Docker evitan ufw: verifique los reenvíos del router y
DOCKER-USER - El proxy pasa una IP de cliente que las aplicaciones no pueden engañar (§4.5, X-Forwarded-For)
- Miembros del grupo docker listados; cada uno es equivalente a root
- Archivos de secretos en modo 600; sin
.env/claves legibles por el mundo - SO parcheado, sin reinicio pendiente mayor de 7 días; imágenes actualizadas (tabla de actualidad)
- Las copias de seguridad se ejecutaron recientemente y se probó una restauración (§13.4)
Reglas de enfrentamiento
- Solo lectura por defecto. Sin escrituras, reinicios, actualizaciones, POST que cambien datos, fuerza bruta o escaneo de hosts que el propietario no posea.
- Nunca imprima valores secretos. Informe solo el nombre de la variable y archivo:línea.
- Inspeccione los almacenes de configuración (tablas de configuración de BD, ajustes JSON, env de
docker inspect) por claves y longitudes solamente:jq 'paths',SELECT key FROM …,awk -F= '{print $1, length($2)}'. Nunca vuelque una fila o archivo de configuración completo para mirarlo: contendrá claves API. - Los cambios (actualizaciones, chmod, correcciones de configuración) ocurren solo después del informe, y solo cuando el solicitante lo pidió. Para actualizaciones, siga "Actualizar de forma segura" a continuación.
Paso 3 — Informe (con esta forma exacta)
- Alcance y nivel: qué se examinó, el nivel y la razón en una línea.
- Veredicto: una oración — desplegar / arreglar-primero / parar.
- Hallazgos, clasificados Crítico → Bajo. Cada hallazgo tiene: título,
CONFIRMADO(lo reprodujo o leyó la ruta exacta de código/configuración) oPISTA(plausible, no probado), evidencia (archivo:línea, comando + extracto de salida), impacto en una oración, arreglo. - Tabla de actualidad (auditoría de host): componente, versión en ejecución, última, riesgo de actualizar.
- Cobertura: las secciones de compuerta §16 que verificó, y las que no verificó y por qué. El silencio no es una aprobación.
- Próximas acciones, numeradas, primero el de menor esfuerzo y mayor riesgo.
Actualizar de forma segura ("asegúrese de que todo esté actualizado")
- Confirme que existe una copia de seguridad y es reciente (§13.4). Registre el ID de imagen actual de cada contenedor para que la reversión sea
image: <repositorio>@<digesto anterior>. - Sin estado = sin volumen nombrado ni montaje bind que la aplicación escriba, y sin base de datos. Los sitios nginx estáticos, gotenberg, flaresolverr no tienen estado. Si no está seguro, trátelo como portador de datos.
- Clasifique: portador de datos o migración de esquema (bases de datos, Immich, Paperless, Vaultwarden, Firefly, n8n, Home Assistant) → uno a la vez, lea las notas de lanzamiento para cambios importantes primero. Sin estado (sitios nginx estáticos, herramientas) → en lote.
- Nunca salte una versión mayor de base de datos (postgres 15→17) a través de
docker pull. Eso necesita un dump/restore. docker compose pull && docker compose up -dpor proyecto, luego verifique el estado: estado del contenedor, registros de errores y una comprobación HTTP de la URL pública.- Las compilaciones locales (
local-build) se actualizan reconstruyendo con--pull. Los paquetes del SO necesitan sudo; si no tiene ninguno, informe la lista y el indicador de reinicio. - Si las descargas fallan con
429 toomanyrequests, deténgase. Solicitedocker loginen el host, o reintente después de 6 h. No haga bucles.
Errores comunes
| Error | Correcto |
|---|---|
| Informar todo como "Alto" | Gravedad = explotabilidad × nivel × radio de explosión |
| Tratar un acierto de script como un hallazgo | La salida del script es una PISTA hasta que lea el código |
| "El contenedor se ejecuta como root" sin verificar | Muchas imágenes reducen privilegios en el entrypoint; verifique ps dentro |
| "El puerto 9000 está abierto" en un host LAN | Diga quién puede alcanzarlo: solo LAN, WAN a través de reenvío de router, o a través de proxy |
| Saltarse el nivel y auditar un sitio estático como un banco | Primero el nivel; T1 necesita cabeceras y dependencias, no RLS |
Actualizar todo con :latest de una sola vez | Un servicio portador de datos a la vez, con un digesto de reversión |
Arreglar deshabilitando el control (RLS apagado, CORS *) | Arregle la política, nunca la elimine (§7.2) |