{"ok": true, "database": "docs", "table": "sections", "rows": [{"id": "upgrade_guide:breaking-changes", "page": "upgrade_guide", "ref": "breaking-changes", "title": "Breaking changes", "content": "The  skip_csrf  plugin hook has been removed.  Existing plugins that still declare a  skip_csrf  hookimpl will continue to load - pluggy silently ignores unknown hook names - but the hook is no longer consulted by core, so the flows it previously unlocked will now be blocked (or allowed) purely on the basis of the new header check. \n                             The new middleware already covers the common cases that  skip_csrf  was written for: \n                             \n                                 \n                                     Browser-initiated JSON POSTs automatically get  Sec-Fetch-Site: same-origin  and pass the check. \n                                 \n                                 \n                                     Non-browser API clients (curl,  requests , server-to-server scripts) do not send browser security headers and are passed through. \n                                 \n                                 \n                                     Requests with an explicit  Authorization: Bearer ...  header are exempt from the CSRF check (see above). \n                                 \n                             \n                             If your plugin previously used  skip_csrf  to accept cross-origin browser POSTs, replace that flow with an authentication mechanism that does  not  rely on ambient browser credentials. Safe patterns include: \n                             \n                                 \n                                     Requiring an  Authorization: Bearer ...  API token on the endpoint. \n                                 \n                                 \n                                     Requiring a non-ambient credential in the request body (a webhook secret, HMAC signature, signed capability URL, OAuth client credential, or similar). \n                                 \n                                 \n                                     Issuing a short-lived signed URL that encodes the actor, the action, and an expiry, and verifying the signature on request. \n                                 \n                             \n                             Do not rely on the  ds_csrftoken  cookie for your own plugin's security checks - Datasette no longer sets or validates it, and the  request.scope[\"csrftoken\"]()  compatibility shim now returns a fresh random value each request rather than the signed cookie-bound value it used to. \n                         \n                         \n                             The  asgi-csrf  dependency has been dropped.  Any plugin that imported from  asgi_csrf  directly will need to be updated. \n                         \n                         \n                             The  csrf_error.html  template now receives a  reason  context variable  instead of  message_id  and  message_name . Custom overrides of this template should be updated.", "breadcrumbs": "[\"Upgrade guide\", \"Datasette 1.0a20 plugin upgrade guide\", \"CSRF protection is now header-based\"]", "references": "[]"}], "primary_keys": ["id"], "primary_key_values": ["upgrade_guide:breaking-changes"], "query_ms": 4.086924000148429, "truncated": false}