# Regla: Seguridad

Esta regla es OBLIGATORIA. Aplica a todo código de producción sin excepción.
Ninguna feature se considera completa si viola cualquiera de los puntos aquí listados.

---

## OWASP Top 10 — Mitigaciones obligatorias

Antes de cerrar cualquier ticket, verificar que el código no introduce ninguna
vulnerabilidad del OWASP Top 10. Las más frecuentes en este stack:

- **Inyección (A03)**: Toda interacción con BD usa parameterized queries o el ORM.
  NUNCA concatenar strings para construir SQL. NUNCA usar `format()` o f-strings
  en queries de BD.
- **Autenticación rota (A07)**: Tokens con expiración corta. Refresh tokens en
  httpOnly cookies. Invalidar sesiones al cambiar contraseña.
- **Exposición de datos sensibles (A02)**: Cifrar PII en reposo. TLS obligatorio
  en tránsito. Logs sin datos personales ni tokens.
- **Control de acceso roto (A01)**: Verificar permisos server-side en CADA endpoint.
  No confiar en validaciones de frontend para autorización.
- **Componentes vulnerables (A06)**: Actualizar dependencias con CVEs conocidos
  dentro de 72 horas de notificación.

---

## Gestión de secretos

- NUNCA hardcodear credenciales, API keys, tokens, passwords o connection strings
  en el código fuente.
- NUNCA hardcodear secretos en archivos de configuración que se versionen en git
  (.env, config.yaml, settings.py, etc.).
- Usar variables de entorno inyectadas por el sistema de deployment (Vault, AWS
  Secrets Manager, Azure Key Vault, Kubernetes Secrets, etc.).
- Archivo `.env` solo para desarrollo local — SIEMPRE en `.gitignore`.
- Si un secreto se filtra accidentalmente en git: rotarlo inmediatamente y
  limpiar el historial. No es suficiente con un commit que lo borre.
- Auditar `.env.example` periódicamente — solo debe contener nombres de variables,
  NUNCA valores reales.

---

## Validación y sanitización de inputs

- Validar TODA entrada del usuario en el servidor, sin excepción.
  La validación en frontend es UX, no seguridad.
- Usar esquemas Pydantic (Python) o Zod/class-validator (TS) para inputs de API.
- Definir tipos estrictos: longitud máxima, formato, dominio de valores permitidos.
- Rechazar inputs malformados con 400 Bad Request, con mensaje de error genérico
  (no exponer detalles internos de validación al cliente externo).
- Sanitizar HTML antes de renderizar en el frontend si el contenido viene de usuarios.
  Usar DOMPurify o equivalente — NUNCA confiar en strings crudos.
- Normalizar paths antes de operar sobre el filesystem (ver path traversal).

---

## Parameterized queries

- ORM o prepared statements SIEMPRE para consultas a la BD.
- Si se requiere SQL crudo por performance, usar `text()` de SQLAlchemy con
  parámetros nombrados — NUNCA interpolación de strings.
- Revisión obligatoria en code review: buscar `f"SELECT` o `"SELECT" +` como
  señales de alerta inmediata.

---

## HTTPS y seguridad de transporte

- HTTPS obligatorio en todos los ambientes excepto localhost.
- HSTS habilitado con `max-age` mínimo de 1 año.
- Certificados renovados automáticamente (Let's Encrypt / cert-manager).
- Redirigir HTTP → HTTPS en el nivel del balanceador/proxy, no en la app.
- No usar TLS < 1.2. Preferir TLS 1.3.

---

## CORS

- Whitelist explícita de orígenes permitidos — NUNCA `*` en producción.
- Orígenes definidos como variables de entorno, no hardcodeados en el código.
- `credentials: true` solo cuando sea estrictamente necesario.
- Revisar que los métodos y headers permitidos son los mínimos necesarios.

---

## CSRF

- CSRF tokens obligatorios en toda operación de mutación (POST, PUT, PATCH, DELETE)
  para sesiones basadas en cookies.
- APIs stateless con JWT en Authorization header son inmunes a CSRF por diseño,
  pero documentar explícitamente por qué no se necesita el token.
- Verificar el header `Origin` o `Referer` como defensa adicional.
- SameSite=Strict o SameSite=Lax en cookies de sesión.

---

## Sanitización de output

- Escapar HTML en templates server-side (Jinja2 lo hace por defecto — no desactivar).
- En Angular, usar interpolación `{{ }}` en lugar de `[innerHTML]`.
  Si `[innerHTML]` es necesario, sanitizar con `DomSanitizer.sanitize()`.
- No confiar en que el frontend sanitiza — validar también server-side.
- Cabeceras de seguridad obligatorias en respuestas HTTP:
  `Content-Security-Policy`, `X-Frame-Options: DENY`, `X-Content-Type-Options: nosniff`.

---

## Funciones peligrosas prohibidas

- `eval()` — prohibido en JavaScript y Python sin excepción.
- `exec()` — prohibido en Python sin revisión de seguridad explícita documentada.
- `subprocess` con `shell=True` — prohibido. Usar lista de argumentos.
- `pickle.loads()` con datos externos — prohibido (deserialización insegura).
- `yaml.load()` sin `Loader=yaml.SafeLoader` — prohibido.
- `__import__()` con strings dinámicos — prohibido.

---

## Path traversal prevention

- Normalizar y validar paths antes de operaciones de filesystem:
  ```python
  from pathlib import Path
  base = Path("/uploads").resolve()
  target = (base / user_input).resolve()
  assert str(target).startswith(str(base)), "Path traversal detectado"
  ```
- NUNCA usar input del usuario directamente en `open()`, `os.path.join()` o
  equivalentes sin normalización previa.
- Directorios de uploads aislados del código fuente de la aplicación.

---

## Actualización de dependencias

- Ejecutar `pip-audit` / `npm audit` en CI. Fallo en vulnerabilidades HIGH o CRITICAL.
- Dependabot o Renovate configurado en el repositorio.
- Dependencias con CVE crítico: actualizar en máximo 72 horas.
- Dependencias con CVE medio: actualizar en máximo 2 semanas.
- Pin versions en producción — no usar rangos abiertos (`>=`, `*`, `^` en prod).

---

## Checklist antes de merge a main

- [ ] No hay secrets hardcodeados (revisar con `git grep -i "password\|secret\|token\|key"`)
- [ ] Inputs validados con esquemas estrictos
- [ ] RBAC verificado en todos los endpoints nuevos
- [ ] Sin uso de `eval`, `exec`, `shell=True`
- [ ] Logs sin datos sensibles
- [ ] Dependencias nuevas auditadas
