SPA
│
│ Cookie: session=...
▼
Django API
JavaScriptから送るためHTMLフォームを使っていなくても、ブラウザがセッションCookieを自動送信する構成は変わりません。
対策として、CSRFトークンをカスタムヘッダーへ入れます。
X-CSRFToken: トークン
カスタムヘッダーを付けたクロスオリジンリクエストは通常CORSプリフライトの対象になります。
ただし、CORSを広く許可すると防御が弱くなるため、許可Originを限定する必要があります。

クライアントサイドCSRFは、JavaScriptコード自身が攻撃者の入力を使って、意図しないAPIリクエストを組み立てる問題です。
例えば、URLフラグメントやクエリ文字列から送信先を作るコードです。
const endpoint = location.hash.substring(1);
fetch(endpoint, {
method: "POST",
credentials: "include",
headers: {
"X-CSRFToken": getToken()
}
});
攻撃者が次のURLを踏ませたとします。
https://example.com/app#/api/account/delete