brand logo

ドキュメント

useHeadSafe

ユーザー入力を用いてヘッドデータを提供する推奨方法。

useHeadSafe コンポーザブルは、useHead コンポーザブルのラッパーであり、安全な値のみを許可するように入力を制限します。

使用法

useHead と同じ値をすべて渡すことができます。

useHeadSafe({
  script: [
    { id: 'xss-script', innerHTML: 'alert("xss")' }
  ],
  meta: [
    { 'http-equiv': 'refresh', content: '0;javascript:alert(1)' }
  ]
})
// 安全に生成されます
// <script id="xss-script"></script>
// <meta content="0;javascript:alert(1)">
こちらも参照 unhead.unjs.io > docs > typescript > head > api > composables > use-head-safe

useHeadSafe(input: MaybeComputedRef<HeadSafe>): void

許可される値のリストは以下の通りです:

const WhitelistAttributes = {
  htmlAttrs: ['class', 'style', 'lang', 'dir'],
  bodyAttrs: ['class', 'style'],
  meta: ['name', 'property', 'charset', 'content', 'media'],
  noscript: ['textContent'],
  style: ['media', 'textContent', 'nonce', 'title', 'blocking'],
  script: ['type', 'textContent', 'nonce', 'blocking'],
  link: ['color', 'crossorigin', 'fetchpriority', 'href', 'hreflang', 'imagesrcset', 'imagesizes', 'integrity', 'media', 'referrerpolicy', 'rel', 'sizes', 'type'],
}

詳細な型については @unhead/vue を参照してください。

tips

このセクションは公式ドキュメントの翻訳ではなく、本サイト独自の補足記事です。

はじめに:なぜ useHeadSafe が重要なのか

Nuxt アプリケーションでページのタイトルやメタタグ、スクリプトなどのヘッド情報を動的に操作することはよくあります。しかし、ユーザー入力や外部データをそのままヘッドに反映すると、クロスサイトスクリプティング(XSS)などのセキュリティリスクが生じる可能性があります。useHeadSafe は、こうしたリスクを軽減しつつ、柔軟にヘッド情報を管理できるコンポーザブルです。

本記事では、useHeadSafe の特徴や使いどころ、実務での具体的なユースケース、そして注意すべきポイントを丁寧に解説します。Nuxt で安全かつ効率的にヘッド情報を扱いたい開発者の方に役立つ内容です。

まず結論:useHeadSafe のポイント

  • 安全な属性のみを許可し、XSS攻撃のリスクを低減する
  • useHead と同じインターフェースで使えるため、学習コストが低い
  • ユーザー入力や外部APIからのデータをヘッドに反映する際に特に有効
  • 許可される属性はホワイトリストで厳密に管理されている
  • すべてのヘッド要素(meta、script、link など)に対応している
  • ただし、完全なセキュリティ保証ではないため、入力のサニタイズも併用推奨

いつ使うべきか、使わない方がよいケース

使うべきケース

  • ユーザーが入力した値をページタイトルやメタタグに反映したい場合
  • 外部APIから取得したデータをヘッドに動的にセットする必要がある場合
  • セキュリティリスクを抑えつつ柔軟にヘッド情報を操作したい場合
  • SSR(サーバーサイドレンダリング)環境で安全にヘッドを管理したい場合

使わない方がよいケース

  • 静的に決まったヘッド情報のみを設定する場合(useHead で十分)
  • 入力値の安全性が完全に保証されている場合(ただし推奨はしない)
  • ヘッド情報の細かい制御よりもパフォーマンス最適化が最優先の場合(過剰な安全対策は不要な負荷になることも)

実務でよくあるユースケースとサンプルコード

1. ユーザー入力をタイトルに反映する

ユーザーがフォームで入力した文字列をページタイトルに反映したいが、スクリプトタグなどの悪意あるコードは排除したい場合。

import { ref } from 'vue'
import { useHeadSafe } from 'unhead/vue'

const userInput = ref('ユーザーの入力')

useHeadSafe({
  title: userInput.value
})

このように useHeadSafe を使うと、許可されていない属性やスクリプトは自動的に除外されるため安全です。

2. 外部APIのメタ情報を動的にセットする

ブログ記事のメタ情報をAPIから取得し、SEO対策として動的に設定するケース。

import { ref, onMounted } from 'vue'
import { useHeadSafe } from 'unhead/vue'

const metaInfo = ref({ title: '', description: '' })

onMounted(async () => {
  const res = await fetch('/api/article-meta')
  metaInfo.value = await res.json()

  useHeadSafe({
    title: metaInfo.value.title,
    meta: [
      { name: 'description', content: metaInfo.value.description }
    ]
  })
})

APIからのデータに悪意あるコードが混入していても、useHeadSafe が安全に処理します。

3. 動的にスクリプトタグを挿入する(制限付き)

広告タグや解析スクリプトを動的に挿入したいが、XSSリスクを抑えたい場合。

useHeadSafe({
  script: [
    {
      id: 'analytics',
      type: 'application/ld+json',
      textContent: JSON.stringify({ '@context': 'https://schema.org' })
    }
  ]
})

textContent 属性のみ許可されているため、innerHTML のような危険な属性は使えません。

よくある落とし穴・注意点

SSR と Hydration の観点

useHeadSafe は SSR でも動作しますが、サーバーとクライアントでヘッドの内容が異なると Hydration エラーの原因になります。動的に変わる値はできるだけ初期レンダリング時に確定させるか、クライアント側でのみ更新する工夫が必要です。

パフォーマンスへの影響

ホワイトリストによる検証処理が入るため、非常に大量のヘッド更新を頻繁に行うとパフォーマンスに影響が出る可能性があります。必要な更新に絞って使いましょう。

完全なXSS防止ではない

useHeadSafe は許可された属性のみを反映することでリスクを減らしますが、ユーザー入力のサニタイズやバリデーションは別途行うべきです。特にスクリプトやスタイルの動的挿入は慎重に扱いましょう。

まとめ

useHeadSafe は Nuxt で安全にヘッド情報を動的に操作するための強力なツールです。ユーザー入力や外部データを扱う際のXSSリスクを軽減しつつ、useHead と同様の使い勝手を提供します。実務ではSEO対策や動的メタ情報の反映に役立ちますが、SSRのHydration問題やパフォーマンス面、そして入力のサニタイズは併せて注意が必要です。安全で快適なNuxt開発のために、ぜひ活用してください。

useHeadSafe はあくまで「安全な属性のみを許可する」仕組みです。ユーザー入力の検証やサニタイズは別途行い、二重の安全対策を心がけましょう。