Security of TypeScript Applications: Top 10 Vulnerabilities for Beginners

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 Matters from Day One

TypeScript is a superset of JavaScript that adds static typing. Many beginner developers mistakenly believe that typing automatically solves all security problems. In reality, TypeScript compiles to regular JavaScript, and all vulnerabilities inherent to JS remain relevant. In this article, we will break down the top 10 vulnerabilities that beginners face and show how to avoid them.



1. XSS (Cross-Site Scripting)

XSS is one of the most common attacks. An attacker injects a malicious script into a page, which executes in the user's browser.

Example of vulnerable code:

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

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

How to fix:

Always escape user input. Use libraries like DOMPurify or built-in escaping methods:

import DOMPurify from 'dompurify';

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


2. SQL Injections

If you form SQL queries by concatenating strings with user input, you open the door to SQL injections.

Vulnerable code:

function getUser(username: string): Promise<User> {    const query = `SELECT * FROM users WHERE username = '${username}'`;    return db.execute(query);}

Safe alternative:

function getUserSafe(username: string): Promise<User> {    const query = 'SELECT * FROM users WHERE username = $1';    return db.execute(query, [username]); // parameterized query}


3. Unsafe Password Storage

Never store passwords in plain text. Use bcrypt or argon2 for hashing.

import bcrypt from 'bcrypt';

async function hashPassword(password: string): Promise<string> { const saltRounds = 12; return bcrypt.hash(password, saltRounds);}

async function verifyPassword(password: string, hash: string): Promise<boolean> { return bcrypt.compare(password, hash);}


4. Insecure Direct Object References (IDOR)

When a user can access other users' data simply by changing an ID in the URL.

Example:

// Vulnerable: any user can get any orderapp.get('/api/order/:id', (req, res) => {    const order = getOrderById(req.params.id);    res.json(order);});

// Safe: check ownershipapp.get('/api/order/:id', (req, res) => { const order = getOrderById(req.params.id); if (order.userId !== req.user.id) { return res.status(403).json({ error: 'Forbidden' }); } res.json(order);});


5. Using Outdated Dependencies

TypeScript projects often use npm packages. Outdated versions may contain known vulnerabilities.

  • Regularly run npm audit
  • Use npm update to update packages
  • Set up automatic checks in CI/CD


6. Insufficient Input Validation

TypeScript types are not checked at runtime. Always validate data on the server.

interface UserInput {    email: string;    age: number;}

// Not enough: TypeScript types do not protect at runtimefunction processUser(input: UserInput) { // ...}

// Correct: use Zod or Joi for validationimport { z } from 'zod';

const UserSchema = z.object({ email: z.string().email(), age: z.number().min(18).max(120)});

function processUserSafe(input: unknown) { const validate

Blogs

Book Recommendations