The Thuban Audit — v0.4.6

We Scanned 10 of the Biggest JavaScript Repos. Here's What We Found — Including Our Own Mistakes.

Before launching Thuban, we pointed it at Express, Next.js, Strapi, Signal Desktop and six more of the most popular open-source projects in the JavaScript ecosystem. This is the full, honest breakdown: the real findings, the borderline calls, and the five categories of false positives we found in our own scanner — and fixed before publishing this.

9+1
repos scanned*
1,956
issues in production repos
19.8s
total scan time
5
false positive categories fixed

*9 production repos + OWASP Juice Shop, which is intentionally vulnerable and counted separately (see below).

Why we're publishing our own scanner's mistakes

Every developer's first objection to a code scanner is the same: "it's probably all false positives." Fair. Most scanners earn that reputation.

So instead of cherry-picking our best results, we're showing you the whole audit — including the moment our scanner flagged 213 issues in cal.com and 196 of them were wrong. We fixed the root cause, re-scanned, and cal.com dropped to 26 legitimate findings. That fix — and four others like it — shipped before this post did.

The principle Shipping a scanner with known false positives is worse than shipping no scanner at all. We stress-test Thuban against real codebases (and against itself, with our 515-pattern Crucible suite) before every release.

The results

RepoStarsFilesIssuesScan TimeNotable
Express66k100212874msXSS patterns in examples, hardcoded example passwords
Lodash60k515143.6sDeep nesting, complexity hotspots
Fastify33k1001251.3sComplexity warnings
Next.js130k1002025.7sPhantom imports in CI scripts
n8n50k1003992.8s295 magic numbers (mostly JSON config — noise, see below)
Strapi65k1001981.6sSSL validation disabled in setup script
cal.com33k100261.1sClean after our path-alias fix
Signal Desktop15k1001291.1sDeep nesting, quality warnings
LangChain.js13k1001511.1sMissing constants, perf warnings
Juice Shop*10k10085651msSQL injection everywhere — by design

*OWASP Juice Shop is a deliberately vulnerable training application. Thuban correctly flagged its planted vulnerabilities — a validation of detection capability, not a finding against the project. It is excluded from the 1,956 headline count.

The findings that matter

Strapi: SSL certificate validation disabled REAL

examples/complex/scripts/setup-v4-project.js — when database SSL is enabled, certificate validation is turned off:

ssl: env.bool('DATABASE_SSL', false)
  ? { rejectUnauthorized: false }
  : false,

This permits man-in-the-middle attacks on the database connection. Important context: this is in an example setup script, not Strapi's production runtime — but setup scripts get copy-pasted into production configs constantly. The fix is one line: rejectUnauthorized: true or a proper CA certificate.

Responsible disclosure We reported this to Strapi's security team before publishing, and we're framing it accurately: an insecure default in example tooling, not a runtime vulnerability. If you've copied this setup script, check your database config.

Express: XSS-shaped patterns in official examples BORDERLINE

res.send('users ' + names.slice(from, to + 1).join(', '));

The specific example isn't exploitable — the output comes from a hardcoded array. But res.send(user_influenced_data) without sanitisation is the exact pattern that becomes reflected XSS when a developer swaps in real data. Express examples are how millions of developers learn Node. Of 25 taint findings in Express, 23 were in test files (expected); 2 were in examples.

Express: hardcoded password in the auth example EXPECTED

hash({ password: 'foobar' }, function (err, pass, salt, hash) {

Example code with hardcoded credentials gets copy-pasted. The comment says "foobar is the pass here" — but how many people change it?

n8n: 295 magic numbers NOISE

Our magic-number rule fired on JSON configuration files, which are naturally full of numbers. That's a scanner limitation, not an n8n problem — it's on our fix list for v0.4.7. We're counting it against ourselves, not them.

The 5 false positives we fixed in our own scanner

This is the section most scanner vendors would delete. We think it's the most important one.

Fix 1 — node: protocol imports flagged as hallucinations

require('node:fs') — standard since Node 16 — was flagged as a phantom import.

Eliminated ~20 false positives across Fastify, Next.js, Signal.

Fix 2 — scanning inside comments

Patterns like eval() and SQL-injection regexes matched code examples inside JSDoc comments. Comment lines are now skipped except for rules designed for them (TODO/FIXME).

Lodash dropped 611 → 514 issues.

Fix 3 — sanitiser blindness

Data passing through escapeHtml(), DOMPurify.sanitize() and 20+ other sanitisers was still flagged as XSS. Taint analysis now recognises them.

Eliminated 3 false XSS findings in Express.

Fix 4 — self-referencing imports

Fastify's own tests doing require('fastify') were flagged as phantom imports. The scanner now walks up the directory tree checking package.json names, including workspaces.

Eliminated 7 false positives in Fastify.

Fix 5 — TypeScript path aliases

import X from '@/lib/thing' is a build-tool alias, not an npm package. The scanner treated it as a hallucinated dependency.

cal.com dropped 213 → 26 issues. The single biggest accuracy win of the audit.

What's still on our fix list

Full transparency — four known false-positive categories remain, targeted for v0.4.7:

CategoryPlan
Hardcoded-key detection firing on test fixturesExclude test/, *.spec.* from SEC001
Magic numbers in JSON config filesExclude .json from QUAL005
Monorepo workspace siblings flagged as phantom importsResolve across all workspace packages
"File too large" warnings on big JSON filesSilence for non-code files

Until then, any finding can be suppressed with // thuban-ignore.

What this proves

1. The scanner finds real issues. A genuine SSL misconfiguration in a 65k-star project's tooling. XSS-shaped teaching patterns in the framework everyone learns from. And it correctly identified every planted vulnerability in OWASP's deliberately vulnerable training app.

2. It's fast. 951 files, 10 repos, 19.8 seconds total. Roughly 2 seconds per repo.

3. We eat our own dog food. Five false positive categories found, fixed, and disclosed — before launch, not after your bug report.

Run the same audit on your own code

Everything runs locally. Your code never leaves your machine.

npm install -g thuban  &&  thuban scan .

Get Thuban

Methodology: Thuban v0.4.6, default ruleset (69 rules), capped at 100 files per repo, scanned July 2026 from each repo's default branch. Juice Shop findings excluded from headline counts as intentional. Strapi finding disclosed to their security team prior to publication. Questions or corrections: we want them — open an issue.