7 capas de seguridad que todo dev debería implementar
Row Level Security, JWT, CORS, variables de entorno, rate limiting, sanitización y encriptación. Las 7 capas de seguridad que implemento en cada sistema que construyo.
Ignacio Rimini · Fundador de Quantex Agency
Publicado el · 4 min de lectura · Ingeniería
Seguridad no es una feature que agregás al final, es una serie de decisiones que tomás a lo largo del desarrollo. Estas son las 7 capas que implemento en cada sistema que construyo, desde el primero hasta el último commit.
01 · Row Level Security: cada usuario ve solo sus datos
Row Level Security (RLS) es una política en la base de datos que garantiza que un usuario no pueda acceder a registros de otro, incluso si tiene el link directo o manipula el request.
En Supabase, se activa con:
ALTER TABLE orders ENABLE ROW LEVEL SECURITY; CREATE POLICY usuarios_ven_sus_ordenes ON orders FOR SELECT USING (auth.uid() = user_id);
Sin RLS, si alguien cambia el ID en la URL o en el body del request, puede acceder a datos de otro usuario. Con RLS, la restricción vive en la DB, ningún bug en el backend puede bypasearla.
02 · JWT: el sistema sabe quién sos
JSON Web Tokens verifican la identidad del usuario en cada request. El token tiene tres partes: header (algoritmo), payload (datos del usuario como user_id y rol) y firma criptográfica.
El backend verifica la firma antes de procesar cualquier request. Sin un token válido, la respuesta es 401 Unauthorized.
Lo que no hay que hacer:
- Guardar información sensible en el payload (es base64, no está encriptado)
- Usar tokens sin expiración (si lo roban, es permanente)
- Ignorar la verificación de la firma
Expiración recomendada: 15 minutos para access tokens, 7 días para refresh tokens con rotación automática.
03 · CORS: tu backend no habla con cualquiera
CORS (Cross-Origin Resource Sharing) define qué dominios pueden hacer requests a tu API. Sin configuración restrictiva, cualquier sitio externo puede intentar consumirla desde el browser de tus usuarios.
Configuración segura en Express:
app.use(cors({ origin: ['https://tuapp.com'], credentials: true }));
Importante: CORS es una medida del browser, no del servidor. No protege contra requests directos con curl o Postman, para eso están la autenticación y el rate limiting. CORS protege contra ataques CSRF desde otros sitios web.
04 · Variables de entorno: las claves no van en el código
API keys, passwords de DB, tokens de servicios externos, todo eso va en variables de entorno, nunca hardcodeado en el código fuente.
Si subís una API key a GitHub, aunque la borrés después, queda en el historial de commits. Los bots de scanning encuentran estas keys en minutos y las usan antes de que puedas revocarlas.
Reglas básicas:
- Archivo .env local con todos los secrets
- .env en el .gitignore desde el commit inicial
- Variables de entorno en el panel del proveedor de hosting (Vercel, Railway, AWS)
- Nunca console.log() de variables de entorno en producción
05 · Rate Limiting: un usuario no puede spamear tu API
Rate limiting limita cuántas requests puede hacer un usuario o IP por unidad de tiempo. Es la primera línea de defensa contra fuerza bruta en login, spam en formularios de contacto y ataques de enumeración.
Por endpoint según el riesgo:
- Endpoints públicos: 200 req/min por IP
- Login y registro: 10 req/min por IP (fuerza bruta)
- Envío de emails/SMS: 5 req/min por usuario
- Webhooks entrantes: validar firma en lugar de rate limit
express-rate-limit en Node, slowapi en Python FastAPI, o Cloudflare Rules a nivel infraestructura son implementaciones comunes.
06 · Sanitización: lo que el usuario escribe no se ejecuta
Inyección SQL, XSS (Cross-Site Scripting) y template injection son ataques donde el usuario escribe código malicioso en un campo y el sistema lo ejecuta.
SQL Injection: nunca concatenes input del usuario en una query. Usá prepared statements:
Vulnerable: SELECT * FROM users WHERE email = '" + email + "' Seguro: db.query('SELECT * FROM users WHERE email = $1', [email])
XSS: sanitizá el HTML antes de renderizarlo. En React, JSX ya escapa el contenido por defecto, el peligro es dangerouslySetInnerHTML sin sanitización.
Validación de tipos: usá Zod o Joi para validar el schema del body antes de procesarlo.
07 · Encriptación: los datos sensibles viven cifrados
Contraseñas, documentos personales y datos sensibles deben estar encriptados en la base de datos. Si alguien hace un dump de la DB, no obtiene datos usables.
Contraseñas: nunca en texto plano. Se hashean con bcrypt, Argon2 o scrypt con un salt único por usuario. bcrypt con cost factor 12 es el estándar mínimo actual.
Datos sensibles (DNI, tarjetas, documentos): encriptación simétrica con AES-256. La clave de encriptación vive en un Key Management Service (AWS KMS, HashiCorp Vault), no en la DB.
En tránsito: HTTPS para todo. TLS 1.2 mínimo, 1.3 recomendado.
Ninguna de estas capas es compleja de implementar desde el principio. El problema es agregarlas sobre un sistema ya construido: RLS requiere revisar cada query, la encriptación requiere migrar datos, las variables de entorno requieren auditar todo el código.
En Quantex esto va por defecto en cada sistema que construimos. No es un extra, es el estándar mínimo.


