You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-up to #210 (PR #213, hotfixed further in commit c6fdad5 on dev).
While verifying #210's fix in production, found that Angular's SSR
"page not found" route (apps/blog-app/src/app/routes/[...page-not-found].ts)
returns HTTP 200 for any unmatched path, not 404. This means:
But real bot-scanner traffic (sampled from Cloud Run logs, 2026-07-04
23:04–23:49 UTC) overwhelmingly hits paths outside that namespace: /.env, /config.php, /backend/.env, /.env.production, /api/.env (one level, not under /v1/), /config.json, /js/config.js,
etc. — all still return 200 today because they fall through to the SSR
not-found handler.
A file-based catch-all can't fix this from server/routes/**: Nitro
registers the SSR fallback as the literal wildcard pattern /**, and
anything we register at that exact same top-level pattern gets silently
overwritten (confirmed empirically — see chore(blog-app): block Cloud Run env/secret scrapers (low-hanging fruit) #210's PR discussion). The only
namespaces we can safely claim are ones that don't collide with the
reserved root wildcard (e.g. /v1/**), which by definition can't cover
paths outside our own route prefix.
Real fix
Make the Angular SSR not-found route actually set a 404 status instead of
200. This is the same underlying class of issue as #211 (Nitro/Analog SSR
routing not matching plain HTTP semantics) — likely requires setting the
response status in [...page-not-found].ts via Angular's server-side RESPONSE_INIT / HttpStatusCode injection token (Analog/Angular Universal
supports setting status codes from a route resolver), so the same component
that renders the "not found" UI also emits a 404 status code before Nitro
sends the response.
Acceptance
Any unmatched path (bare, /api/* outside v1/, or otherwise) returns 404
from a live curl -o /dev/null -w '%{http_code}' check.
The rendered "not found" page content is unchanged for real users
(same UI, just a correct status code).
Context
Follow-up to #210 (PR #213, hotfixed further in commit c6fdad5 on
dev).While verifying #210's fix in production, found that Angular's SSR
"page not found" route (
apps/blog-app/src/app/routes/[...page-not-found].ts)returns HTTP 200 for any unmatched path, not 404. This means:
/api/v1/**catch-all added in chore(blog-app): block Cloud Run env/secret scrapers (low-hanging fruit) #210 now correctly 404s anything underour own API namespace (verified live:
/api/v1/env,/api/v1/config→404).
23:04–23:49 UTC) overwhelmingly hits paths outside that namespace:
/.env,/config.php,/backend/.env,/.env.production,/api/.env(one level, not under/v1/),/config.json,/js/config.js,etc. — all still return 200 today because they fall through to the SSR
not-found handler.
server/routes/**: Nitroregisters the SSR fallback as the literal wildcard pattern
/**, andanything we register at that exact same top-level pattern gets silently
overwritten (confirmed empirically — see chore(blog-app): block Cloud Run env/secret scrapers (low-hanging fruit) #210's PR discussion). The only
namespaces we can safely claim are ones that don't collide with the
reserved root wildcard (e.g.
/v1/**), which by definition can't coverpaths outside our own route prefix.
Real fix
Make the Angular SSR not-found route actually set a 404 status instead of
200. This is the same underlying class of issue as #211 (Nitro/Analog SSR
routing not matching plain HTTP semantics) — likely requires setting the
response status in
[...page-not-found].tsvia Angular's server-sideRESPONSE_INIT/HttpStatusCodeinjection token (Analog/Angular Universalsupports setting status codes from a route resolver), so the same component
that renders the "not found" UI also emits a 404 status code before Nitro
sends the response.
Acceptance
/api/*outsidev1/, or otherwise) returns 404from a live
curl -o /dev/null -w '%{http_code}'check.(same UI, just a correct status code).
confirm the paths that used to 200 now show 404 in
httpRequest.status.