WordPress「アップロード権限がありません」エラーの直し方
結論: このエラーは iPhone アプリやブラウザ、スクリプト側ではなく、WordPress サーバー側から返されています。最も多い原因は次の 2 つです:(1) Application Password に紐づくユーザーが upload_files capability を持っていない、(2) セキュリティプラグインや WAF が WordPress に届く前に /wp-json/wp/v2/media をブロックしている。ユーザーを Author(または upload_files を含む任意のロール)に昇格させるか、該当のファイアウォールルールから media エンドポイントを除外すれば、すぐにアップロードが動きます。
WordPress 6.7 にて 2026 年 6 月 2 日に動作検証済み。
クイック診断:レスポンスから原因を読み取る
何かを変更する前に、クライアントが受け取っている HTTP レスポンスを確認してください。ステータスコードとエラーボディの組み合わせで、根本原因がほぼ特定できます。
| HTTP status | Error code | 想定される原因 | 最初に試すこと |
|---|---|---|---|
| 403 | rest_cannot_create | ユーザーロールに upload_files がない | ロールを Author 以上へ変更(Root Cause 1 参照) |
| 401 | rest_invalid_authentication | Application Password が誤っているか revoke 済み | Application Password を再発行(Root Cause 4 参照) |
| 403 | HTML ページ(JSON ではない) | セキュリティプラグインまたは WAF がブロック | Wordfence/iThemes/Cloudflare のイベントログを確認 |
| 503 / timeout | (ボディなし) | WAF やレートリミッタが接続を破棄 | Cloudflare またはオリジン側ファイアウォールのログを確認 |
| 200 | HTML ページ(JSON ではない) | プラグインで WP REST API が無効化されている | 「Disable REST API」系プラグインを無効化 |
このエラーがクライアントに届くまで
クライアントが WordPress に写真をアップロードするとき、リクエストは /wp-json/wp/v2/media への POST として送られます。リクエストにはユーザー名と Application Password を含む Authorization ヘッダーが付与されます。Application Password は Users → Profile → Application Passwords で発行するトークンで、WordPress 5.6 以降のコア機能です(公式インテグレーションガイド)。
WordPress コアはファイルを受け付ける前に permission check を実行します。WP_REST_Attachments_Controller::create_item_permissions_check() 内の該当ロジックは次のとおりです:
if ( ! current_user_can( 'upload_files' ) ) {
return new WP_Error(
'rest_cannot_create',
__( 'Sorry, you are not allowed to upload media on this site.' ),
array( 'status' => rest_authorization_required_code() )
);
} Application Password に紐づくユーザーが upload_files capability を持っていない場合、WordPress は HTTP 403 を返し、JSON ボディに "code": "rest_cannot_create" を含めます。クライアントはこのレスポンスを受け取り、「アップロード権限がありません」として表示します。
つまりこのメッセージは文字通りで、WordPress 自身が「このユーザーにはアップロードを許可していない」と言っています。次に必要なのはなぜそう判断されたのかを突き止めることです。ロール capability の一覧は 公式の Roles and Capabilities ページに掲載されています。
Root Cause 1:ユーザーロールに upload_files がない
これは SnapPress のサポートケースで最も多く観測される原因です。WordPress のデフォルトロールは 5 つで、メディアアップロードができるのは一部だけです:
| Role | メディアアップロード可否 |
|---|---|
| Administrator | 可 |
| Editor | 可 |
| Author | 可 |
| Contributor | 不可 |
| Subscriber | 不可 |
Application Password が Contributor または Subscriber に属している場合、認証自体は成功してもアップロードは必ず失敗します(パスワードは正しいが、その権限では足りないという状態です)。
ロールを確認する方法
https://your-site.example/wp-admin/で WordPress 管理画面にログインします。- Users → All Users を開きます。
- クライアントアプリに登録した Application Password の持ち主を探します。
- Role 列を確認します。
ロールが Contributor、Subscriber、あるいは upload_files を含まないカスタムロールであれば、原因はそれです。
修正方法(最小権限を優先)
最も安全な修正は、ユーザーを Author に昇格させることです。Author は upload_files を持ち、自身の投稿を作成・公開できる最小のデフォルトロールです。他ユーザーやプラグイン、設定の管理はできないため、アップロード用途だけが必要な場合の推奨ロールです。
他の Author の投稿を編集・公開する必要があれば Editor、サイト全体の管理が本当に必要な場合(たとえば自分一人で運用している自己所有サイト)にのみ Administrator へ昇格してください。ロール変更後は、正しくなったユーザーで新しい Application Password を発行し、クライアントアプリを更新してください。新規発行は厳密には必須ではありませんが、「古い認証情報が残っている」という仮説を消すために推奨されます。
カスタムロールを使っている場合
サイトで Members や User Role Editor のようなロールプラグインを使っている場合、ロール名はデフォルトと一致しないことがあります。ロールエディタを開き、対象ユーザーに割り当てられたロールを探し、upload_files のチェックボックスが有効になっているか確認してください。保存して再試行します。アップロードがある日突然動かなくなった場合、プラグイン更新によるカスタムロールの権限退行がいちばん怪しいので、ここから調べてください。複数ユーザーで運用するサイトでは、upload_files と最小限の投稿系 capability だけを持つ専用のカスタムロールを作るのが最もきれいです。
Root Cause 2:セキュリティプラグインが REST API をブロックしている
ユーザーロールが upload_files を含んでいるのにアップロードが失敗する場合、次に疑うのは WordPress コアが処理する前に REST API リクエストを止めるセキュリティプラグインです。代表的なものは:
- Wordfence — ファイアウォールルールが普通でない Authorization ヘッダーにマッチすることがあり、Rate Limiting が REST トラフィックをスロットルすることもあります。
- iThemes Security / Solid Security — REST API ハードニングのオプションにより、ブラウザのログイン済みセッション以外からの
/wp-json/wp/v2/*を拒否することがあります。 - Disable REST API — 名前のとおり、デフォルトで全 REST エンドポイントをブロックします。アプリからアップロードするには
/wp/v2/mediaをホワイトリストする必要があります。 - SecuPress、Shield Security なども同等の設定を持っています。
これらにブロックされると、プラグインが返す 403 が WordPress 本体のエラーに似ているため、「アップロード権限がない」という同じ症状に見えます。違いは、コアの current_user_can() チェックがそもそも走っていないことです。
Wordfence の確認ポイント
確認すべき設定は 2 つあります。Wordfence → All Options → Firewall Options を開きます:
- Brute Force Protection:厳しい lockout 設定だと、1 回のリトライで Application Password が一気にロックされることがあります。
- Rate Limiting:「If anyone's requests exceed...」のしきい値は REST トラフィックにも適用されます。失敗したアップロードをリトライするモバイルアプリがこれに引っかかることがあります。
Wordfence を疑う場合、Wordfence → Tools → Live Traffic を開いた状態でクライアントからアップロードをトリガーしてください。リクエストがブロックされていれば、発火したルールがログエントリに表示されます。ファイアウォールの全リファレンスは wordfence.com/help/firewall/ にあります。
iThemes Security / Solid Security の確認ポイント
Solid Security はリリースごとに REST API ハードニングの場所を移動させてきました。最近のバージョンでは Security → Settings → Advanced → WordPress Tweaks 配下に REST API オプションがあります(古いビルドでは Tools 配下にありました)。重要なのは次の 2 つの状態です:
- Default(REST API enabled) — アプリからのアップロードに必要な状態。
- Restricted — REST エンドポイントをログイン済みブラウザセッションに限定します。Application Password のリクエストはここで失敗します。
可能なら Default に戻す、もしくは /wp/v2/media を明示的にホワイトリストしてください。ラベル名はバージョンによって異なるので、ご利用バージョンの Solid Security ドキュメントを参照してください。
切り分けの手順
怪しいプラグインを 1 つずつ無効化し、その都度アップロードを試します。無効化した瞬間にアップロードが通るようになったものが犯人です。特定できたら、その中で REST API をブロックしている具体的な設定を見つけ、/wp-json/wp/v2/media をそこから除外してください。上記のプラグインはいずれも、メニューの場所はバージョンごとに違うものの、エンドポイント単位の除外設定をなんらかの形でサポートしています。
Root Cause 3:WAF がリクエストをブロックしている
サイトが WAF(Cloudflare WAF、Sucuri、AWS WAF、BunkerWeb など)の背後にある場合、アップロードリクエストが WordPress サーバーに到達する前に WAF が拒否することがあります。特に Cloudflare の WAF managed rules には、大きな multipart POST ボディや変則的な Content-Type の組み合わせをターゲットにするルールがあり、メディアアップロードはその両方を使います。ルールカタログは Cloudflare の WAF ドキュメントを参照してください。
症状はさまざまですが、典型的には次のいずれかです:
- レスポンスボディに Cloudflare のエラーページが入った HTTP 403。
- HTTP 503 もしくはタイムアウト(ボディなし)。
- JSON ではなく HTML が返る HTTP 200。
Cloudflare 向けの絞り込んだ修正
Cloudflare の managed rules を一括で無効化しないでください。代わりに、実際に発火しているルールを特定します:
- Cloudflare ダッシュボードで Security → Events(旧 Firewall Events)を開きます。
- クライアントから失敗するアップロードをトリガーします。
- ホスト名または URI
/wp-json/wp/v2/mediaでイベントを絞り込みます。ブロックしたルールが ruleset ID と rule ID 付きで表示されます。 - Security → WAF → Custom Rules でカスタムルールを作成し、特定したそのルールだけをアップロードエンドポイント向けに Skip させます:
(http.request.uri.path eq "/wp-json/wp/v2/media") and (http.request.method eq "POST") アクションは「Skip」とし、対象は特定した ruleset/rule に限定してください(managed challenge をまとめて Skip しない)。優先度は「Block」系ルールより上に置きます。これで /wp-json/ の残りに対する保護は維持したまま、正規のメディアアップロードだけを通せます。
Root Cause 4:認証失敗または Application Password が revoke されている
Application Password には期限切れフィールドがありません。発行後は手動で revoke するまで有効です。したがってこのケースの症状は通常、403 の権限エラーではなく HTTP 401 と rest_invalid_authentication です。とはいえ他のどれにも当てはまらないときは確認の価値があります:
- WordPress 管理画面 → Users → Profile → Application Passwords を開きます。
- クライアントアプリに登録したパスワードが今もリストにあるか確認します。
- 削除されていれば(手動、セキュリティプラグイン、またはパスワード変更イベントなどで)、新しく発行してクライアントを更新します。
- サイトが HTTPS で到達可能か確認します。WordPress はセキュリティ上、プレーン HTTP では Authorization ヘッダーを剥がします。http と https が混在していると断続的な 401 を引き起こします。
- セキュリティプラグインやカスタムコードが
wp_is_application_passwords_availableフィルタで Application Passwords を無効化していないことを確認します。
セキュリティプラグインの中には、パスワード変更・ロール変更・不審な挙動などのイベントで Application Password を自動的に revoke するものがあります。最近ロールを変更したばかりであれば、それだけで既存のパスワードが revoke されている可能性があります。再発行は 1 分で終わります。
コマンドラインで修正を検証する
修正を適用したら、クライアントアプリを使わずにアップロードが動くか検証できます。curl が使える環境から次を実行します:
curl -u 'your-username:your-application-password' \
-X POST \
-H 'Content-Disposition: attachment; filename=test.jpg' \
-H 'Content-Type: image/jpeg' \
--data-binary @test.jpg \
https://your-site.example/wp-json/wp/v2/media アップロードが成功すれば、HTTP 201 と、新しいメディアアイテムの id、source_url、media_details を含む JSON ボディが返ります。それ以外は記事冒頭の診断表に戻ってください。レスポンスボディがどの行に該当するかをほぼ教えてくれます。
curl が使えなければ、Postman など Basic 認証と multipart form data をサポートする HTTP クライアントでも同じテストが可能です。エンドポイント、認証情報、期待されるレスポンスはまったく同じです。
モバイルアプリ側ではこの問題を直せない理由
アップロードの不具合はアプリ側のバグだと考えたくなります。アプリが目に見える部分だからです。しかし WordPress REST API はあらゆるクライアント(ブラウザ、iOS アプリ、Zapier、コマンドライン)に対する唯一の権威ある gatekeeper です。アプリの役割は、妥当な形式のリクエストを正しい認証情報で送り、レスポンスを表示することです。WordPress が「アップロード権限なし」と言う以上、アプリを変えてもその答えは変わりません。修正は必ず WordPress 側(ロール、プラグイン設定、WAF ルール、Application Password)で行います。
これは設計上の意図であり、REST API モデルの強みでもあります。同じチェックが、スマホアプリでもデスクトップクライアントでも自作スクリプトでもサイトを保護してくれます。
まとめチェックリスト
- 実際のレスポンスから HTTP ステータスコードとエラーコードを読み取り、冒頭の診断表に照らす。
- WordPress ユーザーロールを確認する。デフォルトロールの中では
upload_filesを含むのは Author 以上。 - ロールが正しければ、セキュリティプラグインを 1 つずつ無効化してアップロードを再試行する。
- 原因のプラグインがなければ、WAF のイベントログを確認し、発火している具体的なルールに対してのみ
/wp-json/wp/v2/mediaの例外を追加する。 - Application Password がユーザープロフィールに残っていること、サイトが HTTPS であることを確認し、必要なら再発行する。
- クライアントアプリに戻る前に curl で end-to-end の動作確認をする。
この順で進めれば、SnapPress に寄せられる「アップロード権限なし」の報告はほとんど解消します。エラーメッセージは正しく仕事をしてくれています。あとはその文脈を読み解けば対処できる、それだけの問題です。
Frequently Asked Questions
- WordPress が iPhone アプリに『アップロード権限がありません』を返すのはなぜですか?
- REST API エンドポイント
/wp-json/wp/v2/mediaは、WordPress ユーザーがupload_filescapability を保持していることを要求します。Subscriber と Contributor ロールはこの capability を持ちません。iPhone アプリがこれらのロールのユーザーで認証している場合、アップロードを試みるたびに HTTP 403 がエラーコードrest_cannot_createとともに返されます。ユーザーを Author(またはupload_filesを含む任意のロール)に昇格させれば解決します。 - サイト管理者なのに『アップロード権限なし』が出ます。何が起きているのですか?
- ユーザーロールが正しい場合、次に疑うべきは REST API をブロックするセキュリティプラグインまたは WAF ルールです。Wordfence、iThemes Security、Solid Security、「Disable REST API」系プラグインにはいずれも、ブラウザ以外からの REST トラフィックを拒否する設定があります。Cloudflare WAF で
/wp-json/を対象としたルールも同じ効果を持ちます。ファイアウォールのイベントログで実際にブロックしているルールを特定し、そのルールだけを/wp-json/wp/v2/mediaに対して除外してください。 - WordPress の Application Password は、紐づくユーザーと同じロール権限を持ちますか?
- はい。Application Password はユーザーごとに発行され、認証されたリクエストはそのユーザーの capability そのままで実行されます。基となるユーザーが Subscriber であれば、Application Password が正常に発行されていてもアップロードはできません。Application Password には期限切れフィールドはなく、手動で revoke するまで有効です。
- ターミナルから
upload_filescapability を確認するには? - curl で
-u username:application-passwordを指定し、小さなテスト画像を/wp-json/wp/v2/mediaに POST します。HTTP 201 と新しいメディア ID を含む JSON が返ればアップロードは動作しています。HTTP 403 で code がrest_cannot_createならロールにupload_filesが不足。HTTP 401 でrest_invalid_authenticationなら Application Password が誤っているか revoke されています。WordPress 形式ではないレスポンスボディ(HTML エラーページや Cloudflare チャレンジ)で HTTP 403 が返る場合は、WordPress に届く前段のフィルタがブロックしています。 - いっそユーザーを Administrator に昇格させてはダメですか?
- 最後の手段として、かつ自分が完全に管理しているサイトでのみにしてください。最小権限の原則では、
upload_filesを持つ最小のロール、つまり Author を与えるべきです。Administrator は、設定・プラグイン・他ユーザーの管理が本当に必要なアカウントのために残しておきます。複数人で運用するサイトでは、upload_filesと最小限の投稿系 capability だけを持つ専用カスタムロールがさらに安全です。