API surface 68 endpoints · express

Headline
50/ 100 MIXED
3 HIGH · 4 MED · 61 LOW · status FAIL
ApiGate inventories every HTTP endpoint, classifies auth posture (GUARDED / OPEN / UNKNOWN), assigns a risk tier per endpoint, and diffs the surface against any declared OpenAPI spec. 100% static — no network, no credentials, deterministic.
Endpoints
68
HIGH risk
3
MED risk
4
Guarded
0
Open
68
Unknown
0
Shadow
0
Stale
0

Gate reasons

CI exit-1 fired on the following deterministic, enum-locked reasons:

  • open-write

Endpoint inventory 68 of 68 · sorted risk DESC, then method/path

68 / 68 visible
MethodPathFrameworkRiskPostureMarker / ReasonLocation
DELETE/user/:idexpressHIGHOPENexamples/route-middleware/index.js:82
POST/expressHIGHOPENexamples/cookies/index.js:39
PUT/user/:id/editexpressHIGHOPENexamples/route-separation/index.js:45
GET/api/usersexpressMEDOPENexamples/web-service/index.js:75
GET/usersexpressMEDOPENexamples/content-negotiation/index.js:40
GET/usersexpressMEDOPENexamples/route-separation/index.js:40
GET/users/:from-:toexpressMEDOPENexamples/params/index.js:63
ALL/user/:id{/:op}expressLOWOPENexamples/route-separation/index.js:41
GET/expressLOWOPEN PUBLICexamples/auth/index.js:84
GET/expressLOWOPEN PUBLICexamples/content-negotiation/index.js:9
GET/expressLOWOPEN PUBLICexamples/cookie-sessions/index.js:16
GET/expressLOWOPEN PUBLICexamples/cookies/index.js:24
GET/expressLOWOPEN PUBLICexamples/downloads/index.js:15
GET/expressLOWOPEN PUBLICexamples/ejs/index.js:45
GET/expressLOWOPEN PUBLICexamples/error-pages/index.js:30
GET/expressLOWOPEN PUBLICexamples/error/index.js:29
GET/expressLOWOPEN PUBLICexamples/hello-world/index.js:7
GET/expressLOWOPEN PUBLICexamples/markdown/index.js:32
GET/expressLOWOPEN PUBLICexamples/multi-router/index.js:10
GET/expressLOWOPEN PUBLICexamples/online/index.js:50
GET/expressLOWOPEN PUBLICexamples/params/index.js:47
GET/expressLOWOPEN PUBLICexamples/resource/index.js:78
GET/expressLOWOPEN PUBLICexamples/route-middleware/index.js:70
GET/expressLOWOPEN PUBLICexamples/route-separation/index.js:36
GET/expressLOWOPEN PUBLICexamples/session/index.js:22
GET/expressLOWOPEN PUBLICexamples/session/redis.js:27
GET/expressLOWOPEN PUBLICexamples/view-constructor/index.js:32
GET/expressLOWOPEN PUBLICexamples/view-locals/index.js:26
GET/403expressLOWOPENexamples/error-pages/index.js:41
GET/404expressLOWOPENexamples/error-pages/index.js:34
GET/500expressLOWOPENexamples/error-pages/index.js:48
GET/Readme.mdexpressLOWOPENexamples/view-constructor/index.js:39
GET/api/reposexpressLOWOPENexamples/web-service/index.js:80
GET/api/user/:name/reposexpressLOWOPENexamples/web-service/index.js:85
GET/client.jsexpressLOWOPENexamples/search/index.js:69
GET/failexpressLOWOPENexamples/markdown/index.js:36
GET/files/*fileexpressLOWOPENexamples/downloads/index.js:26
GET/forgetexpressLOWOPENexamples/cookies/index.js:34
GET/loginexpressLOWOPENexamples/auth/index.js:100
GET/logoutexpressLOWOPENexamples/auth/index.js:92
GET/middlewareexpressLOWOPENexamples/view-locals/index.js:64
GET/middleware-localsexpressLOWOPENexamples/view-locals/index.js:102
GET/nextexpressLOWOPENexamples/error/index.js:34
GET/postsexpressLOWOPENexamples/route-separation/index.js:49
GET/restrictedexpressLOWOPENexamples/auth/index.js:88
GET/search/{:query}expressLOWOPENexamples/search/index.js:52
GET/user/:idexpressLOWOPENexamples/route-middleware/index.js:74
GET/user/:idexpressLOWOPENexamples/route-separation/index.js:42
GET/user/:id/editexpressLOWOPENexamples/route-middleware/index.js:78
GET/user/:id/editexpressLOWOPENexamples/route-separation/index.js:44
GET/user/:id/viewexpressLOWOPENexamples/route-separation/index.js:43
GET/user/:userexpressLOWOPENexamples/params/index.js:55
GETenvexpressLOWOPENexamples/error/index.js:10
GETetag fnexpressLOWOPENlib/response.js:161
GETjson escapeexpressLOWOPENlib/response.js:235
GETjson escapeexpressLOWOPENlib/response.js:263
GETjson replacerexpressLOWOPENlib/response.js:236
GETjson replacerexpressLOWOPENlib/response.js:264
GETjson spacesexpressLOWOPENlib/response.js:237
GETjson spacesexpressLOWOPENlib/response.js:265
GETjsonp callback nameexpressLOWOPENlib/response.js:267
GETquery parser fnexpressLOWOPENlib/request.js:231
GETsubdomain offsetexpressLOWOPENlib/request.js:388
GETtrust proxy fnexpressLOWOPENlib/request.js:301
GETtrust proxy fnexpressLOWOPENlib/request.js:341
GETtrust proxy fnexpressLOWOPENlib/request.js:358
GETtrust proxy fnexpressLOWOPENlib/request.js:419
POST/loginexpressLOWOPEN PUBLICexamples/auth/index.js:104

Rubrics five 0–100 scores · headline = arithmetic mean of non-null rubrics

Inventory Resolved100
Auth Coverage0
Open Endpoint Risk0
Spec Driftn/a
no spec
Determinism100

Trust / audit material

Parser capabilities what each parser sees and what it intentionally does not

The honesty contract, machine-readable. This matrix is frozen at the published apigate version (0.3.0) and the same data is in the JSON report under parserCapabilities.

ParserCapabilityBehavior
expresscrossFileMountPrefixno
expressdynamicMountPrefixUNRESOLVED
expresshttpMethodsget/post/put/delete/patch/head/options/all
expresslanguagejs, mjs, cjs (AST) · ts, tsx (regex fallback)
expressmiddlewareIdentifierExtractionyes
expresssameFileMountPrefixyes
expresstypeScriptAstno
fastifyhttpMethodsget/post/put/delete/patch/head/options + fastify.route()
fastifylanguagejs, mjs, cjs (AST only)
fastifypreHandlerIdentifierExtractionyes
fastifyregisterPrefixPropagationno
fastifyrouteOptionsParsedyes
fastifytypeScriptAstno
nestclassLevelGuardsyes
nestcontrollerArrayArgfirst path only
nestcontrollerObjectArgpath field only (version segment ignored)
nestcontrollerStringArgyes
nestdynamicDecoratorArgUNRESOLVED
nestglobalGuardDetectionNOT DETECTED — useGlobalGuards(...) / { provide: APP_GUARD } providers in main.ts / app.module.ts are invisible to per-controller parsing. Endpoints protected ONLY by a global guard will be reported OPEN. Workaround: extend auth.nest with your custom marker, or use config.severityOverrides to pin specific endpoints.
nesthttpMethods@Get/@Post/@Put/@Patch/@Delete/@Options/@Head/@All
nestlanguagets, tsx, js, mjs (regex extractor — no full TS AST)
nestmethodDecoratorsBelowAnchoryes
nestmethodLevelGuardsyes
nestmultilineControllerArgPARTIAL — single-line and { path: '...' } object form resolve; complex multi-line @Controller args may block the upward scan above @Controller (deferred to v0.4)
openapibasePathOas2yes
openapilanguageyaml, yml, json
openapimissingSecurityUNKNOWN (conservative)
openapioperationSecurityyes
openapioperationSecurityEmptyArrayOPEN
openapirootSecurityyes
openapispecVersionsOpenAPI 2.0 (swagger:) and 3.x (openapi:)

What this does NOT prove

ApiGate is a deterministic, static surface auditor. The points below are not footnotes — they are the contract of what a static report can and cannot tell you. Read them every time.

  1. Static analysis cannot verify runtime authorization (BOLA / object-level access). ApiGate only inspects declared auth posture, not the correctness of the auth middleware itself.
  2. An endpoint with a declared auth identifier in its middleware chain is classified GUARDED — the middleware may still be misconfigured, bypassable, or insecure at runtime.
  3. Routes mounted via dynamic strings (computed prefixes, runtime registration, factory functions) are reported as UNRESOLVED rather than guessed.
  4. ApiGate uses a built-in heuristic pattern list to mark common public-auth paths (login / signup / refresh / health / OAuth callbacks) as INTENTIONAL-PUBLIC. The heuristic is deterministic and configurable but can be wrong both ways — review the marked endpoints and override `publicAuthPatterns` in `.apigate.config.json` if your project disagrees.
  5. The per-endpoint `risk` tier (HIGH / MED / LOW) is a heuristic — pattern-based, frozen at `riskTier.version`. Use `severityOverrides` to pin specific endpoints. Risk is a triage aid, not a runtime exploitability claim.
  6. NestJS global guards registered via `app.useGlobalGuards()` or `{ provide: APP_GUARD }` providers are INVISIBLE to ApiGate's per-controller parser. An endpoint protected ONLY by a global guard will be reported OPEN. If your project uses this pattern, extend `auth.nest` with your custom marker, or pin specific endpoints in `severityOverrides`. See `parserCapabilities.nest.globalGuardDetection`.
  7. ApiGate makes ZERO network calls. It does not send code, telemetry, or scan artifacts anywhere. Reports are written to local files only.