Independent Benchmark — 55 Real-World Express & Next.js Repos

98% precision on the backend bugs that matter

829 checks across 55 production repos. Compared against Semgrep Pro, Snyk Code, and GitHub GHAS. Every finding manually labeled.

Head-to-Head Comparison

MetricSecurityChecksSemgrep ProSnyk CodeGitHub GHAS
Precision98.2%65%62%58%
False positive rate1.8%35%38%42%
Avg findings/repo148794112
Avg scan time28s45s60s90s
Express + Next.js depth

What only SecurityChecks catches

Framework-specific backend bugs that generic scanners miss entirely. These require understanding Express middleware ordering, Next.js caching semantics, and cross-file auth call chains.

E

Express Deep Pack

8 cross-file checkers

Auth middleware ordering gaps

Routes where body parsing happens before auth, enabling payload DoS

Route-level ownership verification

Routes with :id params that call services without ownership checks in the call chain

Sub-router auth bypass

Sub-routers mounted without auth middleware, exposing all child routes

Auth route rate limiting

Login/register endpoints without brute-force protection

Error handler stack leak

Error handlers that send err.stack to clients in production

Unprotected data mutations

POST/PUT/DELETE routes calling data-mutating services with no auth anywhere in the chain

N

Next.js Deep Pack

8 cross-file checkers

Server Action input validation

Server Actions passing FormData directly to database without zod/validation

Route Handler ownership gaps

Route Handlers with [id] params that skip ownership verification

Cached user-specific data

Pages using ISR/cache on data that includes session or user-specific content

Parallel route auth inconsistency

Parallel routes (@modal, @sidebar) missing auth that sibling routes have

Stale auth in cached pages

Cached pages reading session state without revalidation on auth changes

Revalidation endpoint auth

On-demand revalidation routes without authentication, enabling cache purge DoS

Semgrep Pro, Snyk, and GHAS have zero rules for these categories. Their JS/TS interfile analysis covers generic dataflow (SQLi, XSS, command injection) but not framework-specific middleware ordering, cache semantics, or auth call chain verification.

Precision by Category

Secrets & Credentials

SecurityChecks
98%
Semgrep Pro
82%
Snyk Code
85%
GitHub GHAS
80%

SQL/NoSQL Injection

SecurityChecks
99%
Semgrep Pro
72%
Snyk Code
70%
GitHub GHAS
65%

XSS

SecurityChecks
97%
Semgrep Pro
68%
Snyk Code
65%
GitHub GHAS
60%

Auth & Access Control

SecurityChecks
98%
Semgrep Pro
55%
Snyk Code
50%
GitHub GHAS
45%

CSRF / IDOR / Mass Assignment

SecurityChecks
99%
Semgrep Pro
60%
Snyk Code
55%
GitHub GHAS
40%

Cryptography

SecurityChecks
97%
Semgrep Pro
75%
Snyk Code
72%
GitHub GHAS
70%

Express Middleware & Config

SecurityChecks
98%
Semgrep Pro
40%
Snyk Code
35%
GitHub GHAS
30%

Next.js Server Actions & Cache

SecurityChecks
99%
Semgrep Pro
25%
Snyk Code
20%
GitHub GHAS
15%

Webhooks & Idempotency

SecurityChecks
99%
Semgrep Pro
Snyk Code
GitHub GHAS

Race Conditions & Business Logic

SecurityChecks
97%
Semgrep Pro
10%
Snyk Code
5%
GitHub GHAS

Why Precision Matters

Real false positive examples from competitor tools on production codebases. SecurityChecks filters these out because it understands framework context.

Semgrep Pro false positivejavascript.express.security.audit.xss.mustache-escape
// Template rendering with auto-escaped framework (Next.js JSX)
return <div>{userData.name}</div>;

React/JSX auto-escapes by default. SecurityChecks understands framework context — this is not XSS.

Snyk Code false positivejavascript/NoSQLInjection
const user = await prisma.user.findUnique({ where: { id } });

Prisma ORM parameterizes all queries by design. Only $queryRaw is injectable.

GitHub GHAS false positivejs/path-injection
const config = require(`./config/${environment}.json`);

environment is from process.env (server-controlled), not user input.

Semgrep Pro false positivejavascript.lang.security.detect-non-literal-require
const plugin = require(`./plugins/${name}`); // name from internal config

Path is constructed from validated config, not user input. SecurityChecks tracks data flow origin.

Every finding is real

98% precision means you spend time fixing, not triaging. No more alert fatigue from generic scanners.

Framework-aware

829 checks purpose-built for Express and Next.js. Understands middleware ordering, Server Actions, caching semantics.

Cross-file analysis

Auth call chain verification, ownership checks across service boundaries, cache invalidation tracking — not just pattern matching.

Methodology

Repos: We selected 55 popular open-source JavaScript and TypeScript repositories using Express, Next.js, NestJS, Fastify, tRPC, and more. All repos have 1,000+ GitHub stars.

Tools: Each repo was scanned with SecurityChecks (829 checks including 74 cross-file engine checkers), Semgrep Pro with JS/TS interfile analysis, Snyk Code, and GitHub CodeQL (GHAS).

Labeling: Every finding was manually classified as True Positive (TP) or False Positive (FP) by reviewing the source code, checking framework context, and verifying exploit feasibility.

Precision formula: TP / (TP + FP) * 100. A tool that reports 100 findings with 35 false positives has 65% precision.

Framework depth: For each tool, we evaluated whether it detects framework-specific issues (Express middleware ordering, Next.js cache semantics, auth call chain verification) versus only generic vulnerability patterns (SQLi, XSS, secrets).

Fairness: All tools ran with recommended production configs. No custom rules were added. Source code and scripts are available for reproducibility.

Try it on your codebase

See the difference framework-aware security makes. Connect your repo, get results in your PR.