Contents
“One forgotten eval()
sank a fintech’s $2 M seed round. Let’s make sure it doesn’t happen to you.”
Nodejs makes shipping features fast; sometimes too fast. In 2025, public CVE data shows SQL/NoSQL injection is still the #1 flaw in Nodejs applications, followed closely by prototype pollution and malicious dependencies. Below you’ll find runnable code, real-world fixes, and a copy-paste checklist so you can push secure code without slowing CI/CD.
Why Nodejs Apps Get Pwned in 2025
Dependency sprawl: the average Express project pulls 1 200+ packages.
Event-loop blocking: a single ReDoS regex can spin CPU to 100 %.
Typosquatting: packages like electorn
(note the typo) still rack up 20 k weekly downloads before takedown.
The 7 Deadly Vulnerabilities & Code-Level Fixes
SQL/NoSQL Injection
Bad
|
|
Good
|
|
Use parameterized queries (pg
, mysql2
, mongodb
all support them). Validate IDs with Joi.number().integer().positive()
.
Prototype Pollution
Vulnerable
|
|
Fixed
|
|
Add Object.freeze(Object.prototype)
during bootstrap to prevent prototype tampering.
XSS & CSRF
XSS fix
|
|
CSRF fix
|
|
Send token in res.locals._csrf
and validate on every state-changing request.
ReDoS & DoS
ReDoS-safe regex
|
|
Rate-limiting
|
|
Malicious Dependencies
npm config set ignore-scripts true
npx lockfile-lint --path package-lock.json --allowed-hosts npm
npm audit --audit-level moderate
in CI.
Sensitive Data Exposure
- Store secrets in
.env
, never commit to Git. - Hash passwords with
bcrypt.hash(password, 12)
. - Add Helmet in one line:
|
|
Headers added include Strict-Transport-Security
, X-Content-Type-Options
, Content-Security-Policy
, etc.
SSRF & DNS Rebinding
Allow-list IPs
|
|
Disable inspector in prod: node --inspect=0.0.0.0:0
is never safe.
Nodejs Security Checklist 2025 (Copy-Paste Ready)
# | Task | CLI / Snippet |
---|---|---|
1 | Use Nodejs 20+ | nvm use 20 |
2 | Enable --experimental-permission |
node --experimental-permission --allow-fs-read=* index.js |
3 | Parameterize all queries | pool.query('SELECT * FROM users WHERE id = $1', [id]) |
4 | Freeze prototypes | Object.freeze(Object.prototype) |
5 | Add Helmet | app.use(helmet()) |
6 | Rate-limit sensitive routes | express-rate-limit |
7 | Audit deps | npm audit --audit-level moderate |
8 | Lint lockfile | npx lockfile-lint |
9 | Sanitize HTML | DOMPurify.sanitize() |
10 | Hash passwords | bcrypt.hash(password, 12) |
11 | Validate env | require('dotenv-safe').config() |
12 | Secure CI | npm ci --ignore-scripts |
Save as SECURITY.md
in repo root.
Tooling Deep-Dive
Tool | Type | Example |
---|---|---|
eslint-plugin-security | Static linting | npm i -D eslint-plugin-security "extends": ["plugin:security/recommended"] |
Snyk Code | SAST | npx snyk test |
CodeQL | GitHub-native | .github/workflows/codeql.yml |
Helmet vs express-rate-limit
Concern | Helmet | express-rate-limit |
---|---|---|
XSS | ✔ CSP header | ✖ |
Brute-force login | ✖ | ✔ |
ReDoS mitigation | ✖ | ✔ |
Lines of code | 1 | 3-5 |
Use both; they’re complementary.
Automating Security in CI/CD
.github/workflows/security.yml
|
|
FAQ
Q: How to prevent SQL injection in Nodejs?
A: Always use parameterized queries ($1
, $2
placeholders) and validate inputs with Joi
or zod
.
Q: Nodejs prototype pollution fix with example?
A: Freeze Object.prototype
on startup and sanitize deep merges as shown above.
Q: Best Nodejs security linter?
A: eslint-plugin-security for quick local checks; Snyk Code or CodeQL for deeper SAST in CI.
Conclusion & Next Step
Security doesn’t have to be a drag. Add the checklist to your repo, drop Helmet & rate-limiting into your app today, and let CI fail builds that introduce new vulns.
Sources
- OWASP Top 10 2021
- Nodejs Security WG CVE Reports 2023-24
- Snyk State of Open Source Security 2025
✨ Thank you for reading and I hope you find it helpful. I sincerely request for your feedback in the comment’s section.