Introducción: por qué la seguridad de las aplicaciones TypeScript es crítica
TypeScript es una extensión de JavaScript que añade tipado estático y capacidades modernas. Sin embargo, el tipado no garantiza la seguridad. Errores de validación, manejo incorrecto de la entrada del usuario y vulnerabilidades en dependencias pueden provocar ataques graves. En este artículo analizaremos las 10 vulnerabilidades más comunes en aplicaciones TypeScript, proporcionaremos ejemplos de código y mostraremos cómo evitarlas.
1. Cross-Site Scripting (XSS)
Los ataques XSS ocurren cuando un atacante inyecta un script malicioso en una página web. TypeScript no protege automáticamente contra esto.
Ejemplo de código vulnerable
function renderUserInput(input: string): string { return `<div>${input}</div>`;}
// El atacante envía: <script>alert('XSS')</script>Solución
Utilice escape de caracteres HTML o bibliotecas como DOMPurify:
import DOMPurify from 'dompurify';
function renderUserInputSafe(input: string): string { const sanitized = DOMPurify.sanitize(input); return `<div>${sanitized}</div>`;}2. Inyección SQL
Si utiliza TypeScript con bases de datos, la concatenación no controlada de cadenas en consultas SQL puede provocar fugas de datos.
Ejemplo de código vulnerable
async function getUser(id: string): Promise<User | null> { const query = `SELECT * FROM users WHERE id = '${id}'`; return await db.query(query);}Solución
Utilice consultas parametrizadas (prepared statements):
async function getUserSafe(id: string): Promise<User | null> { const query = 'SELECT * FROM users WHERE id = $1'; return await db.query(query, [id]);}3. Contaminación de prototipos (Prototype Pollution)
Esta vulnerabilidad es característica de JavaScript/TypeScript. Un atacante puede modificar el prototipo de un objeto, afectando a todos los objetos en tiempo de ejecución.
Ejemplo de código vulnerable
function merge(target: any, source: any) { for (const key in source) { if (source.hasOwnProperty(key)) { target[key] = source[key]; } }}
const user = { name: 'Alice' };merge(user, JSON.parse('{"__proto__": {"isAdmin": true}}'));// Ahora todos los objetos tienen isAdmin: trueSolución
Verifique las claves para propiedades peligrosas y utilice utilidades seguras:
function safeMerge(target: Record<string, any>, source: Record<string, any>) { for (const key in source) { if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue; target[key] = source[key]; }}4. Cross-Site Request Forgery (CSRF)
Los ataques CSRF obligan al usuario a realizar acciones no deseadas en un sitio donde está autenticado.
Solución en TypeScript
// Generación de token CSRFimport crypto from 'crypto';
function generateCsrfToken(): string { return crypto.randomBytes(32).toString('hex');}
// Verificación en middlewarefunction csrfMiddleware(req: Request, res: Response, next: NextFunction) { const token = req.headers['x-csrf-token']; if (token !== req.session.csrfToken) { return res.status(403).json({ error: 'CSRF validation failed' }); } next();}5. Deserialización insegura
El uso de JSON.parse() o eval() en datos no verificados puede provocar la ejecución de código arbitrario.
Ejemplo vulnerable
function processData(data: string) { const obj = eval('(' + data + ')'); // ...}Enfoque seguro
function processDataSafe(data: string) { try { const obj = JSON.parse(data); // Validación adicional de tipo if (typeof obj !== 'object' || obj === null)