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);
まとめ
以上で投稿タイトルの問題は解決されました。
投稿を表示するとタグが文字として表示され、投稿を更新するとタグが除去されることが確認できます。
コメント