Playbooks

Security

Salir

Auth & Secrets

La seguridad empieza con saber quién está del otro lado. Una mala autenticación hace irrelevante todo lo demás.

JWT (JSON Web Token)
Stateless. El token contiene claims. Ideal para APIs. Peligroso si no rotás secrets o no ponés expiración corta.
✅ Access token: 15 min. Refresh token: 7 días. Rotá el secret de refresh al detectar uso malicioso.
❌ Nunca guardes información sensible en el payload (no está encriptado, solo encodeado).
OAuth 2.0 / OIDC
Para third-party login (Google, GitHub) o service-to-service. Delegás la autenticación a un provider.
✅ Usá un provider consolidado (Auth0, Clerk, Firebase Auth). No implementes OAuth desde cero.
❌ No aceptes tokens de providers que no estén en tu allowlist. Validá el issuer y audience siempre.
API Keys
Identifican a un cliente, no a un usuario. Útiles para webhooks, integraciones B2B, y acceso de servicios.
✅ Generá keys con prefijo (sk_live_xxx). Guardá solo el hash en DB. Mostrá la key una sola vez al crearla.
❌ No uses API keys para autenticar usuarios. No las pongas en URLs (quedan en logs).

Secrets — las 5 reglas de oro

1. Nunca hardcodees secrets en el código. git revert no borra el historial. Si commiteaste un secret, rotalo inmediatamente.
2. Usá variables de entorno para desarrollo local (.env en .gitignore). En producción, usá un vault (1Password Secrets, HashiCorp Vault, AWS Secrets Manager).
3. Cada entorno tiene sus propios secrets. El secret de staging no puede ser el mismo que producción.
4. Rotá secrets periódicamente. Un secret de 6 meses es una bomba de tiempo.
5. Si un secret se filtró, asumí que está comprometido. Rotalo y auditá quién tuvo acceso.

OWASP Top 7

No necesitás saber las 100 vulnerabilidades de OWASP. Estas 7 cubren el 95% de los incidentes de seguridad en aplicaciones web.

#1 Broken Access Control
Un usuario ve o modifica datos de otro porque no validaste permisos en el backend.
🔧 Validá permisos en cada endpoint, no solo en el frontend. Usá middleware de autorización por rol. Testeá con usuarios de distintos roles.
#2 Cryptographic Failures
Datos sensibles viajan en texto plano. HTTPS mal configurado. Hashing débil (MD5, SHA1).
🔧 HTTPS en todos lados. HSTS header. Passwords con bcrypt/argon2. Datos sensibles en reposo encriptados con AES-256.
#3 Injection
SQL injection, command injection, LDAP injection. Input del usuario ejecutado como código.
🔧 Nunca concatenes strings para queries SQL. Usá ORMs o prepared statements. Validá y sanitizá todo input del usuario.
#4 Insecure Design
Falta de threat modeling. No pensaste en seguridad durante el diseño, solo al final.
🔧 Threat modeling en features nuevas. Preguntate: ¿qué pasa si un usuario malicioso usa esto? Documentá los riesgos aceptados.
#5 Security Misconfiguration
Defaults inseguros. Debug mode en producción. Headers de seguridad ausentes.
🔧 Desactivá debug en producción. Configurá CSP, X-Frame-Options, X-Content-Type-Options. Usá librerías de seguridad estándar (Helmet).
#6 Vulnerable Components
Dependencias con CVEs conocidos. No actualizás hace meses.
🔧 Dependabot o Renovate con auto-merge para parches. Auditá dependencias semanalmente. Si una dep no tiene mantenimiento activo, reemplazala.
#7 Auth Failures
Contraseñas débiles. Sin rate limiting en login. Sin MFA para cuentas críticas.
🔧 Rate limiting en /login. MFA obligatorio para admins. Password policy: mínimo 12 chars, sin restricciones absurdas que bajen entropía.

Dependencias

Tu código es tan seguro como tu dependencia más vulnerable. Un paquete sin mantenimiento es una puerta abierta.

1. Bloqueá el pipeline si hay vulnerabilidades critical o high. Medium pueden ser warning.
2. Dependabot/Renovate con auto-merge para parches (semver patch). Minor y major requieren review humano.
3. Auditá la salud del paquete antes de instalarlo: ¿tiene mantenimiento activo? ¿cuántos contributors? ¿pasa tests?
4. Lockfile (pnpm-lock.yaml) commiteado siempre. CI usa --frozen-lockfile. Instalación reproducible = seguridad.
5. SBOM (Software Bill of Materials): sabé exactamente qué dependencias tenés. Útil para auditorías y respuesta a incidentes.

Código seguro

La seguridad no es una feature — es una propiedad emergente de cada línea de código que escribís.

Input validation

Nunca confíes en el input del usuario
Validá en el backend aunque ya hayas validado en el frontend. El frontend es sugar para el usuario, no seguridad.
Whitelist, no blacklist
Definí qué caracteres/formato es válido. Es más fácil enumerar lo permitido que lo prohibido.
Escapá output según contexto
HTML entities para HTML. Parameterized queries para SQL. encodeURIComponent para URLs. Cada contexto tiene su propio mecanismo de escape.
Usá librerías de validación
Zod, Joi, Yup. No escribas regex de validación a mano — son propensas a errores y difíciles de mantener.
Limitá tamaño de input
Body parser con límite (ej: 1MB para JSON). Prevenís DoS por payload gigante.

Prácticas de código seguro

Prepared statements para SQL
Nunca concatenes strings para queries. Usá el ORM correctamente — la mayoría soporta parámetros bindeados. Si hacés raw SQL, usá $1, $2, etc.
CORS restrictivo
Allow origin específico, no *. Allow methods solo los que usás (GET, POST, PUT). Allow credentials solo si es necesario.
Rate limiting en endpoints sensibles
/login, /register, /reset-password, /verify-email. Bloqueo progresivo: 5 intentos → 1 min, 10 → 15 min, 20 → 1 hora.
Logs sin datos sensibles
Nunca loguees passwords, tokens, o datos de tarjeta. Usá redacción en logs. Si necesitás debuggear, hacelo en desarrollo con datos sintéticos.
Headers de seguridad
Content-Security-Policy, Strict-Transport-Security, X-Content-Type-Options, X-Frame-Options, Referrer-Policy. Helmet.js los configura todos en una línea.
CSRF protection
Tokens CSRF en formularios. SameSite=Strict o Lax en cookies. APIs que usan Authorization header (Bearer token) son inmunes a CSRF clásico.