Security of TypeScript Applications: Top 10 Vulnerabilities and Protection

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why TypeScript Application Security is Critical

TypeScript is a superset of JavaScript that adds static typing and modern capabilities. However, typing does not guarantee security. Validation errors, improper handling of user input, and vulnerabilities in dependencies can lead to serious attacks. In this article, we will break down the top 10 most common vulnerabilities in TypeScript applications, provide code examples, and show how to avoid them.



1. Cross-Site Scripting (XSS)

XSS attacks occur when an attacker injects a malicious script into a web page. TypeScript does not automatically protect against this.

Example of vulnerable code

function renderUserInput(input: string): string {  return `<div>${input}</div>`;}

// Attacker passes: <script>alert('XSS')</script>

Solution

Use HTML character escaping or libraries like DOMPurify:

import DOMPurify from 'dompurify';

function renderUserInputSafe(input: string): string { const sanitized = DOMPurify.sanitize(input); return `<div>${sanitized}</div>`;}


2. SQL Injection

If you use TypeScript with databases, uncontrolled string concatenation in SQL queries can lead to data leaks.

Example of vulnerable code

async function getUser(id: string): Promise<User | null> {  const query = `SELECT * FROM users WHERE id = '${id}'`;  return await db.query(query);}

Solution

Use parameterized queries (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. Prototype Pollution

This vulnerability is characteristic of JavaScript/TypeScript. An attacker can modify an object's prototype, affecting all objects at runtime.

Example of vulnerable code

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}}'));// Now all objects have isAdmin: true

Solution

Check keys for dangerous properties and use safe utilities:

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)

CSRF attacks force a user to perform unwanted actions on a site where they are authenticated.

Solution in TypeScript

// CSRF token generationimport crypto from 'crypto';

function generateCsrfToken(): string { return crypto.randomBytes(32).toString('hex');}

// Verification in 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. Insecure Deserialization

Using JSON.parse() or eval() on unverified data can lead to arbitrary code execution.

Vulnerable example

function processData(data: string) {  const obj = eval('(' + data + ')');  // ...}

Safe approach

function processDataSafe(data: string) {  try {    const obj = JSON.parse(data);    // Additional type validation    if (typeof obj !== 'object' || obj === null)                

Blogs

Book Recommendations