2026年11月6日
2026年11月6日
WordPressのSVGアップロードを安全に有効化する方法【セキュリティ対策付き】
はじめに
WordPressはデフォルトでSVGファイルのアップロードを禁止しています。SVGはXMLベースのフォーマットのため、悪意のあるスクリプトを埋め込める危険性があるからです。しかし適切なサニタイズ処理を実装すれば、安全にSVGを活用できます。本記事では、セキュリティを確保しながらSVGアップロードを有効化する完全な手順を解説します。
症状・原因
- メディアライブラリにSVGをアップロードしようとすると「このファイルタイプは許可されていません」エラーが表示される
upload_mimesフィルターでSVGを追加しても、WordPressのセキュリティチェックで弾かれる- SVGをアップロードできてもメディアライブラリでサムネイルが表示されない
解決手順
ステップ1:upload_mimesとwp_check_filetype_and_extでSVGを許可する
<?php
// functions.php または カスタムプラグインに追加
// SVGのMIMEタイプをアップロード許可リストに追加
add_filter( 'upload_mimes', 'allow_svg_uploads' );
function allow_svg_uploads( $mimes ) {
// 管理者のみSVGアップロードを許可(セキュリティのため)
if ( current_user_can( 'manage_options' ) ) {
$mimes['svg'] = 'image/svg+xml';
$mimes['svgz'] = 'image/svg+xml';
}
return $mimes;
}
// WordPress 4.7.1以降のセキュリティチェックをバイパス
add_filter( 'wp_check_filetype_and_ext', 'fix_svg_filetype_check', 10, 4 );
function fix_svg_filetype_check( $data, $file, $filename, $mimes ) {
// SVGファイルの拡張子チェックを修正
$filetype = wp_check_filetype( $filename, $mimes );
if ( 'svg' === $filetype['ext'] || 'svgz' === $filetype['ext'] ) {
$data['ext'] = $filetype['ext'];
$data['type'] = $filetype['type'];
}
return $data;
}
ステップ2:ComposerでSVGサニタイズライブラリを導入する
# WordPressルートまたはプラグインディレクトリで実行
cd /var/www/html/wp-content/plugins/my-plugin
# enshrined/svg-sanitize ライブラリをインストール
composer require enshrined/svg-sanitize
# autoloadファイルの確認
ls vendor/enshrined/svg-sanitize/src/
<?php
// プラグインのメインファイルでComposerオートロードを読み込む
if ( file_exists( __DIR__ . '/vendor/autoload.php' ) ) {
require_once __DIR__ . '/vendor/autoload.php';
}
ステップ3:wp_handle_uploadフィルターでアップロード時にサニタイズする
<?php
use enshrined\svgSanitize\Sanitizer;
// アップロード処理のフィルターでSVGをサニタイズ
add_filter( 'wp_handle_upload', 'sanitize_svg_on_upload' );
function sanitize_svg_on_upload( $upload ) {
// SVGファイル以外はスキップ
if ( 'image/svg+xml' !== $upload['type'] ) {
return $upload;
}
// SVGサニタイザーを初期化
$sanitizer = new Sanitizer();
// XSSスクリプトや危険な属性を除去
$sanitizer->removeRemoteReferences( true );
// ファイルの内容を読み込んでサニタイズ
$dirty_svg = file_get_contents( $upload['file'] );
$clean_svg = $sanitizer->sanitize( $dirty_svg );
if ( false === $clean_svg ) {
// サニタイズ失敗時はファイルを削除してエラーを返す
unlink( $upload['file'] );
return new WP_Error( 'svg_sanitize_failed', 'SVGファイルのサニタイズに失敗しました。' );
}
// サニタイズ済みの内容でファイルを上書き保存
file_put_contents( $upload['file'], $clean_svg );
return $upload;
}
ステップ4:メディアライブラリでSVGプレビューを表示する
<?php
// 管理画面でSVGのサムネイル表示を有効化
add_action( 'admin_head', 'display_svg_in_media_library' );
function display_svg_in_media_library() {
// メディアライブラリ画面のみ適用
$screen = get_current_screen();
if ( ! $screen || 'upload' !== $screen->id ) {
return;
}
?>
<style>
/* メディアライブラリのSVGサムネイル表示を修正 */
.media-icon img[src$=".svg"],
img[src$=".svg"].attachment-post-thumbnail {
width: 100% !important;
height: auto !important;
}
/* SVGのアイコン表示をグリッドビューで修正 */
.attachment .thumbnail img[src$=".svg"] {
width: 100%;
object-fit: contain;
}
</style>
<?php
}
// メディアライブラリのAJAXレスポンスにSVGのwidthとheightを追加
add_filter( 'wp_prepare_attachment_for_js', 'add_svg_dimensions', 10, 3 );
function add_svg_dimensions( $response, $attachment, $meta ) {
if ( 'image/svg+xml' === $response['mime'] ) {
// SVGからviewBox属性を読み取って寸法を取得
$svg = simplexml_load_file( get_attached_file( $attachment->ID ) );
if ( $svg && isset( $svg['viewBox'] ) ) {
$parts = explode( ' ', $svg['viewBox'] );
if ( count( $parts ) === 4 ) {
$response['width'] = intval( $parts[2] );
$response['height'] = intval( $parts[3] );
}
}
}
return $response;
}
ステップ5:テンプレートでのSVG表示(imgタグ vs インラインSVG)
<?php
// 方法1: imgタグでの表示(CSSで制御可能、JSアクセス不可)
function display_svg_as_img( $attachment_id ) {
$svg_url = wp_get_attachment_url( $attachment_id );
// altテキストをメディアライブラリから取得
$alt_text = get_post_meta( $attachment_id, '_wp_attachment_image_alt', true );
echo '<img src="' . esc_url( $svg_url ) . '" alt="' . esc_attr( $alt_text ) . '" class="svg-image">';
}
// 方法2: インラインSVGとして展開(CSS/JSで各要素を操作可能)
function display_inline_svg( $attachment_id ) {
$svg_path = get_attached_file( $attachment_id );
// ファイルの存在確認
if ( ! file_exists( $svg_path ) ) {
return;
}
// SVGの内容を読み込んで直接出力
$svg_content = file_get_contents( $svg_path );
// PHPタグやスクリプトが残っていないか最終確認
$svg_content = preg_replace( '/<script[\s\S]*?<\/script>/i', '', $svg_content );
$svg_content = preg_replace( '/on\w+="[^"]*"/i', '', $svg_content );
// クラスを付与してスタイル制御しやすくする
$svg_content = str_replace( '<svg', '<svg class="inline-svg"', $svg_content );
echo $svg_content;
}
// テンプレートでの使用例
// display_svg_as_img( get_post_thumbnail_id() );
// display_inline_svg( 123 ); // SVGのメディアID
注意事項
- 管理者限定アップロード:
current_user_can('manage_options')で管理者のみSVGアップロードを許可し、一般ユーザーには制限してください - サニタイズは必須: SVGはJavaScriptやPHPコードを埋め込める危険性があるため、
enshrined/svg-sanitizeによるサニタイズを必ず実装してください - CDNキャッシュ: SVGをCloudflareなどのCDN経由で配信する場合、Content-Typeヘッダーが
image/svg+xmlになっているか確認してください - HTTPSの推奨: SVGのインライン表示はHTTPS環境でのみ安全に動作します
まとめ
WordPressのSVGアップロードはupload_mimesとwp_check_filetype_and_extフィルターで有効化し、enshrined/svg-sanitizeライブラリで安全性を担保することで実用的に運用できます。インラインSVGはアニメーションやCSS制御に優れますが、セキュリティ面ではimgタグ表示のほうが安全です。関連記事:WordPressのメディアライブラリを最適化する方法