Repository navigation
fix(manager): POST送信経路によらずCSRFトークンを必ず付与する - #473
Conversation
リソース編集のプレビュー後にフォームへ target="main" が残り、以後の保存が シェルを経由しないネイティブ送信になっていた。AJAX遷移で差し込まれた フォームには hidden の csrf_token がなく、form.submit() は submit イベントを 発火しないため、token: none の 403 になっていた。 - CSRF自動付与を media/script/csrf.js へ切り出し、shell.js より先に読み込む - submit イベントと form.submit() の両方で送信直前に csrf_token を補う - XHR(jQuery含む)と fetch の同一オリジンPOSTに X-CSRF-Token を付与する (ajaxSetup の beforeSend は呼び出し側の指定で上書きされるため廃止) - プレビュー送信後は action / target を元の状態へ戻す Fixes #470 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VqS5g34F8nY9QhMKxX6VGV
|
Warning Review limit reachedNext included review available in 51 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Repository: modxcms-jp/evolution-jp/.coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (4)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
Fetch requests may overwrite an existing request token when init.headers is provided.
Review effort: Lite
Findings: None
What changed in this PR
This pull request centralizes CSRF protection for manager POST requests and restores form state after previews.
Changes:
- Adds CSRF handling for forms, XHR, and
fetch. - Loads
csrf.jsbeforeshell.js. - Restores preview form
actionandtarget. - Documents the resolved issue.
| File | Changes |
|---|---|
manager/media/style/common/jscripts.tpl |
Restores form state after preview. |
manager/media/script/csrf.js |
Adds CSRF tokens to submission paths; fetch header merging needs correction. |
manager/actions/header.inc.php |
Loads csrf.js before shell.js. |
assets/docs/troubleshooting/solved-issues.md |
Records the Issue #470 resolution. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Fixes #470
What
管理画面から
manager/index.phpへの POST に、送信経路によらず必ず CSRF トークンが付くようにしました。header.inc.phpのインラインからmanager/media/script/csrf.jsに切り出し、shell.jsより先に読み込むように変更action/targetを元の状態に戻すよう修正(jscripts.tpl)Why
CSRF token validation failed | action: 5 | method: POST | token: none | valid_tokens_count: 1が繰り返し報告されている(同系統で 3 回目。過去の個別修正は #267 / #357 / #448)。原因:
preview_mode=1)がフォームをtarget="prevWin"で送信した後、target="main"を設定して戻していた。シェル化でmainフレームはなくなったため、以後の保存・テンプレート変更はshell.jsを経由しないネイティブ送信になる(結果も別タブに開く)csrf_tokenがない。旧実装は DOMContentLoaded 時にしか注入せず、form.submit()/jQuery(form).submit()は submit イベントを発火しないので送信時の補完も働かなかったtarget付きフォーム(バックアップ a=93 など)もトークンが欠落しうる。jQuery はajaxSetupのbeforeSendで付与していたが、呼び出し側がbeforeSendを指定すると上書きされる画面ごとの修正では別経路で再発するため、共通層で保証する形にしました。
How
csrf.jsが以下を担います(トークンは従来どおり<meta name="csrf-token">から取得)。requestSubmitcsrf_tokenを補う(shell.jsが FormData を作る前)form.submit()/jQuery(form).submit()HTMLFormElement.prototype.submitをラップして補う(target付き・chromeless のネイティブ送信を含む)X-CSRF-Tokenヘッダを付与。呼び出し側で付けている場合は重複させないfetchX-CSRF-TOKENと共存)shell.jsはform.submitを退避して使うため、csrf.jsを先に読み込むTest
ローカル Docker 環境で Playwright(headless Chromium)を使い、全 POST の
csrf_tokenフィールド /X-CSRF-Tokenヘッダの有無とレスポンスを記録して確認しました。修正前(再現): SPA 遷移でリソース編集 → プレビュー → 保存 で 403。システムログは報告と完全に一致しました。
修正後:
targetは残らず、別タブも開かないtarget="main"を強制して保存)beforeSendを独自指定した jQuery POST / 生 fetch /Requestの fetch / 生 XHR / 独自X-CSRF-TOKEN付き jQuerytarget="fileDownloader")chromeless=1)でプレビュー → 保存php -l manager/actions/header.inc.php/node --check manager/media/script/csrf.js: OK互換性・影響
header.inc.phpを経由せず完全な HTML を出力するモジュールは対象外。従来どおりフォームにcsrfTokenField()を出力してくださいwindow.fetchとXMLHttpRequest.prototypeをラップします。同一オリジンの非 GET リクエストにヘッダを 1 つ追加するだけです🤖 Generated with Claude Code
https://claude.ai/code/session_01VqS5g34F8nY9QhMKxX6VGV