OWASP Top 10 Web Application Security: Vulnerabilities & Remediation in Modern Web Stacks
A developer's guide to fixing OWASP Top 10 vulnerabilities in modern TypeScript, Next.js, and Node.js web applications: Broken Access Control, Injection, SSRF, and Cryptographic Failures.

Header Ad Advertisement
Web application security in modern full-stack development is no longer the exclusive domain of dedicated penetration testers. With full-stack frameworks (Next.js, Remix, Fastify, NestJS) running complex server-side compute and edge functions, frontend and backend engineers must proactively understand and remediate the OWASP Top 10 security vulnerabilities.
A single architectural oversightโsuch as exposing a database ID in a REST endpoint without verifying session ownershipโcan expose an entire customer database to catastrophic exfiltration.
Here is a practical, code-heavy deep dive into the most prevalent vulnerabilities and their definitive production mitigations.
1. A01: Broken Access Control (The #1 Web Vulnerability)
Broken Access Control occurs when an application permits a user to access resources or execute actions outside their intended permission boundary. The most infamous variant is the Insecure Direct Object Reference (IDOR).
Vulnerable Code Example (Trusting Client Input):
// VULNERABLE: Anyone can read any invoice by tampering with the URL ID
app.get('/api/invoices/:invoiceId', async (req, res) => {
const { invoiceId } = req.params;
const invoice = await db.invoices.findById(invoiceId);
return res.json(invoice);
});
Secure Remediation (Enforcing Session Ownership):
// SECURE: Enforces that the invoice belongs strictly to the authenticated organization
app.get('/api/invoices/:invoiceId', authenticateSession, async (req, res) => {
const { invoiceId } = req.params;
const currentOrgId = req.user.organizationId;
const invoice = await db.invoices.findOne({
_id: invoiceId,
organizationId: currentOrgId, // Critical tenant isolation
});
if (!invoice) {
// Return 404 rather than 403 to prevent ID enumeration scanning
return res.status(404).json({ error: 'Invoice not found' });
}
return res.json(invoice);
});
2. A02: Cryptographic Failures & Password Hashing
Cryptographic failures involve storing sensitive data in cleartext, employing outdated algorithms (MD5, SHA-1, DES), or leaking secret tokens in Git repositories.
Best Practices for Modern Cryptography:
- Password Hashing: Always use Argon2id (OWASP recommended) or bcrypt with a minimum work factor of 12.
- Secrets Management: Never commit
.envfiles. Use AWS Secrets Manager, HashiCorp Vault, or Vercel Environment Variables. - Data at Rest: Encrypt sensitive Personally Identifiable Information (PII) like Aadhaar numbers, tax IDs, or medical history with AES-256-GCM.
import argon2 from 'argon2';
// Modern password hashing using Argon2id
export async function hashPassword(plainText: string): Promise<string> {
return await argon2.hash(plainText, {
type: argon2.argon2id,
memoryCost: 65536, // 64 MB RAM
timeCost: 3, // 3 iterations
parallelism: 1,
});
}
3. A03: Injection (SQL, NoSQL, and Command Injection)
Injection occurs when untrusted user input is concatenated directly into a query interpreter without sanitization or parameterization.
Vulnerable vs Secure PostgreSQL Query:
// โ CRITICAL RISK: SQL Injection via String Concatenation
const query = `SELECT * FROM users WHERE email = '${req.body.email}'`;
const result = await client.query(query);
// โ
SECURE: Parameterized Query using Placeholders ($1, $2)
const safeQuery = `SELECT id, email, role FROM users WHERE email = $1`;
const safeResult = await client.query(safeQuery, [req.body.email]);
NoSQL Injection Warning (MongoDB / Mongoose):
Attackers can send JSON payloads containing operator objects: {"username": "admin", "password": {"$gt": ""}}.
Always sanitize inputs using mongo-sanitize or validate schemas strictly with Zod:
import { z } from 'zod';
const LoginSchema = z.object({
username: z.string().min(3).max(50),
password: z.string().min(8).max(100), // Enforces pure string, blocking MongoDB object injection
});
4. A05: Security Misconfiguration & Missing HTTP Headers
Default server headers often leak underlying technology stacks (e.g. X-Powered-By: Express or Server: Apache/2.4.41), facilitating targeted automated exploit toolkits.
Essential Security Headers to Configure in Next.js / Express:
// next.config.js - Enterprise Security Headers
module.exports = {
async headers() {
return [
{
source: '/(.*)',
headers: [
{
key: 'X-DNS-Prefetch-Control',
value: 'on',
},
{
key: 'Strict-Transport-Security',
value: 'max-age=63072000; includeSubDomains; preload',
},
{
key: 'X-Frame-Options',
value: 'DENY', // Prevents Clickjacking attacks
},
{
key: 'X-Content-Type-Options',
value: 'nosniff', // Prevents MIME-type confusion attacks
},
{
key: 'Referrer-Policy',
value: 'origin-when-cross-origin',
},
{
key: 'Content-Security-Policy',
value: "default-src 'self'; script-src 'self' https://pagead2.googlesyndication.com; img-src 'self' data: https:;",
},
],
},
];
},
};
5. A10: Server-Side Request Forgery (SSRF)
SSRF vulnerabilities occur when a web application accepts a user-supplied URL and executes a server-side fetch() or axios.get() request without validating the destination IP.
The AWS / GCP Metadata Exfiltration Attack:
An attacker inputs http://169.254.169.254/latest/meta-data/iam/security-credentials/ into your "Import Website Preview" feature, causing your backend EC2 instance or Cloud Run container to download and return its own administrative IAM role credentials!
Bulletproof SSRF Defense Pattern:
import ipaddr from 'ipaddr.js';
import dns from 'dns/promises';
export async function validateSafeUrl(targetUrl: string): Promise<boolean> {
const parsed = new URL(targetUrl);
// 1. Enforce HTTPS only
if (parsed.protocol !== 'https:') return false;
// 2. Resolve DNS hostname to raw IP
const addresses = await dns.resolve4(parsed.hostname);
for (const ip of addresses) {
const addr = ipaddr.parse(ip);
// Block private ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.1, 169.254.0.0/16)
if (addr.range() !== 'unicast') {
return false; // Blocks internal subnet & cloud metadata attempts
}
}
return true;
}
6. Enterprise Security CI/CD Checklist
To maintain a zero-vulnerability software lifecycle, integrate these 5 automated security gates into your GitHub Actions / GitLab CI pipeline:
- Static Application Security Testing (SAST): Run
semgreporSonarQubeon every pull request to catch hardcoded secrets and unescaped HTML injections. - Software Bill of Materials (SBOM) & Dependency Audits: Run
npm audit --audit-level=highor Snyk to block packages with known CVEs. - Automated Rate Limiting: Enforce distributed Redis token-bucket rate limiters on
/api/auth/*and public submission endpoints. - CORS Hardening: Never use
Access-Control-Allow-Origin: *withcredentials: true. - Periodic Penetration Testing: Conduct annual third-party black-box and white-box penetration audits.
Security Golden Rule
Never trust client data. Validate every payload on the server with strict type schemas (Zod/Valibot), enforce tenant-aware authorization in every database query, and encrypt all sensitive credentials at rest and in transit.
Mid Content Ad Advertisement
Interactive Developer Tools & Converters
View All Tools โMarkdown Live Editor
Live Markdown editor with split-screen preview and HTML export.
Markdown Previewer
Real-time Markdown to HTML previewer and syntax validator with instant copy.
JSON Formatter
Format, validate and beautify JSON with syntax highlighting and error detection.
Base64 Encoder
Encode and decode Base64 strings and files instantly in your browser.
Editorial Disclaimer
The security techniques, vulnerabilities, and code examples discussed in this article are shared strictly for educational and defensive security purposes. Do not use this knowledge to conduct unauthorized access, penetration testing, or any illegal activity on systems you do not own or have explicit written permission to test. Always comply with applicable laws in your jurisdiction.
Last content review: September 2026 ยท Learntrix by Vyuhantrix
Copyright 2026 Vyuhantrix Technologies. All content on Learntrix is the intellectual property of Vyuhantrix. Reproduction, distribution, or republishing of this article โ in whole or in part โ without written permission from Vyuhantrix is strictly prohibited.
Footer Article Ad Advertisement
Related Articles
View all in Cyber Security โ
Zero-Trust Kubernetes Security: SPIFFE, Istio mTLS, and eBPF Kernel Hardening
An enterprise guide to implementing true Zero-Trust security inside Kubernetes: cryptographically verifiable SPIFFE/SPIRE workload identities, automated Istio mTLS, and eBPF runtime threat detection.
