Skip to content

Finish CSRF token frontend integration (#537 follow-up) #627

Description

@itsmiso-ai

Parent umbrella issue: #622
Source audit: Weekly tech debt audit: miso-chat - 2026-06-24
Source audit date: 2026-06-24

Original recommendation

P1 — Finish CSRF token frontend integration (#537 follow-up): make public/index.html (or the extracted public/lib/api-client.js successor) fetch /api/csrf-token on page load, attach X-CSRF-Token to every state-changing request from apiFetch, retry once on 403 with a fresh token, and add integration tests covering both the accepted-token and rotated-token paths.

Matched top finding

  • Route-level CSRF tokens ship but the frontend never fetches or sends them (issue Add route-level CSRF tokens for browser session commands #537 partially regressed). security.js:121-129 documents that the frontend MUST fetch /api/csrf-token and send X-CSRF-Token. The route exists at server.js:453 but grep -rn "X-CSRF-Token\|/api/csrf-token" public/ public/lib/ public/mobile/ returns zero matches outside server files. csrfTokenCheck then early-returns when req.session.csrfToken is unset (security.js:152-154), so today's protection is only origin-check + SameSite. Send/abort/reaction/logout state changes are reachable from any origin that origin-checks will accept (capacitor://localhost, ionic://localhost, app://localhost, null, plus configured CORS_ORIGIN/ALLOWED_ORIGINS/CSRF_TRUSTED_ORIGINS).

  • Android release APKs are not signed for production (issue Replace debug APK release lane with production-grade artifact policy #536 partially regressed). android/app/build.gradle:19-25 declares release { minifyEnabled false; proguardFiles ... } with no signingConfig, and the release workflow builds assembleRelease + bundleRelease against that type. The OTA manifest's apkUrl for stable/beta points at these artifacts (android-release.yml:113,121,135,151). Without a release keystore wired up (env-injected or committed), installs from OTA fail on real devices, and the published APK/AAB is indistinguishable from a debug build.

  • script-src 'unsafe-inline' after PR fix: remove CSP nonce that blocks inline scripts #604 removed the inline-script nonce. security.js:204 now allows inline scripts; public/index.html has 30+ inline <script> blocks, plus uses div.innerHTML = '<a href="' + url + '"...' (public/index.html:3233) and other innerHTML sinks driven by gateway-controlled image URLs. The CSP defense-in-depth that would catch a future XSS bug is gone. The same PR also shipped because frontend startup regression was caught late; need a CSP-preserving inline-script policy (hash-based or extracted) plus pre-merge frontend smoke.

  • Auth regression introduced by merge automation and caught post-merge (PRs [codex] restore frontend startup #618, [codex] restore shared session access #620). PR [codex] restore frontend startup #618 broke frontend startup; [codex] restore shared session access #620 had to re-instate shared session access after the auth boundary tightened too much and broke isAuthenticated semantics for agent:main:main keys. Both were catchable by integration tests that don't yet exist for the boot path or the deployment-boundary semantics. This is the same regression class as bug(release): release workflow fails before image build on app startup regressions #374 (release workflow) and chore(release): bump version to 0.4.17 #617/[codex] restore frontend startup #618 (frontend startup).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions