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
| Method | Path | Framework | Risk | Posture | Marker / Reason | Location |
|---|---|---|---|---|---|---|
| DELETE | /user/:id | express | HIGH | OPEN | — | examples/route-middleware/index.js:82 |
| POST | / | express | HIGH | OPEN | — | examples/cookies/index.js:39 |
| PUT | /user/:id/edit | express | HIGH | OPEN | — | examples/route-separation/index.js:45 |
| GET | /api/users | express | MED | OPEN | — | examples/web-service/index.js:75 |
| GET | /users | express | MED | OPEN | — | examples/content-negotiation/index.js:40 |
| GET | /users | express | MED | OPEN | — | examples/route-separation/index.js:40 |
| GET | /users/:from-:to | express | MED | OPEN | — | examples/params/index.js:63 |
| ALL | /user/:id{/:op} | express | LOW | OPEN | — | examples/route-separation/index.js:41 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/auth/index.js:84 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/content-negotiation/index.js:9 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/cookie-sessions/index.js:16 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/cookies/index.js:24 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/downloads/index.js:15 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/ejs/index.js:45 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/error-pages/index.js:30 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/error/index.js:29 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/hello-world/index.js:7 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/markdown/index.js:32 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/multi-router/index.js:10 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/online/index.js:50 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/params/index.js:47 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/resource/index.js:78 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/route-middleware/index.js:70 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/route-separation/index.js:36 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/session/index.js:22 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/session/redis.js:27 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/view-constructor/index.js:32 |
| GET | / | express | LOW | OPEN PUBLIC | — | examples/view-locals/index.js:26 |
| GET | /403 | express | LOW | OPEN | — | examples/error-pages/index.js:41 |
| GET | /404 | express | LOW | OPEN | — | examples/error-pages/index.js:34 |
| GET | /500 | express | LOW | OPEN | — | examples/error-pages/index.js:48 |
| GET | /Readme.md | express | LOW | OPEN | — | examples/view-constructor/index.js:39 |
| GET | /api/repos | express | LOW | OPEN | — | examples/web-service/index.js:80 |
| GET | /api/user/:name/repos | express | LOW | OPEN | — | examples/web-service/index.js:85 |
| GET | /client.js | express | LOW | OPEN | — | examples/search/index.js:69 |
| GET | /fail | express | LOW | OPEN | — | examples/markdown/index.js:36 |
| GET | /files/*file | express | LOW | OPEN | — | examples/downloads/index.js:26 |
| GET | /forget | express | LOW | OPEN | — | examples/cookies/index.js:34 |
| GET | /login | express | LOW | OPEN | — | examples/auth/index.js:100 |
| GET | /logout | express | LOW | OPEN | — | examples/auth/index.js:92 |
| GET | /middleware | express | LOW | OPEN | — | examples/view-locals/index.js:64 |
| GET | /middleware-locals | express | LOW | OPEN | — | examples/view-locals/index.js:102 |
| GET | /next | express | LOW | OPEN | — | examples/error/index.js:34 |
| GET | /posts | express | LOW | OPEN | — | examples/route-separation/index.js:49 |
| GET | /restricted | express | LOW | OPEN | — | examples/auth/index.js:88 |
| GET | /search/{:query} | express | LOW | OPEN | — | examples/search/index.js:52 |
| GET | /user/:id | express | LOW | OPEN | — | examples/route-middleware/index.js:74 |
| GET | /user/:id | express | LOW | OPEN | — | examples/route-separation/index.js:42 |
| GET | /user/:id/edit | express | LOW | OPEN | — | examples/route-middleware/index.js:78 |
| GET | /user/:id/edit | express | LOW | OPEN | — | examples/route-separation/index.js:44 |
| GET | /user/:id/view | express | LOW | OPEN | — | examples/route-separation/index.js:43 |
| GET | /user/:user | express | LOW | OPEN | — | examples/params/index.js:55 |
| GET | env | express | LOW | OPEN | — | examples/error/index.js:10 |
| GET | etag fn | express | LOW | OPEN | — | lib/response.js:161 |
| GET | json escape | express | LOW | OPEN | — | lib/response.js:235 |
| GET | json escape | express | LOW | OPEN | — | lib/response.js:263 |
| GET | json replacer | express | LOW | OPEN | — | lib/response.js:236 |
| GET | json replacer | express | LOW | OPEN | — | lib/response.js:264 |
| GET | json spaces | express | LOW | OPEN | — | lib/response.js:237 |
| GET | json spaces | express | LOW | OPEN | — | lib/response.js:265 |
| GET | jsonp callback name | express | LOW | OPEN | — | lib/response.js:267 |
| GET | query parser fn | express | LOW | OPEN | — | lib/request.js:231 |
| GET | subdomain offset | express | LOW | OPEN | — | lib/request.js:388 |
| GET | trust proxy fn | express | LOW | OPEN | — | lib/request.js:301 |
| GET | trust proxy fn | express | LOW | OPEN | — | lib/request.js:341 |
| GET | trust proxy fn | express | LOW | OPEN | — | lib/request.js:358 |
| GET | trust proxy fn | express | LOW | OPEN | — | lib/request.js:419 |
| POST | /login | express | LOW | OPEN PUBLIC | — | examples/auth/index.js:104 |
Rubrics five 0–100 scores · headline = arithmetic mean of non-null rubrics
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.
| Parser | Capability | Behavior |
|---|---|---|
| express | crossFileMountPrefix | no |
| express | dynamicMountPrefix | UNRESOLVED |
| express | httpMethods | get/post/put/delete/patch/head/options/all |
| express | language | js, mjs, cjs (AST) · ts, tsx (regex fallback) |
| express | middlewareIdentifierExtraction | yes |
| express | sameFileMountPrefix | yes |
| express | typeScriptAst | no |
| fastify | httpMethods | get/post/put/delete/patch/head/options + fastify.route() |
| fastify | language | js, mjs, cjs (AST only) |
| fastify | preHandlerIdentifierExtraction | yes |
| fastify | registerPrefixPropagation | no |
| fastify | routeOptionsParsed | yes |
| fastify | typeScriptAst | no |
| nest | classLevelGuards | yes |
| nest | controllerArrayArg | first path only |
| nest | controllerObjectArg | path field only (version segment ignored) |
| nest | controllerStringArg | yes |
| nest | dynamicDecoratorArg | UNRESOLVED |
| nest | globalGuardDetection | NOT 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. |
| nest | httpMethods | @Get/@Post/@Put/@Patch/@Delete/@Options/@Head/@All |
| nest | language | ts, tsx, js, mjs (regex extractor — no full TS AST) |
| nest | methodDecoratorsBelowAnchor | yes |
| nest | methodLevelGuards | yes |
| nest | multilineControllerArg | PARTIAL — single-line and { path: '...' } object form resolve; complex multi-line @Controller args may block the upward scan above @Controller (deferred to v0.4) |
| openapi | basePathOas2 | yes |
| openapi | language | yaml, yml, json |
| openapi | missingSecurity | UNKNOWN (conservative) |
| openapi | operationSecurity | yes |
| openapi | operationSecurityEmptyArray | OPEN |
| openapi | rootSecurity | yes |
| openapi | specVersions | OpenAPI 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.
- Static analysis cannot verify runtime authorization (BOLA / object-level access). ApiGate only inspects declared auth posture, not the correctness of the auth middleware itself.
- 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.
- Routes mounted via dynamic strings (computed prefixes, runtime registration, factory functions) are reported as UNRESOLVED rather than guessed.
- 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.
- 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.
- 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`.
- ApiGate makes ZERO network calls. It does not send code, telemetry, or scan artifacts anywhere. Reports are written to local files only.