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/:idexpressHIGHOPEN—examples/route-middleware/index.js:82
POST/expressHIGHOPEN—examples/cookies/index.js:39
PUT/user/:id/editexpressHIGHOPEN—examples/route-separation/index.js:45
GET/api/usersexpressMEDOPEN—examples/web-service/index.js:75
GET/usersexpressMEDOPEN—examples/content-negotiation/index.js:40
GET/usersexpressMEDOPEN—examples/route-separation/index.js:40
GET/users/:from-:toexpressMEDOPEN—examples/params/index.js:63
ALL/user/:id{/:op}expressLOWOPEN—examples/route-separation/index.js:41
GET/expressLOWOPEN PUBLIC—examples/auth/index.js:84
GET/expressLOWOPEN PUBLIC—examples/content-negotiation/index.js:9
GET/expressLOWOPEN PUBLIC—examples/cookie-sessions/index.js:16
GET/expressLOWOPEN PUBLIC—examples/cookies/index.js:24
GET/expressLOWOPEN PUBLIC—examples/downloads/index.js:15
GET/expressLOWOPEN PUBLIC—examples/ejs/index.js:45
GET/expressLOWOPEN PUBLIC—examples/error-pages/index.js:30
GET/expressLOWOPEN PUBLIC—examples/error/index.js:29
GET/expressLOWOPEN PUBLIC—examples/hello-world/index.js:7
GET/expressLOWOPEN PUBLIC—examples/markdown/index.js:32
GET/expressLOWOPEN PUBLIC—examples/multi-router/index.js:10
GET/expressLOWOPEN PUBLIC—examples/online/index.js:50
GET/expressLOWOPEN PUBLIC—examples/params/index.js:47
GET/expressLOWOPEN PUBLIC—examples/resource/index.js:78
GET/expressLOWOPEN PUBLIC—examples/route-middleware/index.js:70
GET/expressLOWOPEN PUBLIC—examples/route-separation/index.js:36
GET/expressLOWOPEN PUBLIC—examples/session/index.js:22
GET/expressLOWOPEN PUBLIC—examples/session/redis.js:27
GET/expressLOWOPEN PUBLIC—examples/view-constructor/index.js:32
GET/expressLOWOPEN PUBLIC—examples/view-locals/index.js:26
GET/403expressLOWOPEN—examples/error-pages/index.js:41
GET/404expressLOWOPEN—examples/error-pages/index.js:34
GET/500expressLOWOPEN—examples/error-pages/index.js:48
GET/Readme.mdexpressLOWOPEN—examples/view-constructor/index.js:39
GET/api/reposexpressLOWOPEN—examples/web-service/index.js:80
GET/api/user/:name/reposexpressLOWOPEN—examples/web-service/index.js:85
GET/client.jsexpressLOWOPEN—examples/search/index.js:69
GET/failexpressLOWOPEN—examples/markdown/index.js:36
GET/files/*fileexpressLOWOPEN—examples/downloads/index.js:26
GET/forgetexpressLOWOPEN—examples/cookies/index.js:34
GET/loginexpressLOWOPEN—examples/auth/index.js:100
GET/logoutexpressLOWOPEN—examples/auth/index.js:92
GET/middlewareexpressLOWOPEN—examples/view-locals/index.js:64
GET/middleware-localsexpressLOWOPEN—examples/view-locals/index.js:102
GET/nextexpressLOWOPEN—examples/error/index.js:34
GET/postsexpressLOWOPEN—examples/route-separation/index.js:49
GET/restrictedexpressLOWOPEN—examples/auth/index.js:88
GET/search/{:query}expressLOWOPEN—examples/search/index.js:52
GET/user/:idexpressLOWOPEN—examples/route-middleware/index.js:74
GET/user/:idexpressLOWOPEN—examples/route-separation/index.js:42
GET/user/:id/editexpressLOWOPEN—examples/route-middleware/index.js:78
GET/user/:id/editexpressLOWOPEN—examples/route-separation/index.js:44
GET/user/:id/viewexpressLOWOPEN—examples/route-separation/index.js:43
GET/user/:userexpressLOWOPEN—examples/params/index.js:55
GETenvexpressLOWOPEN—examples/error/index.js:10
GETetag fnexpressLOWOPEN—lib/response.js:161
GETjson escapeexpressLOWOPEN—lib/response.js:235
GETjson escapeexpressLOWOPEN—lib/response.js:263
GETjson replacerexpressLOWOPEN—lib/response.js:236
GETjson replacerexpressLOWOPEN—lib/response.js:264
GETjson spacesexpressLOWOPEN—lib/response.js:237
GETjson spacesexpressLOWOPEN—lib/response.js:265
GETjsonp callback nameexpressLOWOPEN—lib/response.js:267
GETquery parser fnexpressLOWOPEN—lib/request.js:231
GETsubdomain offsetexpressLOWOPEN—lib/request.js:388
GETtrust proxy fnexpressLOWOPEN—lib/request.js:301
GETtrust proxy fnexpressLOWOPEN—lib/request.js:341
GETtrust proxy fnexpressLOWOPEN—lib/request.js:358
GETtrust proxy fnexpressLOWOPEN—lib/request.js:419
POST/loginexpressLOWOPEN PUBLIC—examples/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.