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
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.
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 extractedpublic/lib/api-client.jssuccessor) fetch/api/csrf-tokenon page load, attachX-CSRF-Tokento every state-changing request fromapiFetch, 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-129documents that the frontend MUST fetch/api/csrf-tokenand sendX-CSRF-Token. The route exists atserver.js:453butgrep -rn "X-CSRF-Token\|/api/csrf-token" public/ public/lib/ public/mobile/returns zero matches outside server files.csrfTokenCheckthen early-returns whenreq.session.csrfTokenis 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 configuredCORS_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-25declaresrelease { minifyEnabled false; proguardFiles ... }with nosigningConfig, and the release workflow buildsassembleRelease+bundleReleaseagainst that type. The OTA manifest'sapkUrlfor 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:204now allows inline scripts;public/index.htmlhas 30+ inline<script>blocks, plus usesdiv.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
isAuthenticatedsemantics foragent:main:mainkeys. 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).