Guía de Mejores Prácticas de Seguridad
Una Referencia Detallada de seguridad de aplicaciones: autenticación, autorización, validación de inputs, gestión de secretos y prevención de vulnerabilidades comunes.
Overview
La seguridad no es una feature que agregas después—es un fundamento que construyes en cada capa de tu aplicación. A continuación: las prácticas esenciales para construir software seguro.
When to Apply
- Construyes cualquier aplicación que maneje datos de usuarios
- Procesas pagos o información sensible
- Expones APIs a internet
- Trabajas en industrias reguladas (salud, finanzas, etc.)
Authentication & Authorization
Usa Librerías de Autenticación Probadas
Nunca inventes tu propia autenticación. Usa librerías probadas en batalla:
| Lenguaje | Librería Recomendada |
|---|---|
| Node.js | Passport.js, Auth.js |
| Python | Django Auth, Flask-Login |
| Java | Spring Security, OAuth2 |
| Go | casbin, gorilla/sessions |
Autenticación Multi-Factor (MFA)
Requiere MFA para:
- Cuentas de administrador
- Acceso a producción
- Operaciones financieras
Patrones de Autorización
Control de Acceso Basado en Roles (RBAC)
User -> Role -> Permission -> Resource
Principio del Mínimo Privilegio
Otorga solo los permisos necesarios para cada rol. Audita permisos trimestralmente.
Validación de Inputs
Valida en el Límite
# Python con Pydantic
from pydantic import BaseModel, EmailStr, constr
class CreateUserRequest(BaseModel):
email: EmailStr
password: constr(min_length=12)
role: constr(pattern=r'^(user|admin)$')
Sanitiza Output
- Usa queries parametrizadas (nunca concatenación de strings)
- Escapa HTML antes de renderizar en navegadores
- Codifica JSON de forma segura
Gestión de Secretos
Nunca Hardcodees Secretos
# ❌ Mal
API_KEY = "sk-live-abc123"
# ✅ Bien
API_KEY = os.environ.get("API_KEY")
Usa un Gestor de Secretos
| Herramienta | Caso de uso |
|---|---|
| HashiCorp Vault | Enterprise, políticas complejas |
| AWS Secrets Manager | Aplicaciones nativas de AWS |
| Azure Key Vault | Aplicaciones nativas de Azure |
| Doppler | Multi-cloud, developer-friendly |
| 1Password Secrets | Equipos pequeños, setup simple |
Seguridad de Dependencias
Mantén Dependencias Actualizadas
# Escanear vulnerabilidades
npm audit
pip-audit
snyk test
Archivos de Lock
Siempre commitea archivos de lock (package-lock.json, poetry.lock, Cargo.lock) para asegurar builds reproducibles.
Prevención del OWASP Top 10
| Vulnerabilidad | Prevención |
|---|---|
| Injection | Queries parametrizadas, validación de inputs |
| Broken Access Control | Denegar por defecto, forzar ownership |
| Cryptographic Failures | HTTPS en todas partes, encriptar en reposo |
| Insecure Design | Threat modeling, requerimientos de seguridad |
| Security Misconfiguration | Plataformas mínimas, remover defaults |
| Vulnerable Components | Escaneo de dependencias, auto-updates |
| Auth Failures | MFA, contraseñas fuertes, límites de sesión |
| Software Integrity | Verificar paquetes, commits firmados |
| Logging Failures | Loggear eventos de auth, monitorear anomalías |
| SSRF | Whitelist de URLs, deshabilitar protocolos innecesarios |
Comunicación Segura
HTTPS en Todas Partes
- Redirige HTTP a HTTPS
- Usa headers HSTS
- Mantén certificados TLS actualizados
Seguridad de APIs
- Rate limiting (prevenir fuerza bruta)
- Versionado de APIs (deprecación graceful)
- Firmado de requests (verificar integridad)
Logging & Monitoreo
Qué Loggear
- Intentos de autenticación (éxito y fracaso)
- Fallas de autorización
- Errores de validación de input
- Patrones de tráfico inusuales
Qué NO Loggear
- Contraseñas
- API keys
- Información médica personal
- Números de tarjeta de crédito
Security Checklist
- Autenticación usa MFA donde se requiere
- Autorización verifica ownership del recurso
- Todos los inputs validados y sanitizados
- Secretos almacenados en un gestor de secretos
- Dependencias escaneadas por vulnerabilidades
- HTTPS forzado para todo el tráfico
- Headers de seguridad configurados (CSP, HSTS)
- Rate limiting habilitado en APIs públicas
- Datos sensibles encriptados en reposo
- Eventos de seguridad loggeados y monitoreados
Troubleshooting
- Authentication bypass in tests: ensure test users cannot reach production endpoints.
- False positives in scanning tools: tune rules against the risk profile. Distinguish between reachable vulnerabilities and theoretical issues.
- Secrets appear in logs: Audit log sinks for sensitive patterns.
- CSP breaks legitimate functionality: Iterate on allowed sources based on real violations.
- Incident response stalls: run tabletop exercises.
Temas Avanzados
Escenario: Hardening de API Node.js para Produccion
// 1. Helmet: headers de seguridad HTTP
const helmet = require("helmet");
app.use(helmet());
// X-Content-Type-Options: nosniff
// X-Frame-Options: DENY
// Strict-Transport-Security: max-age=31536000
// Content-Security-Policy: default-src self
// 2. Rate limiting
const rateLimit = require("express-rate-limit");
app.use("/api", rateLimit({
windowMs: 60 * 1000, // 1 minuto
max: 100, // 100 requests por minuto
message: "Demasiadas requests"
}));
// 3. CORS estricto
const cors = require("cors");
app.use(cors({
origin: ["https://app.example.com"],
methods: ["GET", "POST", "PUT", "DELETE"],
allowedHeaders: ["Content-Type", "Authorization"],
credentials: true
}));
// 4. Input validation (Zod)
const { z } = require("zod");
const userSchema = z.object({
email: z.string().email().max(255),
password: z.string().min(12).max(128),
name: z.string().min(1).max(100).regex(/^[a-zA-Z0-9 ]+$/)
});
app.post("/api/users", (req, res) => {
const result = userSchema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({ error: "Invalid input" });
}
// ... procesar
});
// 5. SQL injection prevention (parameterized queries)
app.get("/api/users/:id", async (req, res) => {
// NUNCA: `SELECT * FROM users WHERE id = ${req.params.id}`
// SIEMPRE: queries parametrizadas
const result = await pool.query(
"SELECT id, email, name FROM users WHERE id = $1",
[req.params.id]
);
res.json(result.rows[0]);
});
// 6. JWT seguro
const jwt = require("jsonwebtoken");
const token = jwt.sign(
{ userId: user.id, role: user.role },
process.env.JWT_SECRET,
{ expiresIn: "15m", algorithm: "RS256" }
);
// 7. Audit logging
app.use((req, res, next) => {
const start = Date.now();
res.on("finish", () => {
logger.info({
method: req.method,
path: req.path,
status: res.statusCode,
duration: Date.now() - start,
ip: req.ip,
userId: req.user?.id,
});
});
next();
});
// 8. Dependency scanning en CI
// npm audit --audit-level=high
// npx snyk test
// npx trivy fs .
Que headers de seguridad son obligatorios?
X-Content-Type-Options: nosniff (prevenir MIME sniffing), Strict-Transport-Security: max-age=31536000 (forzar HTTPS), X-Frame-Options: DENY (prevenir clickjacking), Content-Security-Policy: default-src self (prevenir XSS), Referrer-Policy: no-referrer (minimizar info expuesta). Usa helmet() en Express para configurar todos automaticamente.
Puntos Clave
- Aplica guía de mejores prácticas de seguridad cuando necesites una solución práctica para tu caso de uso.
- Monitorea el rendimiento después de implementar; mide latencia, errores y uso de recursos antes y después.
- Revisa la sección de Troubleshooting ante errores comunes; la mayoría tienen causa raíz documentada con solución.
- Mantén dependencias actualizadas y ejecuta tests en CI para prevenir regresiones en producción.
Errores Comunes en Producción
- Tratar la guía como un checklist para completar una vez en lugar de una práctica por evolucionar.
- Adoptar cada recomendación de golpe en lugar de comenzar con un cambio medido.
- Saltar la evaluación de madurez e imponer prácticas avanzadas a un equipo no preparado.
- No actualizar runbooks y expectativas de guardia al introducir nuevas prácticas.
- Ignorar datos reales de incidentes al priorizar qué partes de la guía aplicar primero.
- No asignar un responsable que revise decisiones trimestralmente.
- Copiar ejemplos sin adaptarlos a las herramientas y restricciones reales del equipo.
- Olvidar medir resultados antes de agregar la siguiente mejora.
Preguntas frecuentes
¿Con qué frecuencia debería actualizar dependencias?
Al menos mensualmente. Habilita Dependabot o Renovate para PRs automatizados.
¿Es JWT seguro?
JWT es seguro cuando se implementa correctamente: expiración corta, algoritmos de firma fuertes (RS256/ES256), almacenamiento seguro de secretos, y transmisión solo por HTTPS.
¿Debería encriptar todo en la base de datos?
Encripta campos sensibles (PII, credenciales, tokens). La encriptación en reposo debería estar habilitada a nivel de base de datos.
Recursos Relacionados
Cómo hashear contraseñas (Python, JavaScript, Java)
Aprendé a hashear y verificar contraseñas con bcrypt, Argon2 y PBKDF2. Ejemplos prácticos en Python, JavaScript y Java, más pasos de migración y trade-offs de parámetros.
RecipeAutenticación JWT
Cómo generar, validar y refrescar JSON Web Tokens para autenticación de APIs sin estado.
RecipeValidación de Input
Cómo validar input de usuarios de forma segura usando schemas, type checking y sanitización en Python, JavaScript y Java.
DocPlantilla de Rotación de Secretos
Plantilla para programar y rastrear la rotación de claves API, tokens y certificados.
RecipeGestión de Llaves SSH en Bash
Genera, rota y distribuye llaves SSH con scripts bash.
RecipeValidacion de Datos Basada en Schemas con Zod en TypeScript
Valida y sanitiza datos entrantes usando schemas Zod con inferencia de TypeScript, refinements custom y formateo de errores para validacion robusta de APIs y formularios