Architecture 68 C-
Security 53 F
Quality 65 D+
Documentation 68 C-
Maintainability 83 B+
Performance 82 B
Executive Summary
Your codebase scores D+ (67/100) — strong maintainability with security gaps

### Top Strengths

Maintainability B+ (83)
Performance B (82)
Documentation C- (69)

### Key Concerns

Security F (53)
Quality D+ (66)
Architecture C- (68)
Severity Distribution
high (6) medium (27) low (24) info (6)
63 findings · 6 agents · 128s · ~78h tech debt
What to Fix First

1. 01> high Error handler registered before 404 handler in MVC example examples/mvc/index.js:76

   Swap the order: place the 404 catch-all middleware before the error-handling middleware so that errors from the 404 handler are caught by the error handler.

2. 02> high Hardcoded session secret in auth example examples/auth/index.js:22

   Load the session secret from an environment variable (e.g., process.env.SESSION_SECRET) and fail startup if it is not set. Add a comment in the example explicitly warning against using hardcoded secrets in production.

3. 03> high Reflected XSS via session messages constructed from user input examples/auth/index.js:36

   Use a template engine's auto-escaping or explicitly escape values with a library like `escape-html` before embedding in HTML strings. Replace string concatenation with template rendering that auto-escapes.

4. 04> high XSS vulnerability via unsanitized session data rendered as HTML examples/auth/index.js:33

   Use a template engine's auto-escaping or explicitly escape HTML entities using `escape-html` or similar before embedding in HTML strings. Replace raw string concatenation with `escapeHtml()` calls.

5. 05> high Open redirect vulnerability via unvalidated Referrer header examples/auth/index.js:109

   Validate that the Referrer URL is a relative path or belongs to the same origin before using it as a redirect target. Use a whitelist approach or parse the URL and check the hostname.

D+ 0 / 100
Industry median: 62 · Above industry median for Javascript projects D grades signal significant technical debt requiring attention
Architecture68
Security53
Quality66
Documentation69
Maintainability83
Performance82
Architecture
0 C-
Security
0 F
Quality
0 D+
Documentation
0 C-
Maintainability
0 B+
Performance
0 B
0
Findings
0
Critical
0
Duration
$0
Cost
0
Agents
Analysis Coverage
6
Agents
83K
Tokens Used
2m 8s
Duration
$2.63
API Cost
0
Hallucinations Removed
Agents Used
Architecture Security Quality Documentation Dependency Performance
File Hotspot Heatmap

- 18
  examples/auth/index.js
- 10
  examples/mvc/index.js
- 4
  examples/route-map/index.js
- 4
  examples/cookies/index.js
- 4
  examples/markdown/index.js
- 3
  examples/resource/index.js
- 3
  examples/online/index.js
- 2
  examples/mvc/controllers/user/index.js
- 2
  examples/content-negotiation/index.js
- 1
  examples/multi-router/index.js
- 1
  examples/cookie-sessions/index.js
- 1
  examples/error-pages/index.js
- 1
  Readme.md
- 1
  examples/hello-world/index.js
- 1
  examples/route-separation/index.js

Filter
Strengths

- ✓ Multi-router example demonstrates good compositional architecture — The multi-router example correctly demonstrates Express Router composition by mounting versioned API routers at different path prefixes. This is a clean separation pattern that supports independent development and testing of API versions.
- ✓ Dependabot configuration present but effectiveness unverifiable — The repository includes .github/dependabot.yml and .github/workflows/scorecard.yml, indicating proactive dependency management and OpenSSF Scorecard integration. This is a strong positive signal for supply chain security posture. However, without the file contents, the configuration (update frequency, ecosystem coverage, version strategy) cannot be validated.

## Architecture (9)

high Error handler registered before 404 handler in MVC example ~0.5h
▶
examples/mvc/index.js:76-86
In the MVC example, the 500 error handler (`err, req, res, next`) is registered before the 404 catch-all handler. While Express distinguishes error-handling middleware by arity, this ordering is semantically misleading and means that if the 404 handler itself throws an error, there is no error handler after it to catch it. The conventional Express pattern is to place 404 handlers before error handlers.
Recommendation: Swap the order: place the 404 catch-all middleware before the error-handling middleware so that errors from the 404 handler are caught by the error handler.
medium Monkey-patching app.response prototype in MVC example ~1.0h
▶
examples/mvc/index.js:27-33
The MVC example directly mutates `app.response` to add a custom `message()` method. This modifies the shared response prototype, which can cause unexpected side effects if multiple Express apps share the same prototype chain. It also tightly couples application-level behavior to the framework's internal prototype, making it fragile across Express version upgrades.
Recommendation: Use a middleware function that attaches `res.message` per-request instead of mutating the prototype. For example: `app.use(function(req, res, next) { res.message = function(msg) { ... }; next(); });`
medium Monkey-patching app instance with ad-hoc resource method ~2.0h
▶
examples/resource/index.js:12-23
The resource example directly adds a `resource` method to the app instance at runtime (`app.resource = function(...)`). This is an ad-hoc extension pattern that bypasses any type safety, is not discoverable, and couples the routing abstraction directly to the app instance rather than using Express's built-in extension mechanisms (Router, middleware).
Recommendation: Encapsulate the resource routing logic in a separate Router or a factory function that returns a Router, e.g., `function resource(path, obj) { var router = express.Router(); ... return router; }` and mount it with `app.use(resource('/users', User))`.
medium Monkey-patching app instance with map method ~2.0h
▶
examples/route-map/index.js:13-26
The route-map example adds a `map` method directly to the app instance and uses recursive object traversal to register routes. This pattern is fragile, not type-safe, and tightly couples route definition structure to the app object. The recursive approach also makes debugging route registration difficult.
Recommendation: Extract the route mapping logic into a standalone utility function or use Express Router composition. For example: `function mapRoutes(app, routes, prefix) { ... }` as a separate module.
medium Implicit coupling via dynamic boot loader in MVC example ~4.0h
▶
examples/mvc/index.js:73-73
The MVC example uses `require('./lib/boot')(app, ...)` which dynamically discovers and loads controllers from the filesystem. This creates implicit coupling where the application's route structure depends on directory conventions rather than explicit registration. It makes the dependency graph opaque and harder to reason about, test, or refactor.
Recommendation: Consider explicit controller registration (e.g., `app.use('/users', userController)`) or at minimum document the convention clearly. For larger applications, use an explicit route manifest file.
medium Controllers directly access database module without abstraction layer ~4.0h
▶
examples/mvc/controllers/user/index.js:8-8
MVC controllers (user, pet, user-pet) directly import and access `../../db` with raw array indexing (`db.users[id]`, `db.pets[req.params.pet_id]`). There is no repository or service layer abstraction, meaning controllers contain data access logic. This violates separation of concerns and makes it difficult to swap data sources or add business logic.
Recommendation: Introduce a repository or service layer that encapsulates data access. Controllers should call service methods like `userService.findById(id)` rather than directly indexing into a database array.
medium No separation between routing and business logic in auth example ~3.0h
▶
examples/auth/index.js:44-72
The auth example places authentication logic (password hashing, user lookup, session management) directly alongside route definitions in a single file. The `authenticate` function, user database, and route handlers are all co-located with no separation of concerns. This monolithic pattern doesn't scale and makes testing individual components difficult.
Recommendation: Extract authentication logic into a separate auth service module, user data into a separate data module, and keep only route definitions in the main file. This enables unit testing of auth logic independently.
low Hardcoded session secret in multiple examples ~0.5h
▶
examples/auth/index.js:24-24
Multiple examples hardcode session secrets directly in source code (e.g., 'shhhh, very secret', 'some secret here', 'manny is cool'). While these are examples, they establish a pattern that developers may copy into production code. This is an architectural concern as it demonstrates no configuration management pattern.
Recommendation: Even in examples, demonstrate reading secrets from environment variables: `secret: process.env.SESSION_SECRET || 'dev-secret'`. This teaches proper configuration management patterns.
low Inconsistent module import patterns across examples ~0.5h
▶
examples/route-map/index.js:8-8
Examples inconsistently reference the parent Express module — some use `require('../..')`, others use `require('../../')`, and one uses `require('../../lib/express')`. This inconsistency suggests no enforced convention for module resolution and could confuse contributors.
Recommendation: Standardize all examples to use `require('../..')` which resolves through the package's main entry point (index.js). The route-map example importing `../../lib/express` directly bypasses the public API surface.
estimated effort: ~18h

## Security (14)

high Hardcoded session secret in auth example ~0.5h
▶
examples/auth/index.js:22-26
The session middleware is configured with a hardcoded secret string 'shhhh, very secret'. If this pattern is copied into production code, it enables session forgery and tampering. CWE-798: Use of Hard-coded Credentials. OWASP A07:2021 Identification and Authentication Failures.
Recommendation: Load the session secret from an environment variable (e.g., process.env.SESSION_SECRET) and fail startup if it is not set. Add a comment in the example explicitly warning against using hardcoded secrets in production.
high Reflected XSS via session messages constructed from user input ~2.0h
▶
examples/auth/index.js:36-37
In the auth example, session error and success messages are injected directly into HTML via string concatenation without escaping: `res.locals.message = '<p class="msg error">' + err + '</p>'`. While the current messages are static strings, the pattern is dangerous — if any user-controlled data flows into session.error or session.success, it would result in stored/reflected XSS. Additionally, the success message includes `user.name` which originates from the user database but follows an unsafe pattern. CWE-79: Improper Neutralization of Input During Web Page Generation. OWASP A03:2021 Injection.
Recommendation: Use a template engine's auto-escaping or explicitly escape values with a library like `escape-html` before embedding in HTML strings. Replace string concatenation with template rendering that auto-escapes.
medium Open redirect via Referrer header after login ~2.0h
▶
examples/auth/index.js:112-112
After successful authentication, the application redirects to `req.get('Referrer') || '/'`. The Referrer header is attacker-controllable and could point to an external malicious domain, enabling phishing attacks where a user is redirected to a lookalike site after logging in. CWE-601: URL Redirection to Untrusted Site. OWASP A01:2021 Broken Access Control.
Recommendation: Validate that the Referrer URL is a relative path or belongs to the same origin before redirecting. Use a whitelist approach or strip the host portion to ensure only local redirects.
medium Open redirect via Referrer header in cookies example ~1.0h
▶
examples/cookies/index.js:36-45
Both the GET /forget and POST / routes redirect to `req.get('Referrer') || '/'` without validating the Referrer header. An attacker can craft a request with a malicious Referrer to redirect users to an external site. CWE-601: URL Redirection to Untrusted Site. OWASP A01:2021 Broken Access Control.
Recommendation: Validate the Referrer header to ensure it is a relative URL or same-origin before using it in a redirect.
medium Hardcoded session secret in cookie-sessions example ~0.5h
▶
examples/cookie-sessions/index.js:13-13
The cookie-session middleware uses a hardcoded secret 'manny is cool'. Cookie-session stores all session data in the cookie itself, signed with this secret. A known secret allows an attacker to forge arbitrary session data. CWE-798: Use of Hard-coded Credentials. OWASP A07:2021 Identification and Authentication Failures.
Recommendation: Use an environment variable for the session secret. Add a prominent warning comment that this is for demonstration only.
medium Hardcoded cookie-parser secret in cookies example ~0.5h
▶
examples/cookies/index.js:20-20
The cookie-parser middleware is initialized with a hardcoded secret 'my secret here', which is used for signing cookies. CWE-798: Use of Hard-coded Credentials. OWASP A07:2021 Identification and Authentication Failures.
Recommendation: Load the cookie signing secret from an environment variable.
medium Hardcoded session secret in MVC example ~0.5h
▶
examples/mvc/index.js:42-46
The MVC example uses a hardcoded session secret 'some secret here'. CWE-798: Use of Hard-coded Credentials. OWASP A07:2021 Identification and Authentication Failures.
Recommendation: Use an environment variable for the session secret.
medium Missing cookie security flags (httpOnly, secure, sameSite) ~0.5h
▶
examples/cookies/index.js:42-42
In the cookies example, the 'remember' cookie is set with only a maxAge option: `res.cookie('remember', 1, { maxAge: minute })`. It lacks httpOnly, secure, and sameSite flags, making it accessible to JavaScript (XSS risk) and transmittable over unencrypted connections. CWE-614: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute. OWASP A05:2021 Security Misconfiguration.
Recommendation: Set cookies with `{ httpOnly: true, secure: true, sameSite: 'lax' }` flags, especially for any cookie that influences application behavior.
medium No CSRF protection on authentication form ~2.0h
▶
examples/auth/index.js:100-120
The POST /login route in the auth example processes form submissions without any CSRF token validation. An attacker could craft a cross-site form that submits login credentials (login CSRF) to associate a victim's session with the attacker's account. CWE-352: Cross-Site Request Forgery. OWASP A01:2021 Broken Access Control.
Recommendation: Add CSRF protection middleware (e.g., csurf or a custom CSRF token mechanism) to all state-changing routes.
medium Potential XSS in online example via User-Agent rendering ~1.0h
▶
examples/online/index.js:39-43
The online example tracks users by User-Agent header and renders the stored values directly into HTML via the `list()` helper function without escaping: `return '<li>' + id + '</li>'`. The User-Agent header is attacker-controlled and could contain malicious script tags. CWE-79: Improper Neutralization of Input During Web Page Generation. OWASP A03:2021 Injection.
Recommendation: Use escape-html or a similar library to escape the User-Agent values before embedding them in HTML output.
low Verbose error details exposed in error-pages example ~1.0h
▶
examples/error-pages/index.js:22-90
The error-pages example enables 'verbose errors' by default and only disables them when NODE_ENV is 'production'. The 500 error handler passes the full error object to the view: `res.render('500', { error: err })`. If the template renders error.stack or error.message, internal implementation details could leak to users. CWE-209: Generation of Error Message Containing Sensitive Information. OWASP A05:2021 Security Misconfiguration.
Recommendation: Default to non-verbose errors and only enable verbose mode explicitly in development. Ensure error templates do not render stack traces unless verbose errors are enabled.
low Potential XSS in content-negotiation example via user data ~0.5h
▶
examples/content-negotiation/index.js:12-14
The content-negotiation example renders user names directly into HTML without escaping: `return '<li>' + user.name + '</li>'`. While the data currently comes from a static file, this pattern is unsafe if the data source changes. CWE-79: Improper Neutralization of Input During Web Page Generation. OWASP A03:2021 Injection.
Recommendation: Use escape-html to sanitize user.name before embedding in HTML.
low Credentials logged to console in auth example ~0.5h
▶
examples/auth/index.js:60-60
The authenticate function logs the username and password in plaintext to the console: `console.log('authenticating %s:%s', name, pass)`. Even though this is guarded by `!module.parent`, it could leak credentials in logs if the example is run standalone. CWE-532: Insertion of Sensitive Information into Log File. OWASP A09:2021 Security Logging and Monitoring Failures.
Recommendation: Never log passwords. Log only the username or a sanitized identifier for debugging purposes.
low Mass assignment risk in MVC user/pet update controllers ~1.0h
▶
examples/mvc/controllers/user/index.js:30-33
The user and pet update controllers directly assign request body properties to database objects (e.g., `req.user.name = body.user.name`, `req.pet.name = body.pet.name`). While currently limited to specific fields, the pattern of directly accessing nested body properties without validation could lead to prototype pollution or unexpected property assignment if the pattern is extended. CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes. OWASP A08:2021 Software and Data Integrity Failures.
Recommendation: Validate and whitelist specific fields from req.body before assignment. Consider using a validation library.
estimated effort: ~14h

## Quality (11)

high XSS vulnerability via unsanitized session data rendered as HTML ~1.0h
▶
examples/auth/index.js:33-36
In the auth example, session error and success messages are directly interpolated into HTML strings without escaping. If user-controlled data (e.g., username) flows into these messages, it creates a stored XSS vulnerability. The success message includes `user.name` which originates from the hardcoded DB here, but the pattern is dangerous and could be copied into production code.
Recommendation: Use a template engine's auto-escaping or explicitly escape HTML entities using `escape-html` or similar before embedding in HTML strings. Replace raw string concatenation with `escapeHtml()` calls.
high Open redirect vulnerability via unvalidated Referrer header ~1.5h
▶
examples/auth/index.js:109-109
Multiple examples use `req.get('Referrer')` as a redirect target without validation. An attacker can craft a request with a malicious Referrer header pointing to an external domain, causing the application to redirect users to a phishing or malware site.
Recommendation: Validate that the Referrer URL is a relative path or belongs to the same origin before using it as a redirect target. Use a whitelist approach or parse the URL and check the hostname.
medium Hardcoded session secret in multiple examples ~0.5h
▶
examples/auth/index.js:25-25
Session secrets are hardcoded as string literals across multiple example files (auth, cookies, mvc). While these are examples, they set a dangerous precedent. Developers frequently copy example code directly into production applications.
Recommendation: Use environment variables for secrets even in examples (e.g., `process.env.SESSION_SECRET || 'dev-only-secret'`) and add a prominent comment warning against using hardcoded secrets in production.
medium Inconsistent error handling patterns across examples ~3.0h
▶
examples/auth/index.js:51-51
Error handling is inconsistent: some examples use `next(err)` properly (error-pages, params), some throw synchronously (error/index.js line 31), and some silently ignore errors (cookie-sessions has no error handler). The auth example's `hash()` callback on line 51 throws on error (`if (err) throw err`) which would crash the process since it's in an async callback.
Recommendation: Standardize error handling across examples: always use `next(err)` in route handlers, add error-handling middleware, and avoid `throw` in async callbacks. Add a comment explaining the chosen pattern.
medium Prototype pollution risk via direct bracket notation access on user DB ~0.5h
▶
examples/auth/index.js:63-63
In the auth example, `users[name]` uses user-supplied input directly as a property key on a plain object. An attacker could pass `__proto__`, `constructor`, or `toString` as the username to access inherited properties, potentially bypassing authentication logic or causing unexpected behavior.
Recommendation: Use `Object.hasOwn(users, name)` or `Object.create(null)` for the users object, or use a `Map` instead of a plain object for the user database.
medium Regex-based template engine in markdown example is fragile and unsafe ~1.0h
▶
examples/markdown/index.js:19-23
The markdown example's custom engine uses a regex `/\{([^}]+)\}/g` to replace template variables. This is a naive templating approach that could lead to ReDoS with crafted input, doesn't handle nested braces, and the `escapeHtml` only applies to known options — unknown variable names result in empty strings silently.
Recommendation: Use an established templating library for variable interpolation, or at minimum document the limitations. Consider adding input length validation to prevent ReDoS.
medium MVC example error handler placed before 404 handler — incorrect ordering ~0.5h
▶
examples/mvc/index.js:76-85
In the MVC example, the error-handling middleware (4-arity function for 500 errors) is placed before the 404 catch-all middleware. While Express processes error handlers separately from regular middleware, this ordering is confusing and could lead to the 404 handler never being reached if the error handler doesn't call `next()`.
Recommendation: Place the 404 catch-all middleware before the error-handling middleware to ensure proper flow: unmatched routes trigger 404, and errors from any handler (including 404 rendering) are caught by the error handler.
low Inconsistent use of strict mode semicolons and coding style ~2.0h
▶
examples/auth/index.js:65-72
Coding style is inconsistent across examples: some statements end with semicolons and some don't (e.g., auth/index.js line 65 `if (!user) return fn(null, null)` vs line 71 `if (hash === user.hash) return fn(null, user)`). Some files use `var` exclusively while the codebase could benefit from `const`/`let`. Indentation and spacing around function arguments also varies.
Recommendation: Adopt a consistent style guide (e.g., StandardJS or Airbnb) and enforce it with ESLint. Convert `var` to `const`/`let` where appropriate.
low Array index used as database ID without bounds checking in resource example ~0.5h
▶
examples/resource/index.js:52-56
The resource example uses `delete users[id]` with a parsed integer from URL params. Using `delete` on an array creates a sparse array (sets element to `undefined` rather than removing it), and there's no bounds checking for negative indices. The `destroyed` check `id in users` would return true for any index within the original array length.
Recommendation: Use `Array.prototype.splice()` for actual removal, or use an object/Map for the data store. Add bounds checking: `if (id < 0 || id >= users.length)`.
low Route-map example uses recursive function without depth limit ~0.5h
▶
examples/route-map/index.js:15-27
The `app.map()` function in route-map/index.js recursively traverses the route configuration object without any depth limit. A deeply nested or circular route configuration could cause a stack overflow.
Recommendation: Add a maximum depth parameter or use iterative traversal. Add a check for circular references using a `Set` of visited objects.
low Examples exclusively use legacy 'var' declarations and callback patterns ~4.0h
▶
examples/auth/index.js:7-10
All example files use `var` instead of `const`/`let`, and rely entirely on callback-based patterns rather than async/await or Promises. While functional, this makes the examples appear outdated and doesn't demonstrate modern JavaScript best practices to developers learning from them.
Recommendation: Modernize examples to use `const`/`let`, arrow functions where appropriate, and async/await patterns. This improves readability and teaches current best practices.
estimated effort: ~15h

## Documentation (11)

high lib/application.js, lib/request.js, lib/response.js content not provided ~8.0h
▶
lib/application.js
The core library files (application.js, request.js, response.js) are listed in the analysis plan but their content was not provided. These are the most critical files for API documentation assessment — they define the public API surface of Express (app methods, req properties, res methods). Without their content, inline JSDoc/docstring coverage for the core API cannot be evaluated.
Recommendation: Include lib/application.js, lib/request.js, and lib/response.js in the analysis. These files should have comprehensive JSDoc comments for every public method including @param, @returns, @example, and @since tags.
medium Auth example uses hardcoded secret and lacks security disclaimers ~0.5h
▶
examples/auth/index.js:22-26
The auth example uses a hardcoded session secret ('shhhh, very secret') and stores passwords using pbkdf2 without documenting that this is for demonstration only. New developers may copy this pattern into production code. There is no comment warning against using hardcoded secrets or this simplified auth approach in production.
Recommendation: Add a prominent comment block at the top of the file: '// WARNING: This is a simplified example for learning purposes. // In production, use environment variables for secrets, a proper user store, // and consider using passport.js or similar authentication middleware.'
medium MVC example lacks architectural documentation ~2.0h
▶
examples/mvc/index.js:1-89
The MVC example is the most complex example in the collection, featuring a boot loader, multiple controllers with conventions (exports.before, exports.engine, exports.prefix), session-based flash messages, and a custom res.message() method. However, there is no README or top-level documentation explaining the MVC conventions, the boot process, or how controllers are auto-loaded. Users must reverse-engineer the pattern from code.
Recommendation: Add an examples/mvc/README.md explaining: (1) the controller convention (exports.before, exports.engine, exports.name, exports.prefix), (2) how the boot loader discovers and mounts controllers, (3) the custom res.message() flash message pattern, and (4) directory structure overview.
medium Custom res.message() method undocumented API extension pattern ~0.5h
▶
examples/mvc/index.js:28-35
The MVC example extends app.response with a custom message() method by directly modifying the prototype. This is a powerful but non-obvious Express pattern that is not documented with JSDoc or explained beyond a brief inline comment. Users seeing this pattern need to understand Express's prototype chain.
Recommendation: Add a JSDoc-style comment block explaining: what app.response is, why modifying it adds methods to all response objects, the pattern's implications, and a reference to Express documentation on extending request/response.
low Hello World example lacks explanatory comments ~0.5h
▶
examples/hello-world/index.js:1-14
The hello-world example is the most common entry point for new users but contains zero comments explaining what each line does. For a canonical 'getting started' example, this is a missed opportunity to teach Express fundamentals.
Recommendation: Add brief inline comments explaining: requiring express, creating an app instance, defining a route handler, calling res.send(), and starting the server with app.listen(). This is the first example most users see.
low Route separation example referenced but not provided ~1.0h
▶
examples/route-separation/index.js
The file listing includes examples/route-separation/index.js but its content was not provided. This example is commonly referenced for teaching Express application structure patterns and its documentation quality cannot be assessed.
Recommendation: Ensure the route-separation example includes comments explaining the pattern of separating route handlers into individual modules and when to use this pattern vs. the MVC pattern.
low Examples use deprecated module.parent pattern without explanation ~1.0h
▶
examples/auth/index.js:113-116
Every example uses `if (!module.parent)` to conditionally start the server, but this pattern is deprecated in Node.js (module.parent was deprecated in v14.6.0 in favor of require.main === module). There is no comment explaining this pattern or its purpose for new developers.
Recommendation: Add a comment explaining the pattern: '// Only start the server if this file is run directly (not required as a module). // Note: module.parent is deprecated; consider using require.main === module.' Alternatively, update the pattern and document the change.
low Error handling examples lack cross-referencing documentation ~0.5h
▶
examples/error/index.js:1-5
There are two separate error handling examples (examples/error/ and examples/error-pages/) that demonstrate different aspects of error handling, but neither references the other. The error/ example shows basic error middleware, while error-pages/ shows content negotiation in error responses. A developer finding one may miss the other.
Recommendation: Add a comment at the top of each error example referencing the other: '// See also: examples/error-pages/ for content-negotiated error responses' and '// See also: examples/error/ for basic error handling middleware'.
low Resource example documents custom app.resource() but lacks JSDoc ~0.5h
▶
examples/resource/index.js:13-25
The resource example defines a custom app.resource() method that implements a RESTful resource pattern, but uses no JSDoc to document the method signature, the expected shape of the resource object (index, show, destroy, range methods), or return value.
Recommendation: Add JSDoc to app.resource: '/** @param {string} path - The base URL path for the resource. @param {Object} obj - Resource controller with index, show, destroy, and range methods. */'
low Online example has external dependency setup instructions but no error handling docs ~0.5h
▶
examples/online/index.js:1-8
The online/redis example includes setup instructions for Redis at the top (which is good), but doesn't document what happens when Redis is unavailable or how to handle connection errors — a common pain point for developers using this pattern.
Recommendation: Add comments about Redis error handling: '// In production, handle Redis connection errors: db.on("error", ...) // and consider a fallback strategy when Redis is unavailable.'
info README.md and History.md content not available for analysis ~0.5h
▶
Readme.md
The file listing includes Readme.md, History.md, and examples/README.md but their actual content was not provided in the analyzed code. This limits the ability to assess the primary documentation artifacts. Analysis is restricted to example files and lib module references only.
Recommendation: Ensure Readme.md includes installation instructions, quick start guide, API overview, configuration options, contributing guidelines, and links to full API docs. History.md should contain a structured changelog with migration notes for breaking changes.
estimated effort: ~16h

## Maintainability (7)

medium No package.json or lock file content provided for dependency analysis ~0.5h
▶
package.json
The file list references package.json, .npmrc, and .github/dependabot.yml but their contents were not included in the provided code. Without the actual package.json content, it is impossible to assess version pinning, dependency counts, or known CVEs in production dependencies. The analysis is limited to what can be inferred from example code imports.
Recommendation: Ensure package.json, package-lock.json, and .npmrc contents are included in future analyses for comprehensive dependency auditing.
medium Use of 'marked' library for Markdown rendering in examples ~1.0h
▶
examples/markdown/index.js:12-21
The markdown example uses the 'marked' package to parse user-influenced Markdown content. Historically, marked has had multiple XSS vulnerabilities (e.g., CVE-2022-21680, CVE-2022-21681 in versions < 4.0.10). Without knowing the pinned version, there is a risk of using a vulnerable version. The example does use escapeHtml for template variables but the parsed Markdown HTML itself is rendered directly.
Recommendation: Ensure marked is updated to >= 4.0.10 (or latest v12+). Consider enabling marked's sanitize option or using DOMPurify for output sanitization in examples that render user-influenced Markdown.
low Example code uses numerous unpinned optional/dev dependencies ~2.0h
▶
examples/auth/index.js:8-10
The examples directory imports a wide range of third-party packages (express-session, cookie-session, cookie-parser, morgan, method-override, pbkdf2-password, marked, escape-html, http-errors, ejs, hbs, redis, online) that are likely listed as devDependencies. While these are example-only dependencies, their presence increases the attack surface for supply chain attacks during development and CI.
Recommendation: Audit all example dependencies in package.json devDependencies. Consider isolating examples into a separate workspace or documenting that they require separate installation. Ensure Dependabot (referenced in .github/dependabot.yml) covers all dependency groups.
low Redis client usage without version context in online example ~1.0h
▶
examples/online/index.js:17-18
The online example imports 'redis' and 'online' packages. The 'online' npm package has very low download counts and may be unmaintained. Using unmaintained packages in examples that users may copy increases supply chain risk.
Recommendation: Verify the 'online' package is still maintained. Consider adding a deprecation notice or replacing with a more actively maintained alternative. At minimum, document that this example requires additional package installation.
info Positive: .npmrc configuration file present ~0.5h
▶
.npmrc
The presence of .npmrc indicates intentional npm configuration, which may include settings like package-lock=true, engine-strict=true, or registry pinning. This is a good practice for reproducible builds and supply chain security.
Recommendation: Ensure .npmrc includes 'package-lock=true' and consider adding 'engine-strict=true' to enforce Node.js version compatibility.
info Positive: CI workflow present for automated testing ~0.5h
▶
.github/workflows/ci.yml
The repository includes .github/workflows/ci.yml, indicating automated CI testing is configured. Combined with dependabot.yml and scorecard.yml, this represents a mature CI/CD pipeline for dependency management.
Recommendation: Ensure CI workflow includes 'npm audit' or equivalent vulnerability scanning step, and that it runs on pull requests from Dependabot.
info Examples use require() pattern consistent with CommonJS - no ESM migration concerns ~1.0h
▶
examples/downloads/index.js:9-9
All example files use CommonJS require() syntax. Some use 'node:' protocol for built-in modules (e.g., 'node:path', 'node:fs') which is a modern best practice, while others use bare specifiers. This inconsistency is minor but indicates partial modernization.
Recommendation: Standardize on 'node:' protocol prefix for all built-in module imports across examples for consistency and to avoid potential conflicts with npm packages of the same name.
estimated effort: ~7h

## Performance (9)

medium Synchronous fs.readFile in markdown view engine on every request ~2.0h
▶
examples/markdown/index.js:17-24
The custom markdown engine reads the template file from disk on every render call using fs.readFile. While fs.readFile is async (non-blocking I/O), there is no caching of the parsed markdown content. In production with repeated requests to the same views, this results in redundant disk I/O and markdown parsing on every request. Express's built-in view caching (enabled in production via 'view cache' setting) caches the engine lookup but not the file content itself for custom engines.
Recommendation: Implement an in-memory cache for parsed markdown templates keyed by file path and mtime. Alternatively, ensure 'view cache' is enabled and consider caching the rendered HTML output for templates that don't change frequently.
medium Session middleware on all routes including static files in MVC example ~2.0h
▶
examples/mvc/index.js:40-51
In the MVC example, express.static() is registered before session middleware, which is correct. However, the session middleware, body parser, and method-override middleware all run on every non-static request including simple GET requests that don't need body parsing or method override. This adds unnecessary overhead per request for routes that don't use these features.
Recommendation: Apply body parsing and method-override middleware only to routes that need them (POST/PUT/PATCH handlers) rather than globally. Use route-specific middleware to reduce per-request overhead.
medium Missing input sanitization on user-controlled redirect via Referrer header ~1.0h
▶
examples/cookies/index.js:38-38
Multiple examples use req.get('Referrer') directly in res.redirect() without validation. While not strictly a performance issue, open redirect vulnerabilities can be exploited for phishing attacks that generate high volumes of redirected traffic, and the lack of validation means the server processes these redirects without any short-circuiting.
Recommendation: Validate that the Referrer header points to the same origin before using it in redirects. Use a whitelist of allowed redirect targets.
low Synchronous blocking hash computation on startup ~1.0h
▶
examples/auth/index.js:62-72
The pbkdf2 hash is computed asynchronously at module load time, which is fine, but the authenticate() function performs a pbkdf2 hash on every login attempt. While pbkdf2-password uses async callbacks, the underlying computation is CPU-intensive. In a single-threaded Node.js process under high concurrent login attempts, this could block the event loop. However, since this is an example app and pbkdf2-password delegates to crypto which may use libuv thread pool, the real-world impact is moderate.
Recommendation: For production use, ensure the pbkdf2 computation runs in the libuv thread pool (which Node's crypto module does by default). Consider rate-limiting login attempts to prevent CPU exhaustion from repeated hash computations.
low Regex replacement on every markdown render without compilation caching ~1.5h
▶
examples/markdown/index.js:20-22
The markdown engine applies a regex replacement /\{([^}]+)\}/g on every render call after parsing the markdown. While the regex itself is simple, combined with the lack of template caching, this adds unnecessary CPU work per request. The marked.parse() call is also synchronous and CPU-bound, which could block the event loop for large markdown files.
Recommendation: Cache the result of marked.parse(str) and only apply the variable substitution per-request. This separates the expensive parse step from the cheap substitution step.
low Dynamic require() in boot loader called at startup ~0.5h
▶
examples/mvc/index.js:75-75
The MVC example uses require('./lib/boot')(app, ...) which dynamically loads controllers. While this only runs at startup (not per-request), the boot module likely uses synchronous fs operations (readdirSync, require) to discover and load controllers. This is acceptable for startup but would be problematic if called during request handling.
Recommendation: This is acceptable for startup. Ensure the boot loader is not called during request handling. For large applications with many controllers, consider lazy-loading controllers on first access.
low Session messages flushed after next() in middleware ~1.0h
▶
examples/mvc/index.js:55-72
The session messages middleware calls next() and then synchronously clears req.session.messages. Since next() is synchronous in Express's middleware chain, the messages array is cleared after downstream middleware has had a chance to read it. However, if any downstream middleware is async and reads messages after the current tick, the messages would already be cleared. More importantly, this pattern writes to the session on every request even when there are no messages, potentially triggering unnecessary session saves.
Recommendation: Only clear and save session messages if msgs.length > 0 to avoid unnecessary session writes. Move the clearing logic into a response finish event handler: res.on('finish', function() { req.session.messages = []; }).
low String concatenation for HTML generation instead of template rendering ~0.5h
▶
examples/content-negotiation/index.js:10-16
Multiple examples build HTML responses via string concatenation with Array.map().join(). While this is fine for examples, in production this pattern creates many intermediate string allocations. For the content-negotiation example, the HTML response is rebuilt on every request even though the users data is static.
Recommendation: For static data, pre-compute the HTML string once at startup and serve the cached result. For dynamic data, use template engines which are optimized for this pattern.
low Recursive route mapping without depth limit ~0.5h
▶
examples/route-map/index.js:14-27
The app.map() function in the route-map example recursively traverses nested route objects. While the recursion depth is bounded by the route configuration (which is static and small), there is no explicit depth limit. A deeply nested or circular route configuration could cause a stack overflow.
Recommendation: Add a maximum depth parameter to prevent stack overflow with malformed configurations. For the current static usage this is not a practical concern.
estimated effort: ~10h
Technical Debt Summary
0 estimated hours to remediate
cost to remediate: ~$13,738 at $150/hr avg dev rate
By Dimension
Architecture 17.5h
Documentation 15.5h
Quality 15.0h
Security 13.5h
Performance 10.0h
Maintainability 7.0h
By Severity
high 13.5h
medium 39.0h
low 23.0h
info 3.0h
Debt Distribution
high
medi
low
Due Diligence Compliance Mapping
OWASP Top 10 (2021) Coverage
6 of 10 categories checked
A01:2021 Broken Access Control
A02:2021 Cryptographic Failures
A03:2021 Injection
A04:2021 Insecure Design
A05:2021 Security Misconfiguration
A06:2021 Vulnerable and Outdated Components
A07:2021 Identification and Auth Failures
A08:2021 Software and Data Integrity Failures
A09:2021 Security Logging and Monitoring Failures
A10:2021 Server-Side Request Forgery
OWASP Top 10 (2025) Coverage
6 of 10 categories checked
A01:2025 Broken Access Control
A02:2025 Security Misconfiguration
A03:2025 Software Supply Chain Failures
A04:2025 Cryptographic Failures
A05:2025 Injection
A06:2025 Insecure Design
A07:2025 Authentication Failures
A08:2025 Software or Data Integrity Failures
A09:2025 Logging and Alerting Failures
A10:2025 Mishandling of Exceptional Conditions
CWE References Found
CWE-79 CWE-209 CWE-352 CWE-532 CWE-601 CWE-614 CWE-798 CWE-915

AI-assisted screening based on finding text. Not a substitute for professional penetration testing.

Investment Readiness Score
⚠ Automated heuristic — not a substitute for formal due diligence or financial advisory. Score is derived from code-quality signals, not business fundamentals.
0 / 100
needs work

Moderate technical risk. Several areas need attention before fundraising.

Component Breakdown
Overall Score
67 25%
Security Posture
53 20%
Issue Concentration
48 10%
Dependency Health
0 10%
Code Complexity
50 10%
License Compliance
95 10%
SOC 2 Readiness
39 10%
Critical Findings
100 5%

AI-estimated composite score. Consult qualified advisors for investment decisions.

SOC 2 Readiness
⚠ Automated heuristic — not a substitute for formal SOC 2 assessment. Findings are mapped by keyword analysis, not control evidence evaluation.
39.4% control coverage
13 of 33 controls addressed
20 gaps · 41 findings mapped
CC1: Control Environment 0/5
✗ CC1.1 Integrity and ethical values
✗ CC1.2 Board independence and oversight
✗ CC1.3 Management structure and reporting
✗ CC1.4 Commitment to competence
✗ CC1.5 Accountability for internal controls
CC2: Communication and Information 1/3
✓ CC2.1 Information for internal control 5
✗ CC2.2 Internal communication of objectives
✗ CC2.3 External communication
CC3: Risk Assessment 3/4
✓ CC3.1 Specification of suitable objectives 3
✓ CC3.2 Risk identification and analysis 3
✓ CC3.3 Consideration of fraud risk 7
✗ CC3.4 Identification of significant changes
CC4: Monitoring Activities 1/2
✓ CC4.1 Ongoing and separate evaluations 1
✗ CC4.2 Communication of deficiencies
CC5: Control Activities 2/3
✓ CC5.1 Selection of control activities 1
✗ CC5.2 Technology general controls
✓ CC5.3 Deployment through policies 4
CC6: Logical and Physical Access Controls 4/8
✓ CC6.1 Logical access security software 8
✓ CC6.2 Credential and secret management 8
✗ CC6.3 Role-based access authorization
✓ CC6.4 Access removal and session management 8
✗ CC6.5 Physical access restrictions
✗ CC6.6 System boundary protection
✓ CC6.7 Data transmission security 1
✗ CC6.8 Prevention of unauthorized software
CC7: System Operations 1/5
✓ CC7.1 Infrastructure and availability monitoring 1
✗ CC7.2 Security event detection
✗ CC7.3 Security event evaluation
✗ CC7.4 Incident response procedures
✗ CC7.5 Recovery and resilience
CC8: Change Management 0/1
✗ CC8.1 Change control processes
CC9: Risk Mitigation 1/2
✗ CC9.1 Risk mitigation for business disruptions
✓ CC9.2 Third-party and vendor risk management 7

Keyword-based mapping to AICPA Common Criteria (CC1–CC9). Not a formal SOC 2 audit.

PCI DSS 4.0 — Requirement 6
⚠ Automated heuristic — not a substitute for formal PCI DSS assessment. Findings are mapped by keyword analysis, not control evidence evaluation.
63.6% control coverage
7 of 11 controls addressed
4 gaps · 29 findings mapped
R6.2: Secure Software Development 1/4
✗ 6.2.1 Secure development processes defined
✗ 6.2.2 Software development personnel trained
✗ 6.2.3 Code reviewed before release
✓ 6.2.4 Protection against common vulnerabilities 15
R6.3: Security Vulnerabilities Identified and Addressed 3/3
✓ 6.3.1 Known vulnerabilities identified 2
✓ 6.3.2 Software inventory maintained 7
✓ 6.3.3 Patches applied timely 2
R6.4: Public-Facing Web Applications Protected 1/2
✗ 6.4.1 Web application firewall or equivalent
✓ 6.4.2 Automated attack detection 1
R6.5: Changes Managed Securely 2/2
✓ 6.5.1 Change control procedures 3
✓ 6.5.2 Development/test/production separation 3

Keyword-based mapping to PCI DSS 4.0 Requirement 6 (Secure Systems & Software). Not a formal PCI assessment.

NIST CSF 2.0
⚠ Automated heuristic — not a substitute for formal NIST CSF assessment. Findings are mapped by keyword analysis, not control evidence evaluation.
50.0% function coverage
6 of 12 categories addressed
6 gaps · 25 findings mapped
GV: Govern 0/2
✗ GV.OC-01 Organizational context understood
✗ GV.RM-01 Risk management objectives established
ID: Identify 2/2
✓ ID.AM-01 Asset inventory maintained 8
✓ ID.RA-01 Risk assessment performed 2
PR: Protect 3/3
✓ PR.AA-01 Access control enforced 9
✓ PR.DS-01 Data security ensured 8
✓ PR.PS-01 Platform security maintained 4
DE: Detect 1/2
✓ DE.CM-01 Continuous monitoring implemented 2
✗ DE.AE-01 Adverse event analysis performed
RS: Respond 0/2
✗ RS.AN-01 Incident analysis conducted
✗ RS.MI-01 Incident mitigation applied
RC: Recover 0/1
✗ RC.RP-01 Recovery execution planned and tested

Keyword-based mapping to NIST Cybersecurity Framework 2.0 (6 Functions). Not a formal NIST assessment.

Issue Concentration
0
distribution score
concerning
0.516
Gini Coefficient
22
Unique Files
63
Total Issues
Top 10 Hotspot Files

- 1 18
  examples/auth/index.js
- 2 10
  examples/mvc/index.js
- 3 4
  examples/route-map/index.js
- 4 4
  examples/cookies/index.js
- 5 4
  examples/markdown/index.js
- 6 3
  examples/resource/index.js
- 7 3
  examples/online/index.js
- 8 2
  examples/mvc/controllers/user/index.js
- 9 2
  examples/content-negotiation/index.js
- 10 1
  examples/multi-router/index.js

Measures finding distribution across files. For contributor-based bus factor analysis, use git blame tools.

Dependency Risk
0 risk
critical risk
8 dependency findings analyzed · +10 severity penalty
Risk Signals Detected

- cve +20 pts
- lock file +5 pts
- pinned +5 pts
- unpinned +10 pts
- vulnerable +25 pts
- cve +20 pts
- pinned +5 pts
- unmaintained +20 pts

License Compliance
2 unique licenses detected · 18 total mentions
MIT×11 ISC×7
Code Complexity
0
Max Complexity
0.0
Avg Complexity
0
High Complexity Files
unknown risk
No high complexity files detected
ROI Analysis
This analysis cost
$2.63
Manual equivalent ($175/hr × 4h)
$700
Spectra saved you
$697 (100%)
Cost per finding
$0.04

Based on $175/hr senior engineer rate and ~4 hours for equivalent manual review. Actual costs vary.

j k navigate / search Esc clear Enter expand