High Risk — fix 3 things before you ship.High Risk — fix 3 things before you make it live.High Risk — fix 3 things before you ship.
81/ 100executive score · higher is betterthe one overall score · higher is betterexecutive score · higher is better
Material risks remain. Remediate before relying on this in production.Real risks remain. Fix these before you rely on this for real users.Fix these risks before shipping to real users.
82Production ReadinessReady for real usersProduction Readiness72Security90Privacy92ArchitectureHow the code is put togetherArchitecture90IP ProtectionProtecting your ideasIP Protection
Read it:
3 things to fix before you ship3 things to fix before you launch3 things to fix before you ship
A finite, ranked list — highest-severity, lowest-effort blockers first. Clear these and the verdict lifts.A short, ranked list — the most serious, easiest-to-fix problems first. Clear these and the verdict improves.Ranked by severity and effort. Clear these and the verdict lifts.
body-parser@1.20.2 pinned with HIGH DoS advisory (urlencoded)
High·Security·package.json·Small (hours)Quick (a few hours)Small (hours)
EvidenceWhat we foundEvidence
package.jsondependencies: "body-parser": "1.20.2"; re-exported in lib/express.js (exports.json/urlencoded/raw/text = bodyParser.*). OSV: GHSA-qwcr-r2fm-qrc7 (HIGH) plus GHSA-v422-hmwv-36x6 (LOW).
Business impactWhy it mattersImpact
When URL encoding is enabled, body-parser is vulnerable to a denial of service; the urlencoded/json parsers are a core, commonly-mounted request path in Express apps. Reachability into the vulnerable path was not verified by the scanner, but these middlewares are first-class Express exports.
Root causeWhy it happensCause
Pinned direct dependency at a version predating the fix.
Recommended fixHow to fix itFix
Upgrade body-parser to a patched version and re-run the express.urlencoded/json test suites already present in test/.
RemediationHow to fix itRemediationSmall (hours)Quick (a few hours)Small (hours)
Useful?
path-to-regexp@0.1.7 pinned with multiple HIGH ReDoS advisories
package.jsondependencies: "path-to-regexp": "0.1.7"; used in lib/router/layer.js (var pathRegexp = require('path-to-regexp')). OSV: GHSA-37ch-88jc-xwx2, GHSA-9wv6-86v2-598j, GHSA-rhx6-c78j-4q9w (all HIGH).
Business impactWhy it mattersImpact
Route patterns containing multiple parameters can be compiled into backtracking regular expressions, enabling a Regular Expression Denial of Service against any Express app that defines such routes — a single crafted request can consume CPU and stall the event loop. path-to-regexp is directly exercised by Layer for every route, so the vulnerable code is plausibly reachable, though the scanner did not confirm exploitability in this repo.
CI pins third-party GitHub Action to mutable @master ref
Medium·Infrastructure & DevOps·.github/workflows/ci.yml:216·Trivial (<1h)Very quick (under an hour)Trivial (<1h)
EvidenceWhat we foundEvidence
.github/workflows/ci.yml:216"uses: coverallsapp/github-action@master" (also flagged by IaC scanner gha-unpinned-action).
Business impactWhy it mattersImpact
A mutable ref means the action's code can change without review; a compromise or malicious update to that action would run in CI with access to the GITHUB_TOKEN, a supply-chain risk. Static config only — the deployed CI state was not inspected.
Root causeWhy it happensCause
Action referenced by branch instead of a pinned commit SHA or version tag.
Everything else we foundEverything else we noticedEverything else
7 more findings across 4 dimensions — none blocking, all worth a look.7 more problems across 4 categories — none blocking, all worth a look.7 more findings — none blocking.
10Findings in allTotal problems foundAll findings
2High
2Medium
4Low
2Info
Security
How we scored it
Five component scores roll up into the one number — and the verdict is held to the evidence, not to how the write-up reads.Five scores combine into the one overall number — and the verdict is checked against the actual evidence, not just how the write-up sounds.Five scores roll into one number. The verdict is held to the evidence, not the write-up.
Production ReadinessReady for real usersProduction Readiness82
Full coverage — every eligible source and configuration file was audited.
41 other files aren’t code this audit reads — images, lockfiles, generated output, and similar non-source content.
Show the 41 files
stylesheets (4)
examples/ejs/public/stylesheets/style.css
examples/mvc/public/style.css
examples/route-separation/public/style.css
examples/static-files/public/css/style.css
other file types this audit doesn't read (37)
.editorconfig
.eslintignore
LICENSE
benchmarks/run
In the model’s wordsWhat the AI wrote, in its own wordsThe model's words
The executive summary, as Claude wrote it. Evidence, scores and the verdict are computed by nittim.The summary, as Claude wrote it. The evidence, scores and verdict are computed by nittim, not by Claude.Claude wrote this summary. nittim computes the evidence, scores, and verdict.
executive summary · in the model’s wordssummary · in the AI’s own wordssummary · in the model's words
Claude says
Evidence, scores, and the verdict above are computed by nittim. The written read below — this summary and every finding’s narrative — is Claude’s.The evidence, scores, and the verdict above are computed by nittim. The written explanation below — this summary and every finding’s write-up — is Claude’s, the AI assistant that reviewed your code.nittim computes the evidence, scores, and verdict. Claude writes the summary below.
This snapshot is the Express.js web framework (v4.19.1), a mature, widely-deployed, human-authored open-source project maintained by the OpenJS Foundation. The codebase is well-structured, exceptionally well-tested (hundreds of acceptance and unit tests), and follows consistent, idiomatic conventions. It is a library/framework rather than a data-handling application, so most privacy/GDPR concerns are not applicable — Express does not itself collect, store, or transmit personal data. The primary production-safety concern is the set of 14 known-vulnerable transitive/direct dependencies pinned in package.json, several rated HIGH (path-to-regexp ReDoS, body-parser DoS), though the OSV scanner did not verify reachability. A CI workflow pins a third-party GitHub Action to a mutable @master ref. Example applications ship hardcoded session secrets, but these are clearly demonstration code, not production surfaces. No hardcoded credentials and no prompt-injection/audit-tampering content were found. Overall this is a production-grade codebase; the actionable work is dependency maintenance and CI hardening.
Root causeWhy it happensCause
Direct dependency pinned to an old vulnerable version (0.1.7); Express 4.x historically pins this exact version.
Recommended fixHow to fix itFix
Upgrade to a patched path-to-regexp release (or a maintained Express line that pins it), then re-run tests. Track and periodically bump the pinned version.
RemediationHow to fix itRemediationMedium (1–3d)Medium (1–3 days)Medium (1–3d)
Useful?
Recommended fixHow to fix itFix
Pin the action to a full commit SHA (or at minimum a versioned tag) and enable Dependabot for GitHub Actions.
RemediationHow to fix itRemediationTrivial (<1h)Very quick (under an hour)Trivial (<1h)
Useful?
Priority: Core
4 findings
qs@6.11.0 pinned with arrayLimit-bypass DoS advisories · send@0.18.0 / serve-static@1.15.0 template-injection XSS advisories · cookie@0.6.0 accepts out-of-bounds characters in name/path/domain · Example apps ship hardcoded session/cookie secrets
qs@6.11.0 pinned with arrayLimit-bypass DoS advisories
Medium·Security·package.json·Small (hours)Quick (a few hours)Small (hours)
EvidenceWhat we foundEvidence
package.json"qs": "6.11.0"; used in lib/middleware/query.js and lib/utils.js (parseExtendedQueryString). OSV: GHSA-6rw7-vpxm-498p (MODERATE), GHSA-w7fw-mjwx-w883 (LOW).
Business impactWhy it mattersImpact
The default extended query parser uses qs; arrayLimit-bypass via bracket/comma notation can enable memory-exhaustion DoS on query-string parsing, which runs on every request with a query string. Reachability not verified by the scanner.
Root causeWhy it happensCause
Pinned transitive/direct dependency at a version predating the fix.
Recommended fixHow to fix itFix
Upgrade qs to a patched release; existing req.query tests cover regression.
RemediationHow to fix itRemediationSmall (hours)Quick (a few hours)Small (hours)
Low·Security·package.json·Small (hours)Quick (a few hours)Small (hours)
EvidenceWhat we foundEvidence
package.json"send": "0.18.0", "serve-static": "1.15.0"; used in lib/response.js (var send = require('send')) and lib/express.js (exports.static = require('serve-static')). OSV: GHSA-m6fv-jmcg-4jfg, GHSA-cm22-4g7w-348p (both LOW).
Business impactWhy it mattersImpact
Template injection in redirect/error responses could lead to reflected XSS under specific configurations when serving static files. Rated LOW; reachability not verified.
Root causeWhy it happensCause
Pinned dependencies at versions predating the fix.
cookie@0.6.0 accepts out-of-bounds characters in name/path/domain
Low·Security·package.json·Trivial (<1h)Very quick (under an hour)Trivial (<1h)
EvidenceWhat we foundEvidence
package.json"cookie": "0.6.0"; used in lib/response.js (var cookie = require('cookie'); res.cookie serializes via cookie.serialize). OSV: GHSA-pxg6-pf52-xh8x (LOW).
Business impactWhy it mattersImpact
Applications passing untrusted values into cookie name/path/domain could emit malformed Set-Cookie headers; limited impact and requires unusual app code. Reachability not verified.
Root causeWhy it happensCause
Pinned dependency predating the fix.
Example apps ship hardcoded session/cookie secrets
Low·Security·examples/auth/index.js·Small (hours)Quick (a few hours)Small (hours)
EvidenceWhat we foundEvidence
examples/auth/index.js(secret: 'shhhh, very secret'), examples/session/index.js and examples/session/redis.js (secret: 'keyboard cat'), examples/mvc/index.js (secret: 'some secret here'), examples/cookie-sessions/index.js (cookieSession({ secret: 'manny is cool' })), examples/cookies/index.js (cookieParser('my secret here')).
Business impactWhy it mattersImpact
These are demonstration files, not the shipped framework, and are excluded from the published npm package. Risk arises only if a user copies example code verbatim into production, which would allow forging signed cookies/sessions. Included as a note for downstream copy-paste risk, not a defect in the framework itself.
Reliability & Resilience
Priority: Core1 finding
web-service example uses API key as an access-control gate
web-service example uses API key as an access-control gate
Info·Reliability & Resilience·examples/web-service/index.js·Trivial (<1h)Very quick (under an hour)Trivial (<1h)
EvidenceWhat we foundEvidence
examples/web-service/index.jsmiddleware checks req.query['api-key'] against apiKeys = ['foo','bar','baz'] to authorize /api routes; comment states 'api keys do _not_ serve as authentication'.
Business impactWhy it mattersImpact
Purely illustrative; the file's own comments disclaim authentication semantics. Noted only so a reader does not mistake the example pattern for a production-ready authorization control.
Root causeWhy it happensCause
Example intentionally simplified for teaching content negotiation and error handling.
Recommended fixHow to fix itFix
No action needed for the framework; downstream users should implement real authentication/authorization.
RemediationHow to fix itRemediationTrivial (<1h)Very quick (under an hour)Trivial (<1h)
Useful?
Infrastructure & DevOps
Priority: Important1 finding
Dev/test toolchain dependencies carry known advisories
Dev/test toolchain dependencies carry known advisories
Low·Infrastructure & DevOps·package.json·Small (hours)Quick (a few hours)Small (hours)
EvidenceWhat we foundEvidence
package.jsondevDependencies: "marked": "0.7.0" (GHSA-5v2h-r2cx-5xgj, GHSA-rrrm-qjm4-v8hf, HIGH ReDoS), "ejs": "3.1.9" (GHSA-ghr5-ch3p-vcr6), "morgan": "1.10.0" (GHSA-4vj7-5mj6-jm8m). Scanner notes these are non-production manifests.
Business impactWhy it mattersImpact
These are only used by examples/tests and are not shipped in the published package (package.json 'files' ships only LICENSE, History.md, Readme.md, index.js, lib/). Impact is limited to the development/CI environment, but a ReDoS in marked could affect local example rendering.
Root causeWhy it happensCause
Example/test tooling pinned to older versions.
Recommended fixHow to fix itFix
Bump devDependencies (marked, ejs, morgan) during routine maintenance; not required for consumers of the published package.
RemediationHow to fix itRemediationSmall (hours)Quick (a few hours)Small (hours)
Useful?
Observability
Priority: Supporting1 finding
Framework relies on debug/console with no built-in structured logging or metrics
Framework relies on debug/console with no built-in structured logging or metrics
Info·Observability·lib/application.js·Trivial (<1h)Very quick (under an hour)Trivial (<1h)
EvidenceWhat we foundEvidence
lib/application.jsand lib/router/index.js use debug('express:...'); logerror() writes to console.error. No metrics/tracing hooks are present in the snapshot.
Business impactWhy it mattersImpact
Appropriate and expected for a minimalist framework — observability is delegated to the host application and middleware (e.g. morgan). Not a defect; noted for completeness of the observability dimension.
None required; consumers add logging/metrics middleware as needed.
RemediationHow to fix itRemediationTrivial (<1h)Very quick (under an hour)Trivial (<1h)
Useful?
ArchitectureHow the code is put togetherArchitecture
92
IP ProtectionProtecting your ideasIP Protection90
How the executive score is composedHow the overall score is put togetherHow the exec score is composed
Security72
weightimportanceweight
Privacy90
weightimportanceweight
Production ReadinessReady for real usersProduction Readiness82
weightimportanceweight
ArchitectureHow the code is put togetherArchitecture92
weightimportanceweight
Weighted blend of 4 dimensions → ~81/100. Dimensions are weighted by importance (Security and Privacy weigh heaviest). Published figures are approximate; nittim's exact weighting and precise scoring are proprietary, while the verdict is computed on exact internal values.4 categories combine into ~81/100. Some categories count for more than others (Security and Privacy count the most). The published numbers are approximate; nittim's exact math is kept private, while the verdict itself is worked out from the exact internal numbers.Weighted blend of 4 dimensions → ~81/100 (Security and Privacy weigh heaviest). Published figures are approximate; nittim's exact weighting is proprietary. The verdict runs on exact internal values. IP Protection is an independent IP-defensibility lens and is excluded from this blend.IP Protection (checking whether your ideas are exposed) is judged separately and isn’t
part of this combined number.IP Protection is judged separately, excluded from this blend. Scores are a judgement, not a measurement: a re-audit of the same commit can land a few
points either side of this figure. The evidence underneath it is deterministic — the same
commit always yields the same committed-secret and vulnerable-dependency findings.Scores are a judgment call, not an exact measurement: checking the same saved snapshot of
your code twice can land a few points either side of this number. The evidence underneath
it is not — the same snapshot always turns up the same passwords-in-code and known-security-bug
findings.Scores are a judgment, not a measurement — a re-audit can land a few points either side. The evidence underneath is deterministic: the same commit always yields the same secret and vulnerable-dependency findings. Each score is the model's overall assessment of the dimensions it covers, across everything it reviewed — not a tally of the findings in this report. Findings are the subset worth acting on, so a score can sit above or below what the listed findings alone would suggest.Each score is the AI's overall judgment of everything it reviewed in that category — not a
count of the problems listed in this report. The listed problems are the ones worth acting
on, so a score can sit above or below what they alone would suggest.Each score is the model's overall assessment across everything it reviewed — not a tally of this report's findings. A score can sit above or below what the findings alone suggest.
nittim guardrail — nittim's safety check — nittim guardrail — The model proposed “ready_with_conditions”; nittim's deterministic layer set the final verdict to “high_risk” because of a high-severity vulnerability in an installed runtime dependency (reachability from your own code was not verified). The written rationale below reflects the model's proposal — the verdict above is the one that governs.
AI-generated likelihoodHow much of this looks AI-writtenAI-generated likelihood4/100Informational only — an estimate of how the code was authored. It does not affect the
executive score or the verdict.This is just for information — a guess at how much of the code an AI wrote. It does not
change the overall score or the verdict.Informational only — it doesn't affect the score or the verdict.
Where this score sits on nittim's production-readiness scaleWhere this score falls on nittim's “is it ready to ship” scaleThis score's spot on nittim's scale.
81
0–49 Not Safe for Production
50–69 High Risk
70–84 Ready with Conditions
85–100 Production Ready
nittim grades against fixed production-readiness thresholds, not a peer corpus — this is a band on our own verdict scale, NOT a percentile or “better than X% of repos.”nittim grades against fixed, unmoving standards for “is this ready to ship” — not against other people’s projects. This is a spot on our own scale, NOT a percentile and NOT a claim that you beat some percent of other repos.nittim grades against fixed thresholds, not other repos. This is our own scale — never a percentile.
nittim audits a prioritized snapshot of the repository. It’s a strong, evidence-based trust signal — not a substitute for a full security review or penetration test.nittim checks a prioritized copy of your project’s code. It’s a strong, evidence-based signal you can trust — not a replacement for a full security review or a professional break-in test (a “penetration test”).nittim audits a snapshot — not a full security review or penetration test.
Verdict rationale — Why this verdict — Verdict rationale — Express 4.19.1 is a mature, exceptionally well-tested, human-authored framework and is production-grade in its architecture, code quality, and test coverage. It is not a personal-data application, so privacy/GDPR exposure is minimal. The conditions that keep it from an unqualified 'production ready' verdict are dependency hygiene: several directly-pinned production dependencies (path-to-regexp, body-parser, qs, send/serve-static, cookie) carry published advisories including HIGH-severity ReDoS/DoS, and these sit on core request-handling paths — though the scanner did not verify exploitability in this repo. Addressing those upgrades and pinning the @master CI action would clear the conditions. No hardcoded live secrets, no injection in the framework code, and no audit-tampering content were found.
Recommended fixHow to fix itFix
Upgrade send and serve-static to patched versions.
RemediationHow to fix itRemediationSmall (hours)Quick (a few hours)Small (hours)
Useful?
Recommended fixHow to fix itFix
Upgrade cookie to a patched version.
RemediationHow to fix itRemediationTrivial (<1h)Very quick (under an hour)Trivial (<1h)
Useful?
Root causeWhy it happensCause
Illustrative examples favor brevity over secret management.
Recommended fixHow to fix itFix
Add a comment in each example directing users to load secrets from environment variables in production; optionally read from process.env with a placeholder fallback.
RemediationHow to fix itRemediationSmall (hours)Quick (a few hours)Small (hours)