Back to Blog
tips11 min read

Web Security Essentials: OWASP Top 10 for Node.js and React

Practical security — preventing SQL injection, XSS, broken authentication, and IDOR in Node.js applications.

V
By Ventra Rocket
·Published on 20 January 2026
#Security#OWASP#Node.js#XSS#SQL Injection

Most web breaches exploit preventable vulnerabilities. This guide covers the OWASP Top 10 with practical code.

1. SQL Injection Prevention

// VULNERABLE
const users = await db.query(`SELECT * FROM users WHERE email = '${email}'`);

// SAFE — parameterized query
const users = await db.query("SELECT * FROM users WHERE email = $1", [email]);

// SAFE — ORM
const user = await prisma.user.findUnique({ where: { email } });

2. Secure Authentication

import bcrypt from "bcryptjs";
import { SignJWT } from "jose";

async function hashPassword(password: string) {
  return bcrypt.hash(password, 12);
}

async function signToken(userId: string) {
  const secret = new TextEncoder().encode(process.env.JWT_SECRET);
  return new SignJWT({ sub: userId })
    .setProtectedHeader({ alg: "HS256" })
    .setExpirationTime("15m")
    .sign(secret);
}

3. XSS Prevention

// React auto-escapes JSX — safe by default
const Profile = ({ name }: { name: string }) => <h1>{name}</h1>;

// Sanitize rich text before rendering
import DOMPurify from "isomorphic-dompurify";
const SafeContent = ({ html }: { html: string }) => (
  <div
    dangerouslySetInnerHTML={{
      __html: DOMPurify.sanitize(html, {
        ALLOWED_TAGS: ["p", "b", "i", "ul", "ol", "li", "a"],
      }),
    }}
  />
);

4. Access Control (IDOR Prevention)

// SAFE — verify resource ownership before returning data
app.get("/orders/:id", authenticate, async (req, res) => {
  const order = await db.orders.findFirst({
    where: { id: req.params.id, userId: req.user.id },
  });
  if (!order) return res.status(404).json({ error: "Not found" });
  res.json(order);
});

5. Security Headers with Helmet

import helmet from "helmet";

app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'"],
    },
  },
  hsts: { maxAge: 31536000, includeSubDomains: true },
}));

6. Rate Limiting

import rateLimit from "express-rate-limit";
const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 5,
  message: "Too many login attempts.",
});
app.post("/auth/login", loginLimiter, loginHandler);

Security Checklist

  • Parameterized queries for all SQL
  • Passwords hashed with bcrypt (rounds >= 12)
  • JWT access tokens expire < 1 hour
  • Login rate-limited (5 attempts / 15 min)
  • Security headers via Helmet
  • CORS restricted to known origins
  • All endpoints check authorization, not just authentication
  • Rich text sanitized before rendering
  • Secrets excluded from logs

Conclusion

Security built from day one. Ventra Rocket includes a security review in every project delivery, checking against the OWASP checklist.

Related Articles

Web Security Essentials: OWASP Top 10 for Node.js and React | Ventra Rocket