Evidence
csrf.checkOrigin has been concretely removed in SvelteKit 3, currently in pre-release:
cairn's current usage
cairn depends on checkOrigin: false in svelte.config.js as a hard precondition for its admin CSRF subsystem. Key files:
| File |
Line |
Role |
src/lib/sveltekit/csrf.ts |
1 |
Top-level comment: "cairn owns CSRF for the admin once a site disables SvelteKit's global checkOrigin" |
src/lib/sveltekit/guard.ts |
106 |
Comment: "they set checkOrigin: false to hand cairn the admin CSRF authority" |
src/lib/doctor/checks-local.ts |
67, 74, 104, 112 |
Doctor check that asserts checkOrigin: false is present in svelte.config.js or vite.config.ts |
src/tests/unit/doctor-checks-local.test.ts |
58, 318, 329 |
Unit tests for the above doctor check |
Current peer/dev range: ^2.70 (stable 2.70.3).
Impact
When consumer sites upgrade to SvelteKit 3, csrf: { checkOrigin: false } will be silently ignored or will fail to compile, breaking all admin POST flows. The doctor check will also fire on a setting that no longer exists.
trustedOrigins cannot replace checkOrigin: false for cairn's case: the !request_origin clause in SvelteKit's CSRF guard forbids missing-Origin POSTs regardless of trustedOrigins, and privacy-hardened browsers routinely omit the Origin header on same-site navigations.
Planned fallback
The planned migration path (documented in ROADMAP.md under "Migrate cairn's CSRF-disable before SvelteKit removes checkOrigin" and docs/cairn-dx-feedback-2026-06-09-907-0.36-retrofit.md) is:
A Cloudflare Transform Rule that injects an Origin header for /admin POSTs at the edge, before SvelteKit's CSRF guard runs. This lets cairn configure trustedOrigins: ['self'] (or the site's own origin) instead of disabling the check globally, and means the guard always sees an Origin it can evaluate.
The higher-leverage path remains getting upstream to provide a hook that runs before the CSRF check (so cairn can short-circuit it for requests it has already validated), but the Transform Rule is the pragmatic zero-new-dependency fallback.
What needs to happen before SvelteKit 3 stable ships
Evidence
csrf.checkOriginhas been concretely removed in SvelteKit 3, currently in pre-release:3.0.0-next.15via PR #15437"breaking: remove the deprecated CSRF checkOrigin option in favor of trustedOrigins (#15437)"3.0.0-next.25— the removal has already landed in active pre-releasestrustedOriginsis the only remaining escape hatch2.36.2(PR #14281), flagging this as a breaking change aheadcairn's current usage
cairn depends on
checkOrigin: falseinsvelte.config.jsas a hard precondition for its admin CSRF subsystem. Key files:src/lib/sveltekit/csrf.tssrc/lib/sveltekit/guard.tscheckOrigin: falseto hand cairn the admin CSRF authority"src/lib/doctor/checks-local.tscheckOrigin: falseis present insvelte.config.jsorvite.config.tssrc/tests/unit/doctor-checks-local.test.tsCurrent peer/dev range:
^2.70(stable 2.70.3).Impact
When consumer sites upgrade to SvelteKit 3,
csrf: { checkOrigin: false }will be silently ignored or will fail to compile, breaking all admin POST flows. The doctor check will also fire on a setting that no longer exists.trustedOriginscannot replacecheckOrigin: falsefor cairn's case: the!request_originclause in SvelteKit's CSRF guard forbids missing-OriginPOSTs regardless oftrustedOrigins, and privacy-hardened browsers routinely omit the Origin header on same-site navigations.Planned fallback
The planned migration path (documented in ROADMAP.md under "Migrate cairn's CSRF-disable before SvelteKit removes checkOrigin" and
docs/cairn-dx-feedback-2026-06-09-907-0.36-retrofit.md) is:A Cloudflare Transform Rule that injects an
Originheader for/adminPOSTs at the edge, before SvelteKit's CSRF guard runs. This lets cairn configuretrustedOrigins: ['self'](or the site's own origin) instead of disabling the check globally, and means the guard always sees an Origin it can evaluate.The higher-leverage path remains getting upstream to provide a hook that runs before the CSRF check (so cairn can short-circuit it for requests it has already validated), but the Transform Rule is the pragmatic zero-new-dependency fallback.
What needs to happen before SvelteKit 3 stable ships
checkOrigin: falsedoctor check (or convert it to flag the old pattern as deprecated)trustedOriginsinstead ofcheckOrigin: falsedocs/guides/restrict-admin-access.mdand any other docs referencingcheckOrigin