概要:突然出た「返答が正しい JSON レスポンスではありません。」エラー
WordPressのブロックエディターで投稿を保存しようとしたところ、突然、次のエラーが表示されました。
更新に失敗しました。 返答が正しい JSON レスポンスではありません。
それまで特に設定変更はしておらず、ひたすらブログを書き続けていただけでした。
本記事では、実際に私の環境で起きた
- 原因
- 切り分けの手順
- 最終的な解決方法
- なぜ特定のキーワードがセキュリティ的に問題になりうるのか
を整理してまとめます。
結論:タイトルとURLに特定キーワード(今回は eval)を入れたことが原因
結論から申し上げます。
今回のケースでは、
- 記事タイトル
「Pythonのeval()関数:文字列をプログラムとして実行する方法とセキュリティリスク」 - パーマリンク(スラッグ)
/python-eval-function-dynamic-execution-security
という形で、タイトルとURLに「eval」という文字列を含めたことで、
サーバー側のセキュリティ機能(WAF など)が「不審なリクエスト」と判断し、
最終的に WordPress 側で
更新に失敗しました。 返答が正しい JSON レスポンスではありません。
というエラーになっていました。
実際に、
- タイトルを単純な「aaaa」
- URLスラッグを「aaaaa」
のような文字列に変えると、同じ本文でも問題なく更新できました。
さらに検証を進めたところ、
- タイトルとスラッグから「eval」という文字列を取り除くとエラーが出ない
- 本文中に「eval」と書く分には問題なく保存できる
という挙動であることがわかり、「タイトルとURLに含まれるキーワード」が原因と判断しました。
実際に行った切り分け手順
原因が分からない段階では、一般的に言われている対処を一通り試しました。
以下は、実際に行ったことです。
- 時間を置いてから再度試す
一日待ってから再度 WordPress にログインし、投稿の更新を試しました。 - ログインし直す
管理画面から一度ログアウトし、再度ログインしてから更新を試しました。 - PC の再起動
クライアント側の一時的な不調の可能性を疑い、PC を再起動しました。 - REST API の動作確認
ブラウザでhttps://自分のドメイン/wp-json/
に直接アクセスし、JSON が返ってくることを確認しました。 - ブラウザを変えてテスト
普段使っているブラウザとは別のブラウザに切り替えて、同じ記事の更新を試しました。 - ブラウザのキャッシュ・Cookie・サイトデータを削除
キャッシュや Cookie が悪さをしている可能性を排除するため、ブラウザ側のデータを削除してから更新を試しました。 - セキュリティ系プラグインの一時停止
以下のようなセキュリティ関連プラグインを順番に停止し、その都度更新を試しました。- XO Security
- BBQ Firewall
- SAKURA RS WP SSL
- サイトヘルスステータスを確認
WordPress の「サイトヘルス」で、- 「REST API で予期しない結果が発生しました」
- エンドポイント
wp-json/wp/v2/types/post?context=editに対して 403 Forbidden
といった情報が表示されていることを確認しました。
- タイトルと本文を単純な文字列にしてテスト
- タイトルを「aaaa」
- 本文を「aaaaa」
- スラッグを「aaaaa」
としたテスト投稿を作成したところ、この場合は正常に保存・更新できました。
- 少しずつ元のタイトルに近づけて再検証
元のタイトルから単語を足したり引いたりしながら、どの単語でエラーが出るのかを確認し、
最終的に「eval」という文字列を含めたときだけエラーが再現することを突き止めました。
このように、
「キャッシュやプラグインではなさそうだ」
「タイトルやスラッグの文字列が怪しい」
というところまで切り分けていった結果、原因にたどり着けました。
なぜタイトルやURLのキーワードがブロック対象になるのか
多くのレンタルサーバー環境では、WAF(Web Application Firewall)が有効化されています。
WAF は、リクエストの内容を検査し、不正アクセスのパターンを検出して自動的にブロックします。
WAF が検知対象とする典型的な攻撃には、次のようなものがあります。
- SQL インジェクション
- コマンドインジェクション
- クロスサイトスクリプティング(XSS)
- リモートコード実行(RCE)につながるコード注入 など
このとき、WAF は単に URL パスだけではなく、
- クエリ文字列
- POST データ
- JSON ボディ
- HTTP ヘッダー
なども含め、リクエスト全体に怪しいキーワードやパターンが含まれていないかをチェックします。
WordPress のブロックエディターは、投稿の保存に REST API を利用します。
その際に送信する JSON の中に、タイトルやスラッグの文字列がそのまま入ります。
今回のケースでは、
- タイトルとスラッグの中に「eval」という文字列が含まれていた
- その JSON を検査した WAF が、危険なコード実行に関連するキーワードと判断してブロックした
- WordPress 側から見ると、REST API から正常な JSON レスポンスが返らず、
「返答が正しい JSON レスポンスではありません」というエラーになった
と考えられます。
eval 関数とは何か(Python の例)
ここで、記事の本来のテーマでもあった「eval」について簡単に整理します。
Python の eval() 関数は、
文字列として与えられた式を、Python のコードとして評価し、その結果を返す関数
です。
簡単な使用例
expression = "2 + 3 * 4"
result = eval(expression)
print(result) # 14 が出力される
このように、文字列を「式」として扱い、その結果を計算してくれます。
ユーザー入力を受け取り、その内容を評価することもできます。
user_input = input("式を入力してください: ")
print(eval(user_input))
一見すると柔軟で便利な関数ですが、ここに大きなセキュリティリスクがあります。
eval が攻撃に悪用される典型例
eval() は、攻撃者からすると「任意コード実行」を行うための強力な入り口になり得ます。
1. コードインジェクション
例えば、Web アプリケーションが次のようなコードを書いていたとします。
from flask import request
user_input = request.args.get("value") # クエリパラメータから入力を取得
result = eval(user_input)
ここで攻撃者が次のような文字列を指定した場合を考えます。
__import__("os").system("rm -rf /")
eval() はこの文字列を Python コードとしてそのまま実行してしまいます。
つまり、サーバー上で任意のコマンドを実行される危険性があるということです。
このような「外部から与えられた文字列を、そのまま eval に渡す」コードは、
完全にコードインジェクションの脆弱性となり、最悪の場合、サーバーの乗っ取りに直結します。
2. リモートコード実行(RCE)
ユーザーの入力が HTTP リクエストとしてサーバーに届き、その値が eval() に渡される構造になっている場合、
攻撃者はブラウザからの操作だけでサーバー上の任意コードを実行できます。
このような問題は「リモートコード実行(Remote Code Execution, RCE)」と呼ばれ、
非常に重大な脆弱性として報告されます。
WAF が「eval」という文字列を警戒する背景には、
こうした RCE 系攻撃を未然に防ぎたい、という意図があります。
3. JavaScript の eval と XSS など
JavaScript にも eval() が存在し、こちらも長年問題視されてきました。
- ユーザー入力を
eval()に渡してしまうことで XSS を引き起こす - 悪意あるスクリプトが難読化のために
eval()を多用する
といった事情から、セキュリティ製品やブラウザの保護機能の多くがeval という文字列に敏感に反応するようになっています。
今回の WordPress のケースでは、こうした背景を踏まえて、
- サーバー側の WAF が「eval」という文字列を含むリクエストを警戒
- その一環で REST API のリクエストがブロックされた
という形になったと考えられます。
同じエラーで困っている方へのチェックポイント
同じエラーメッセージでも、原因は環境によって異なります。
しかし、今回の経験から、次のような順番で確認すると原因特定がしやすいと感じました。
- まずはブラウザ側を疑う
- キャッシュ削除
- 別ブラウザ、別端末での再現確認
- WordPress セッションのリセット
- 一度ログアウトして再ログイン
- REST API 自体の動作確認
https://ドメイン/wp-json/へアクセスし、エラーが出ていないか確認
- サイトヘルスステータスを見る
- 「REST API で予期しない結果が発生しました」などの情報を確認
- セキュリティ系プラグインや WAF の影響を確認
- プラグインを一時停止してテスト
- レンタルサーバーの管理画面に WAF 設定があれば、ログを確認
- タイトル・スラッグの文字列を単純なものに変えてテスト
- タイトルを「test」
- スラッグを「test-post」
といった、きわめて単純な文字列にして保存できるか確認
- 危険キーワードの有無を確認
- eval
- union select
- drop table
など、攻撃に使われやすい文字列が含まれていないかを確認
こうした手順を踏むことで、
- プラグイン由来なのか
- サーバー側のセキュリティ由来なのか
- 文字列パターン由来なのか
といった切り分けがしやすくなります。
今回の最終的な運用方針
今回の事象を踏まえ、私の運用方針としては次のように整理しました。
- 記事本文では、技術解説として
evalという単語を使用してよい - ただし、
- 記事タイトル
- パーマリンク(スラッグ)
に「eval」という文字列を入れるのは避ける
- スラッグは、意味を保ちつつ、別の英単語に置き換える
- 例:
/python-dynamic-execution-security/のようにする
- 例:
サーバー側の WAF 設定を細かく調整できる環境であれば、
特定パスや特定ルールの除外設定を行うという選択肢もありますが、
一般的なレンタルサーバーでは自由度が限られることも多いため、
「タイトルとURL側で危険キーワードを避ける」というシンプルな対策を採用しました。
まとめ
最後に、本記事の内容を簡潔にまとめます。
- WordPress で「更新に失敗しました。返答が正しい JSON レスポンスではありません。」と表示される場合、
原因は一つではなく、ブラウザやプラグイン、REST API、サーバー設定など多岐にわたります。 - 今回のケースでは、
- 記事タイトルとURLスラッグに「eval」というキーワードを含めた結果、
- サーバー側の WAF が不正なリクエストと判断してブロックし、
- WordPress 側で JSON レスポンスエラーが発生していました。
- ブラウザのキャッシュ削除、再ログイン、PC再起動、プラグイン無効化などを一通り試した上で、
「タイトルやスラッグを単純な文字列にすると保存できる」ことから、
文字列パターンが原因であると切り分けることができました。 eval()は、文字列をコードとして実行できる強力な関数であり、
コードインジェクションやリモートコード実行に悪用される代表的な要素です。
そのため、WAF などのセキュリティ製品が「eval」というキーワードを警戒している可能性があります。- 同じエラーで悩んでいる場合は、一般的な対処に加えて、
「タイトルとスラッグに、セキュリティ的に怪しいキーワードが含まれていないか」
を確認してみることをおすすめします。
以上の内容が、同様のエラーでお困りの方の参考になれば幸いです。
