WordPressでユーザーに編集権限を与える際に気を付けること

WordPressで求人サイトなどのBtoCのマッチングサイトを作る場合、企業をユーザー登録して特定の投稿タイプの編集権限を与え、管理画面から情報を登録してもらうケースがあります。

権限は「User Role Editor」を使うと簡単に管理することができますが、ユーザーが入力するデータの扱いに関しては注意が必要です。
意図しないデータによって表示が崩れたり、悪意のあるユーザーによってプログラムが正しく動作しなくなることもあります。

この記事では、この問題を解決する方法を、投稿タイトルを例に紹介します。

【前提】the_title関数はエスケープしていない

the_permalink関数やthe_title_attribute関数と違い、the_title関数はエスケープ処理がされていません。

例えば、Classic Editorで投稿タイトルを「<b>意図</b></div>しないデータ<script>alert(true)</script>」にすると、JavaScriptが実行されてダイアログが表示され、HTMLの構文エラーも発生します。

これを防ぐためには、2つの処理をします。

出力時のエスケープ

ユーザーが入力したデータは、出力時にエスケープしましょう。WordPressにはHTML用のエスケープ関数が用意されています。

the_titleフィルターフックに関数を登録して、投稿タイプがjobの時はesc_html関数を実行します。

add_filter( 'the_title', function( $post_title, $post_id ) {
  if ( get_post_type($post_id) === 'job' ) {
    return esc_html( $post_title );
  }
  return $post_title;
}, 10, 2);

データベースに保存する前のサニタイズ

そもそもデータベースに保存する前に、データを無害化(サニタイズ)してしまいましょう。

wp_insert_post_dataフィルターフックに関数を登録して、sanitize_text_field関数を実行します。

add_filter( 'wp_insert_post_data', function( $data, $postarr, $unsanitized_postarr ) {
  if ( $data['post_type'] === 'job' ) {
    $data['post_title'] = sanitize_text_field($data['post_title']);
  }
  return $data;
}, 10, 3);

まとめ

以上で投稿タイトルの問題は解決されました。
投稿を表示するとタグが文字として表示され、投稿を更新するとタグが除去されることが確認できます。

コメント