Seguridad de aplicaciones TypeScript: top 10 vulnerabilidades

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Seguridad de aplicaciones TypeScript: top 10 vulnerabilidades



TypeScript, como superconjunto de JavaScript, hereda muchas de sus vulnerabilidades, añadiendo al mismo tiempo riesgos específicos relacionados con el sistema de tipos y la compilación. Incluso la tipificación estricta no garantiza la seguridad: errores en la lógica y prácticas inseguras pueden tener consecuencias graves. En este artículo analizaremos las 10 principales vulnerabilidades de las aplicaciones TypeScript, proporcionaremos ejemplos de código y daremos recomendaciones para la protección.



1. Cross-Site Scripting (XSS) a través de dangerouslySetInnerHTML

Una de las vulnerabilidades más comunes en aplicaciones React/TypeScript es la inserción de HTML sin escapar mediante dangerouslySetInnerHTML.



// ❌ Código vulnerablefunction UserComment({ comment }: { comment: string }) {  return <div dangerouslySetInnerHTML={{ __html: comment }} />;}

// ✅ Variante seguraimport DOMPurify from 'dompurify';

function SafeComment({ comment }: { comment: string }) { const sanitized = DOMPurify.sanitize(comment); return <div dangerouslySetInnerHTML={{ __html: sanitized }} />;}


2. Inyección SQL a través de consultas sin escapar

El uso de plantillas de cadenas en consultas SQL con entrada de usuario es un camino directo a la inyección.



// ❌ Código vulnerableasync function getUser(id: string) {  const query = `SELECT * FROM users WHERE id = '${id}'`;  return db.execute(query);}

// ✅ Variante segura (uso de consultas parametrizadas)async function safeGetUser(id: string) { const query = 'SELECT * FROM users WHERE id = $1'; return db.execute(query, [id]);}


3. Prototype Pollution a través de fusión profunda de objetos

TypeScript permite copiar objetos fácilmente, pero no verifica la cadena de prototipos.



// ❌ Código vulnerablefunction merge(target: any, source: any) {  for (const key in source) {    if (typeof source[key] === 'object') {      target[key] = merge(target[key] || {}, source[key]);    } else {      target[key] = source[key];    }  }  return target;}

// ✅ Variante segurafunction safeMerge(target: Record<string, any>, source: Record<string, any>) { const result = { ...target }; for (const key of Object.keys(source)) { if (key === '__proto__' || key === 'constructor') continue; if (typeof source[key] === 'object' && !Array.isArray(source[key])) { result[key] = safeMerge(result[key] || {}, source[key]); } else { result[key] = source[key]; } } return result;}


4. Inyección NoSQL (MongoDB)

Al trabajar con MongoDB, pasar un objeto directamente desde la solicitud puede provocar la inyección de operadores $where o $regex.



// ❌ Código vulnerableapp.post('/login', async (req, res) => {  const { username, password } = req.body;  const user = await User.findOne({ username, password });  // Si se pasa { "$gt": "" }, se puede eludir la verificación});

// ✅ Variante seguraimport { sanitize } from 'mongo-sanitize';

app.post('/login', async (req, res) => { const cleanBody = sanitize(req.body); const user = await User.findOne({ username: cleanBody.username, password: cleanBody.password });});


5. Comandos del SO a través de child_process

Ejecutar entrada de usuario mediante exec sin escapar es una vulnerabilidad crítica.



// ❌ Código vulnerableimport { exec } from 'child_process';

function runCommand(input: string) { exec(`echo ${input}`, (err, stdout) => { console.log(stdout); });}

// ✅ Variante seguraimport { execFile } from 'child_process';

function safeCommand(input: string) { // Usamos execFile con un array de argumentos execFile('echo', [input], (err, stdout) => { console.log(stdout); });}


6. Path Traversal al trabajar con archivos

Blogs

Book Recommendations