Skip to content

Kayon v1.2.1 — desktop CSRF fix

Choose a tag to compare

@caesarlab caesarlab released this 14 Jul 17:10
· 30 commits to main since this release

This download has been withdrawn. Versions up to 1.3.2 shipped a flaw in the local web server: a crafted request could read any file your Windows account can read, and another could read the chat database. Both were found in review and fixed in 1.4.0. The installer has been removed from this release so nobody installs it by accident. The notes below are kept as the record. Please use the latest release.


Critical fix. This replaces 1.2.0

Don't use 1.2.0. In the installed desktop app it silently rejected every action that changed anything.

What went wrong

  • The Tauri window loads from tauri.localhost and calls the local API on 127.0.0.1:9518. Those are different origins, so the browser stamps every request cross-site.
  • The CSRF guard checked Sec-Fetch-Site before it checked the Origin allow-list, and rejected anything cross-site. Every write returned 403 without a word: load and chat, downloads, pause/resume/cancel, Ollama adopt, delete, settings, the telemetry toggle.
  • Reads still worked, so the app looked alive while doing nothing.
  • The silence had a second cause. The 403 body was plain text, so resp.json() threw inside an un-caught handler and the UI showed nothing at all.

The fix

  • The guard now treats the Origin allow-list as authoritative. A browser sets Origin on every mutating request and scripts can't forge it, so it is the right thing to trust.
  • A Kayon origin, including tauri.localhost, passes. A foreign origin is still rejected, and Sec-Fetch-Site only matters when no Origin is present. Defence against real cross-site pages is unchanged.
  • The logic lives in a pure csrf_check() with regression tests pinning the tauri.localhost case.
  • apiFetch() no longer throws on a non-JSON or non-2xx response. It returns {ok:false, error}, so a rejected call surfaces as a visible error instead of a silent no-op.

Verified

  • The exact request WebView2 sends, Origin tauri.localhost with Sec-Fetch-Site: cross-site, now returns 200.
  • evil.example and no-origin cross-site still return 403.
  • 20 tests pass, and the Codex review found nothing.

Upgrade

Run the installer over any 1.2.0 install.