Frameworks & libraries scanned
We test fixture coverage on these frameworks. New patterns are added with each builtin rule release.
Top CWE classes detected
These CWE classes appear most often in modern codebases of this language. StaticCodeAudit ships dedicated rules for each, mapped to OWASP Top 10 / ISO 27001 / ASVS where relevant.
CWE-79
Cross-Site Scripting (XSS)
innerHTML, dangerouslySetInnerHTML in React, v-html in Vue, Angular bypassSecurityTrust* with user data. Stored, reflected and DOM-based variants covered.
Detected by SCA rule: xss_innerhtml
CWE-1321
Prototype Pollution
Recursive Object.assign, _.merge, or unguarded obj[key] = value when key comes from user input. A single __proto__ key can break every downstream object.
Detected by SCA rule: prototype_pollution
CWE-89
SQL Injection
Sequelize.literal(), raw queries in Prisma $queryRaw\`${input}\`, Mongoose $where with strings, Knex .raw() with concat.
Detected by SCA rule: sql_injection_concat
CWE-918
SSRF
axios.get(url), fetch(url), http.get on user URLs. Particularly dangerous in serverless functions reachable via internal metadata endpoints.
Detected by SCA rule: taint_ssrf
CWE-798
Hardcoded Credentials
API keys committed in .env.example, config.js, or React process.env.REACT_APP_* exposed to client bundle.
Detected by SCA rule: hardcoded_secret
CWE-915
Mass Assignment
User.update(req.body) without field allow-list. Lets attackers escalate privileges (isAdmin: true) via JSON body.
Detected by SCA rule: mass_assignment
Vulnerable vs. clean — three quick examples
CWE-79
Detected by SCA rule: xss_innerhtml
// Vulnerable — React dangerouslySetInnerHTML
function Bio({ user }) {
return <div dangerouslySetInnerHTML={{ __html: user.bio }} />;
}
// Clean — text content, no HTML interpretation
function Bio({ user }) {
return <div>{user.bio}</div>;
}
CWE-1321
Detected by SCA rule: prototype_pollution
// Vulnerable — deep merge without proto guard
function merge(target, source) {
for (const key in source) {
if (typeof source[key] === "object") {
merge(target[key] = target[key] || {}, source[key]);
} else { target[key] = source[key]; }
}
}
// Clean — block __proto__/constructor
function merge(target, source) {
for (const key of Object.keys(source)) {
if (key === "__proto__" || key === "constructor") continue;
if (typeof source[key] === "object") {
merge(target[key] = target[key] || {}, source[key]);
} else { target[key] = source[key]; }
}
}
CWE-89
Detected by SCA rule: sql_injection_concat
// Vulnerable — concat in Sequelize.literal
const users = await User.findAll({
where: sequelize.literal(`name = \'${req.query.name}\'`)
});
// Clean — parameter binding
const users = await User.findAll({
where: { name: req.query.name }
});
What StaticCodeAudit detects (this language)
- XSS in React
dangerouslySetInnerHTML, Vuev-html, Angular trust bypass, vanillainnerHTML - Prototype pollution via deep merge, dynamic key assignment
- SQL injection in Sequelize, Mongoose, Prisma, TypeORM, Knex raw queries
- NoSQL injection (Mongoose
$wherewith strings, Mongo operators in user input) - SSRF via
axios,fetch,httpwith user URLs - Hardcoded secrets (API keys, JWT secrets, AWS, Stripe, GitHub, Slack tokens)
- Mass assignment in Sequelize/Mongoose without field allow-list
- Insecure cookies (
httpOnly,secure,sameSiteflags) - CSRF token missing in Express forms
- Path traversal in
fs.readFilewith user input - Insecure crypto (MD5 in
crypto, hardcoded IV, weak random) - Open redirect (
res.redirect(req.query.url)) - Outdated dependencies via
package.jsonpatterns - CI/CD misconfigurations (.gitlab-ci, GitHub Actions, npm scripts)
CVE Test Suite — the honest number for Express
StaticCodeAudit was measured against a real-world CVE Test Suite: 45 cases reconstructed from published, historical CVEs across 8 frameworks and 5 languages. Express is one of them — and it is the second-lowest-scoring framework in the whole suite.
Express, CVE-reconstructed
Disclosed, not hidden: Express/JavaScript sits second-lowest on the cross-language CVE table, precision at 72.7%. Complex multi-hop taint paths through middleware chains are the specific pattern the rule engine still misses in some Express CVEs. Full cross-language breakdown (including where Python and PHP score higher) on the <a href="/language-benchmarks.php" class="text-primary font-semibold hover:underline">language benchmarks page</a>.
Real vulnerabilities rarely live in one file
Express applications split logic across layers: a route handler receives the request, a data-access module builds the query. A scanner limited to one file at a time never connects the two — it sees user input in routes/orders.js and a database call in db/orders.js, but never the link between them. StaticCodeAudit follows the data across files.
router.get('/orders', (req, res) => {
const id = req.query.id;
res.json(findOrder(id));
});
function findOrder(id) {
const sql = `SELECT * FROM orders WHERE id = ${id}`;
return db.query(sql);
}
id comes from the query string in the route handler, and reaches the SQL query one file later, unmodified — StaticCodeAudit reports it at the exact line where the query runs.
How does this compare to ESLint or Semgrep?
ESLint (with security plugins like eslint-plugin-security) and Semgrep are the two tools that come up first when a JavaScript/TypeScript team looks for a free security scanner. Both are legitimate, and many teams already run one of them — here's an honest comparison, not a takedown.
ESLint + eslint-plugin-security
Free, open-sourceAlready part of most JS/TS toolchains, so adding the security plugin is nearly zero setup cost. Coverage is community-maintained and pattern-based (e.g. flags eval, unsafe regex) — no cross-file taint tracking, and findings aren't mapped to CWE/ISO 27001/ASVS out of the box.
Semgrep (Community)
Free, open-source corePattern-matching engine covering many languages, including JS/TS, with a large open rule registry. The free tier covers most day-to-day rules; cross-file taint tracking, compliance reporting and some enterprise integrations sit behind Semgrep's paid tiers.
Full StaticCodeAudit vs Semgrep comparison →Neither of these gets replaced by installing StaticCodeAudit — if your ESLint config already flags what your team needs, keep running it. What StaticCodeAudit adds on top: findings pre-mapped to CWE/OWASP/ISO 27001/ASVS/NIST CSF (a finding that's audit-ready, not just a rule ID), cross-file taint tracking across your route handlers and modules by default, and 7 other languages covered by the same binary — no separate scanner to configure per language. Many teams run both.
Audit your codebase
Audit your Node.js backends and front-end frameworks (React, Vue, Angular, Svelte) for XSS, prototype pollution, injection flaws and supply-chain risks — without uploading a line to the cloud.
Download demo binary Book a walkthrough