Security
The controls actually in the product.
This page describes the security controls that are in code, not a marketing claim about the product. Every item below maps to a file or a header in the running deployment. The technical policy is in SECURITY.md.
Supported versions
Only the most recent public release receives security fixes.
| Surface | Version | Status |
|---|---|---|
| Web application | Kingfisher 1.5.5 | Current. Served at kingfisherchess.app from every push to master. |
| macOS application | Kingfisher 1.5.5 | Apple Silicon DMG, signed with Developer ID and notarised by Apple; opens with a double-click. |
Older release candidates are not patched. If a regression is reported against one, the answer is to upgrade.
Browser / web application
- Content Security Policy —
vercel.jsonships a strict CSP withdefault-src self, no third-partyscript-src,frame-ancestors none,base-uri self,object-src none. The onlyscript-srcallowances areself,wasm-unsafe-eval(Stockfish WebAssembly) andunsafe-inline(no scripts are inlined; this allowance is retained for Next.js style attributes and does not allow arbitrary inline JavaScript). - Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: credentialless are sent on every response, which is what enables
SharedArrayBufferfor the Stockfish multi-threaded build. - HSTS with
max-age=31536000; includeSubDomains; preloadand a Referrer-Policy: strict-origin-when-cross-origin header on every response. - Permissions-Policy disables
camera,microphone,geolocationandinterest-cohort(FLoC) at the document level. - Remote origins the application calls are named in
connect-src: the application's own host, the GitHub Pages data mirror, Lichess, Chess.com and the desktop companion's loopback range. The policy also allowshttps:, because two calls choose their host at runtime — the full-network browser engine is fetched from the address its manifest records with a pinned SHA-256, and a user-configured assistant endpoint is whatever you typed — so it does not refuse other HTTPS hosts; the application's own code makes no other call. Scripts, styles, frames and objects are restricted to the origin regardless. - The Mac application’s window only shows Kingfisher. It never navigates away from the server the shell started: a link anywhere else is opened in your own browser, and only when it is an
https:address; the one navigation that comes back is the Lichess sign-in callback. Seedesktop/src/main.mjs. In a browser, a link is an ordinary link; there is no outbound allow-list. - Downloaded data is verified. Every reference-pack chunk and every managed engine binary is checked against a SHA-256 recorded in the manifest before it is used; a mismatch is reported, never silently accepted. See
src/reference/install.ts,companion/src/managed-engines.mjsandTHIRD_PARTY_DATA.md. - Decompression bounds — every decompression path uses
DecompressionStreamwith an explicit byte budget and rejects a chunk whose decompressed size exceeds the manifests record. - IndexedDB streaming cache — the explorer caches shards in IndexedDB with a byte budget and a TTL; cached bytes are re-verified against the manifest before they are reused.
- Backup portability — backups are portable JSON with the same schema-versioned envelope as persistence; see
docs/deployment.md.
macOS application
- The desktop shell is Electron with
contextIsolation: true,nodeIntegration: false,sandbox: truefor the renderer, and a preload that exposes a typed bridge. The bridge returnsnullin a browser, so the same application is safe to serve over a public origin. - The companion’s loopback server authenticates every request except
/healthwith a pairing token the shell mints in memory on each launch and never writes to disk; the shell and the companion are the only two processes that ever hold it. Cross-origin requests are refused by CORS. - The application is signed with a Developer ID Application certificate with the Hardened Runtime, notarised by Apple, and stapled; the build refuses to sign a bundle missing any required runtime file and launches the notarised application before it makes a disk image.
- Native engines are not sandboxed. They run with the user's own operating-system permissions, and a settings panel checkbox is the only thing that prevents them from being launched. This is documented in the Settings → Engine dialog and in
AGENTS.md. Do not describe managed engines as sandboxed. - The window cannot open a file that was not chosen in a dialog or dropped on the window; there is no
readFile(path)on the bridge. - The shell holds no chess state. A desktop feature that needs a second copy of the board, the move tree, the engine session or the query is a bug in the arrangement, not a feature of it.
What the product deliberately does not do
- No sync without an account. Signed out, studies, repertoire, training, notes and preferences stay in one browser profile, and the way to move them is Settings → Database → Export backup and restore on the other side. Signed in to the optional account, they sync through a database whose Row Level Security admits only their owner. Secrets never sync, and nor do imported game collections — except My games, on a device where you switch that on.
- Page views and load times only, from this origin. The website counts page views with Vercel Web Analytics and page load timings with Vercel Speed Insights, served from
/_vercel/on this origin — no cookie, no identifier on the device, query strings stripped. No other analytics, no error-reporting service, no third-party script: the CSP is'self'and would refuse one. The Mac application loads none of it. - No advertising cookies, no advertising scripts. The web build does not set any cookie; what state the application needs is held in
localStorageand IndexedDB, scoped to the origin. - No background update. The macOS application asks the release feed when you choose Kingfisher → Check for Updates…, and once, quietly, after launch — a look that shows nothing and downloads nothing. It installs an update only when you click Install Update; the download is verified against Kingfisher’s signing key and your work is saved before the application is replaced. The web build is whatever is currently deployed; if a fix is urgent, a manual refresh picks it up.
How to report a vulnerability
Do not open a public GitHub issue, discussion, tweet or forum post for a security problem. Public issues are indexed by search engines and will be read by every attacker in the world before a fix is in the next release.
Use the private GitHub Security Advisory flow:
https://github.com/mardakurt/kingfisher/security/advisories/new
If the GitHub security flow is unavailable for any reason, open a private issue at the same repository with the word SECURITY: at the start of the title and without exploit detail in the body — the maintainer will move the conversation to the private advisory flow.
The report should include:
- the affected version (e.g.
Kingfisher 1.4.4and the date for the web build orKingfisher 1.4.4and its build number for the macOS application); - a minimal reproduction;
- what you observed and what you expected;
- any workarounds you tried.
A diagnostic export from Settings → Diagnostics is safe to attach. The export never includes Lichess tokens, API keys, the companion pairing token, home-directory paths or full PGN libraries.
What to expect
The maintainer aims to:
- acknowledge the report within seven days;
- ship a fix in the next release, or sooner if the issue is severe;
- publish a CVE if the report warrants one;
- credit the reporter in the release notes (unless the reporter prefers to remain anonymous).
Out of scope
- Engine binary vulnerabilities. Kingfisher verifies the SHA-256 of every engine it downloads against the manifest shipped in the repository, but the engines themselves are third-party and are covered by their own security policies.
- Reference data vulnerabilities. Kingfisher verifies the SHA-256 of every chunk it downloads against the manifest shipped in the data repository.
- Phishing, social engineering, or supply-chain attacks on the users machine. Kingfisher is local-first; the product is not a hosted service.
Non-security issues
For bugs, regressions and product questions, open an issue at the issue tracker. Paste the Settings → Diagnostics → Copy support information line so the report includes version, machine and source/engine state.