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

Security of TypeScript Applications: Top 10 Vulnerabilities for Beginners

\n\n

TypeScript is a superset of JavaScript that adds static typing but does not protect against classic web vulnerabilities. Beginner developers often rely on type strictness, forgetting about security at the logic and data level. In this article, we will analyze the 10 most common vulnerabilities in TypeScript applications with code examples and protection methods.

\n\n

1. XSS (Cross-Site Scripting) via dangerouslySetInnerHTML

\n

One of the most frequent problems is inserting user HTML without sanitization. In TypeScript, this is often encountered when working with React or Angular.

\n\n
// ❌ Vulnerable code\nfunction UserComment({ comment }: { comment: string }) {\n  return <div dangerouslySetInnerHTML={{ __html: comment }} />;\n}\n\n// ✅ Safe option\nimport DOMPurify from 'dompurify';\n\nfunction SafeComment({ comment }: { comment: string }) {\n  const sanitized = DOMPurify.sanitize(comment);\n  return <div dangerouslySetInnerHTML={{ __html: sanitized }} />;\n}
\n\n

2. SQL Injections via String Queries

\n

TypeScript does not protect against SQL injections if you use raw strings. Always use parameterized queries.

\n\n
// ❌ Dangerous\nconst query = `SELECT * FROM users WHERE email = '${userEmail}'`;\n\n// ✅ Safe (example with Prisma)\nconst user = await prisma.user.findUnique({\n  where: { email: userEmail }\n});
\n\n

3. Unsafe Storage of Secrets in Code

\n

API keys, tokens, and passwords should not end up in the source code. TypeScript compiles to JavaScript, and all strings remain readable.

\n\n
// ❌ Never do this\nconst API_KEY = 'sk-1234567890abcdef';\n\n// ✅ Use environment variables\nconst API_KEY = process.env.API_KEY;\nif (!API_KEY) throw new Error('API_KEY is missing');
\n\n

4. NoSQL Injections (MongoDB)

\n

When working with MongoDB via Mongoose or the driver, you can accidentally pass a query object that manipulates the logic.

\n\n
// ❌ Vulnerable code\napp.post('/login', async (req, res) => {\n  const user = await User.findOne({ \n    email: req.body.email, \n    password: req.body.password \n  });\n});\n\n// ✅ Safe option\napp.post('/login', async (req: Request, res: Response) => {\n  const { email, password } = req.body;\n  if (typeof email !== 'string' || typeof password !== 'string') {\n    return res.status(400).send('Invalid input');\n  }\n  const user = await User.findOne({ email, password });\n});
\n\n

5. CSRF (Cross-Site Request Forgery)

\n

If your application uses cookie authentication, an attacker can perform actions on behalf of the user.

\n\n
// ❌ Lack of protection\napp.post('/transfer', (req, res) => {\n  // Executing transfer without checking the source\n});\n\n// ✅ Protection via CSRF token (example with csurf)\nimport csrf from 'csurf';\nconst csrfProtection = csrf({ cookie: true });\napp.post('/transfer', csrfProtection, (req, res) => {\n  // Safe execution\n});
\n\n

6. Prototype Pollution

\n

When merging objects without validation, you can overwrite prototype properties, leading to vulnerabilities.

\n\n
// ❌ Dangerous\nfunction merge(target: any, source: any) {\n  for (const key in source) {\n    target[key] = source[key];\n  }\n}\n\n// ✅ Safe\nfunction safeMerge(target: Record<string, any>, source: Record<string, any>) {\n  for (const key in source) {\n    if (Object.prototype.hasOwnProperty.call(source, key)) {\n      target[key] = source[key];\n    }\n  }\n}
\n\n

7. Information Leakage via Errors

\n

Stack traces and database details should not be shown to the user. TypeScript can lull vigilance due to strict types.

\n\n
// ❌ Bad\napp.use((err, req, res, next) => {\n  res.status(500).json({ error: err.m                

Blogs

Book Recommendations