Skip to content

fix(frontend): harden all 7 findings from the JS security/data-loss review - #65

Open
loonvault-agent[bot] wants to merge 1 commit into
mainfrom
fix/js-hardening-all-findings
Open

loonvault-agent[bot] wants to merge 1 commit into
mainfrom
fix/js-hardening-all-findings

Conversation

@loonvault-agent

Copy link
Copy Markdown
Contributor

Summary

Follow-up to the JS security & data-loss review: lands all 7 findings (the review found no exploitable vulnerability; these are hardening + data-availability fixes). Each fix was empirically verified — the finding was first reproduced, then the fix confirmed, plus non-regression checks.

# File Anti-pattern Fix
1 app.js No fetch timeout: a hanging live API stalls "Loading…" forever; snapshot fallback never runs AbortSignal.timeout(8000), feature-detected
2 app.js Broad .catch conflates render() bugs with fetch failures → "Backend is offline" while the backend is healthy, or a mislabeled data source; errors swallowed silently Two-arg .then separates error channels; all failures logged; render bugs get a distinct message
3 md-renderer.js safeHref accepted protocol-relative //evil.com and backslash /\evil.com URLs (verified live off-site nav) Root-relative alternative is now \/(?![/\\])
4 viewer.js Plain-object grouping: a doc group named __proto__/constructor crashes the docs sidebar (verified TypeError) Object.create(null)
5 md-renderer.js Bold/italic passes rewrote hrefs containing * (verified <strong> inside the attribute — no XSS, but broken links) Opening <a> tags placeholder-stashed like inline code; bold inside link text still renders
6 api-worker.js Wholesale response-header passthrough could leak the execute-api host (e.g. a Location header) the worker exists to hide Response-header allowlist: content-type + CORS set + vary
7 worker.js All client headers forwarded to the origin, including credentials, on a credential-free site cookie/authorization stripped; everything else (e.g. accept-encoding) still forwards

Verification

39-check node suite (scratchpad, not committed): every #64 behavior re-verified (escaping, javascript: blocking, preflight forwarding, 405/404/414/400/421/502 rejections, apex redirect, path allowlists) + each finding's repro-then-fix + non-regressions (bold-in-link-text renders, accept-encoding passthrough, ACAO passthrough, body integrity). node --check clean on all five files.

⚠️ After merge: re-paste both workers into the Cloudflare dashboard (cloudflare/worker.js AND cloudflare/api-worker.js — both changed), then just deploy-frontend + purge the Cloudflare cache.

🤖 Generated with Claude Code

…eview

Security review of all six first-party JS files found no exploitable
vulnerability but 7 anti-patterns; this lands all of them:

1. app.js: fetches had no timeout — a HANGING (not failed) live API stalled
   "Loading…" forever and the snapshot fallback never ran. AbortSignal.timeout
   (8s, feature-detected) guarantees fallback.
2. app.js: broad .catch conflated render() exceptions with fetch failures —
   a display bug could show "Backend is offline" (or refetch + mislabel the
   source) while the backend was healthy. Two-arg .then separates the error
   channels; every failure path now logs; render bugs get their own message.
3. md-renderer.js: safeHref's root-relative alternative accepted
   protocol-relative (//evil.com) and backslash (/\evil.com, normalized by
   browsers to //) URLs — off-site navigation through the scheme allowlist.
   Now /(?![/\\]).
4. viewer.js: sidebar grouping used a plain object — a doc group named
   __proto__/constructor hit the prototype and crashed the docs sidebar.
   Object.create(null).
5. md-renderer.js: bold/italic passes ran over built <a> tags and rewrote
   hrefs containing * (no XSS — quotes escaped — but broken links). Opening
   tags are now placeholder-stashed like inline code; bold inside link TEXT
   still renders.
6. api-worker.js: response headers passed through wholesale — a future
   Location/debug header would leak the execute-api host the worker exists to
   hide. Response headers are now allowlisted (content-type, CORS set, vary).
7. worker.js: all client headers were forwarded to the origin; the site is
   credential-free, so cookie/authorization are now stripped (everything
   else, e.g. accept-encoding, still forwards).

Verified with a 39-check node suite: all prior #64 behavior (escaping,
javascript: blocking, preflight forwarding, rejection statuses, apex
redirect, path allowlists) plus each finding's fix and its non-regression
(bold-in-link-text, accept-encoding passthrough, ACAO passthrough).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants