Security

TypeScript Security Mistakes — What Type Safety Doesn't Prevent

TypeScript's type system gives a false sense of security. Types prevent type errors — not security vulnerabilities. SQL injection, XSS, and hardcoded secrets compile fine with perfect TypeScript types. Here are the security mistakes TypeScript developers make assuming they're protected.


What is TypeScript security?

TypeScript adds static type checking to JavaScript — it will catch string + number type mismatches. It will NOT catch SQL injection, XSS, or hardcoded secrets. These are runtime data flow problems, not type problems. TypeScript compiles to JavaScript and runs in exactly the same security context.


1

XSS through any type bypasses type checks

Using any to handle user input disables type checking and can silently enable XSS.

❌ any props enable XSS

// The type says string, but any bypassed the check
interface Props { content: any }  // ← any = no type safety

function UserContent({ content }: Props) {
  // dangerouslySetInnerHTML with any — TypeScript won't warn
  return <div dangerouslySetInnerHTML={{ __html: content }} />
  // If content = '<script>steal(document.cookie)</script>' → XSS
}

✅ Strict types + sanitization

import DOMPurify from 'dompurify'

interface Props { content: string }  // ← Explicit type

function UserContent({ content }: Props) {
  const sanitized = DOMPurify.sanitize(content)
  return <div dangerouslySetInnerHTML={{ __html: sanitized }} />
  // Or better: avoid innerHTML entirely, use textContent
}
2

SQL injection with Prisma $queryRawUnsafe

Prisma's $queryRawUnsafe bypasses parameterization. TypeScript types don't prevent injection.

❌ Type-safe but SQL-injectable

// TypeScript: correct types, still vulnerable
async function searchUsers(query: string): Promise<User[]> {
  // $queryRawUnsafe interpolates directly — type doesn't help
  return prisma.$queryRawUnsafe(
    `SELECT * FROM User WHERE name LIKE '%${query}%'`
  )
  // Input: "'; DROP TABLE User; --" → disaster
}

✅ Prisma.sql parameterizes correctly

import { Prisma } from '@prisma/client'

async function searchUsers(query: string): Promise<User[]> {
  return prisma.$queryRaw(
    Prisma.sql`SELECT * FROM User WHERE name LIKE ${'%' + query + '%'}`
  )
  // Or use Prisma ORM — no raw SQL needed:
  return prisma.user.findMany({ where: { name: { contains: query } } })
}
3

Hardcoded secrets in TypeScript config

TypeScript developers sometimes hardcode API keys in typed config objects, thinking types make them safe.

❌ Typed but exposed

// Looks professional with types — still a security disaster
const config: AppConfig = {
  database: { host: 'prod.db.example.com', password: 'Secr3t!Pass' },
  stripe: { secretKey: 'sk_live_abc123xyz...' },
  jwt: { secret: 'mysecretkey' },
}

✅ Environment variables with typed access

// Type-safe environment variable access
function getRequiredEnv(key: string): string {
  const value = process.env[key]
  if (!value) throw new Error(`Missing required env var: ${key}`)
  return value
}

const config: AppConfig = {
  database: { host: getRequiredEnv('DB_HOST'), password: getRequiredEnv('DB_PASS') },
  stripe: { secretKey: getRequiredEnv('STRIPE_SECRET_KEY') },
  jwt: { secret: getRequiredEnv('JWT_SECRET') },
}
💡

Pro tip: Enable TypeScript's strict mode (strict: true in tsconfig.json) — it catches noImplicitAny which forces you to be explicit about types. This reduces the surface area for security mistakes but doesn't eliminate them. Still need security analysis.


Scan Your TypeScript for Security Issues

Paste your code — LearnCodeGuide detects all these issues automatically using GPT-4o + Claude Sonnet. Free to start.

Analyze TypeScript Code →

Related Guides

XSS in TypeScriptSQL Injection in TypeScriptHardcoded Secrets in TypeScriptTypeScript Code Review GuideJavaScript Security Checklist

Published by LearnCodeGuide Team · Last reviewed: November 2025