Datasette Replaces CSRF Tokens with Sec-Fetch-Site Headers

Datasette PR #2689 swaps token-based CSRF for Sec-Fetch-Site header checks, eliminating hidden form tokens and skip_csrf hooks for simpler protection across forms and APIs.

Simplifying CSRF Protection Without Tokens

Traditional CSRF tokens in Datasette required adding <input type="hidden" name="csrftoken" value="{{ csrftoken() }}"> to every form in templates and manually disabling protection via the skip_csrf(datasette, scope) plugin hook for external API calls. This scattered complexity made maintenance painful. The new approach uses the browser's Sec-Fetch-Site header—set to same-origin for same-site requests and cross-site for others—to block cross-site form submissions automatically, protecting against CSRF without any tokens or per-endpoint tweaks.

This header-based method, proven secure in production, lets you build forms without extra inputs and expose APIs without CSRF exemptions, reducing boilerplate and errors.

Key Changes in PR #2689

The pull request introduces ASGI middleware inspired by Filippo Valsorda's August 2025 research essay and Go 1.25's net/http implementation:

Claude Code handled 10 commits under guidance, with GPT-5.4 cross-review—AI accelerated the refactor while keeping it precise.

Why It Works and Upgrade Impact

Browsers enforce Sec-Fetch-Site reliably since Chrome 76+, covering 99%+ of users without JavaScript or tokens. It blocks malicious cross-site POSTs natively, trading zero compatibility issues for token pains. Upgrade by pulling latest Datasette: templates clean up automatically, plugins simplify sans skip_csrf. Test forms and APIs stay secure, but verify no custom skips linger.

Summarized by x-ai/grok-4.1-fast via openrouter

4500 input / 2477 output tokens in 15880ms

© 2026 Edge