結論(外部CSSのSRI)
外部CSSのSRIとは、CDNなど別オリジンから読み込むスタイルシートの改ざんを、ハッシュ値で検出する仕組みです。link rel="stylesheet" に integrity 属性で期待するハッシュ値(sha256・sha384・sha512)を書き、ブラウザが取得したCSSのハッシュと一致しない場合にそのスタイルシートを適用させません。CSSが改ざんされると、表示の偽装や属性値の外部送信に悪用されうるため、OWASP ASVS 5.0.0 V3.6.1はJavaScriptだけでなくCSSやWebフォントも対象にしています。
この記事のポイント
- 改ざんされたCSSは、偽の電話番号の表示や、属性セレクターを使った入力値の外部送信に悪用されえます。
- 空のintegrityや未対応アルゴリズムだけの値は検証されず、別オリジンでは crossorigin="anonymous" とCORSが必要です。
- ブラウザによって中身が変わるWebフォントサービスのCSSにはSRIを付けられず、自己ホストかCSPで補います。
- セキュリティAIチェッカーは、有効なSRIのない外部CSSが1件でもあれば△、外部CSSがなければ対象外とします(重みは1)。
- 外部CSSが少なく版固定なら、自己ホストに切り替えるのが最も簡単で確実です。
| 診断項目名 | 外部CSSのSRI |
|---|---|
| 項目ID | html.style-sri |
| 分類 | HTML・JavaScript・外部資産 |
| 重大度・配点の重み | 低(low) 重み 1 |
| 関連する標準・ガイドライン | OWASP ASVS 5.0.0 V3.6.1(L3: JavaScriptライブラリ、CSS、Webフォント等の外部ホスト資産は静的・版固定かつSRI付きに限る)/W3C Subresource Integrity/CWE-353(完全性チェックの欠如) |
外部CSSのSRIとは
外部CSSのSRIとは、外部のCDNやサーバーから読み込むスタイルシートの link rel="stylesheet" 要素に、integrity 属性で期待するハッシュ値を書いておき、ブラウザが取得したCSSのハッシュが一致しない場合にそのスタイルシートを適用させない仕組み(Subresource Integrity)です。
外部CSSにも、JavaScriptと同様にSRIを設定できます。CSSはJavaScriptのように任意の処理を実行できませんが、改ざんされると画面表示の偽装や、属性セレクターと背景画像を組み合わせた情報の外部送信などに悪用される可能性があります。セキュリティAIチェッカーのこの項目は、トップページで読み込まれている外部CSSに有効なSRIが付いているかを確認します。重大度はJavaScriptより低いlow、重みは1です。
<link rel="stylesheet"
href="https://cdn.example.net/icons/2.1.0/icons.min.css"
integrity="sha384-(ファイルのSHA-384ハッシュをBase64で表した値)"
crossorigin="anonymous">
外部JavaScriptのSRIは「外部JavaScriptのSRI」で別に確認します。
外部CSSが改ざんされると何が起こるのか
- 表示の偽装:注意書きや問い合わせ先を
display:noneで隠し、::before/::afterのcontentで偽の電話番号や文言を表示させる。 - 情報の外部送信:属性セレクターと
background-image: url(...)を組み合わせると、入力欄のvalue属性など、HTML属性に含まれる値を1文字ずつ外部へ送信させる手法が知られています(CSSインジェクション)。 - クリックの誘導:透明な要素や配置の変更で、利用者に意図しないリンクやボタンを押させる。
- 外部リソースの読み込み:
@importやurl()により、改ざん者のサーバーへアクセスさせ、閲覧の事実を記録する。
JavaScriptに比べれば影響は限定的ですが、ASVS 5.0.0 V3.6.1はJavaScriptだけでなくCSSやWebフォントも明示的に対象にしています。
SRIの仕様上の要点(CSSの場合)
- 対応するハッシュ関数はSHA-256、SHA-384、SHA-512です(W3C SRI)。
integrityの値に有効なハッシュ指定が1つもない場合(空の値、未対応のアルゴリズムのみ)、ブラウザは検証を行いません。仕様は、未対応のハッシュ関数による指定は「integrityの値がなかったのと同じ」に扱うとしています。- 別オリジンの資産にSRIを使うにはCORSが必要です。
crossorigin="anonymous"を付け、配信元がAccess-Control-Allow-Originを返す必要があります。
SRIが向かないCSS(Webフォントサービスなど)
Webフォントサービスが返すCSSのように、ブラウザの種類や要求内容によって中身が変わるものには、SRIを付けられません。その場合は、フォントとCSSを自己ホストするか、CSPの style-src と font-src で配信元を限定します。
外部CSSのSRIの診断基準(セキュリティAIチェッカー)
取得対象
- 入力URLのリダイレクト後の最終URLのHTML本文(最大2MB)を対象にします。
rel="stylesheet"(引用符付きで値がstylesheetのもの)を持つlink要素のうち、hrefをページURL基準で解決したオリジンがページのオリジンと異なるものを評価します。@importで読み込まれるCSSや、JavaScriptが動的に追加するCSSは対象外です。
「有効なSRI」の条件
integrity 属性の値(空白区切りで複数指定可)に、sha256-、sha384-、sha512- のいずれかで始まりBase64文字が続くハッシュ指定が1つ以上含まれることが条件です。integrity="md5-... sha384-..." のように2番目以降にある指定も有効と認めます。空の値や未対応アルゴリズムのみの値は、ブラウザが検証しないため「SRIなし」と数えます。ハッシュ値と実ファイルの一致は、追加取得を行わないため確認しません。
判定条件
| 判定 | 条件 | 得点への影響 |
|---|---|---|
| 対象外(na) | 外部CSSが0件 | 採点の分母から除外 |
| ○ 問題なし(pass) | すべての外部CSSに有効なSRIがある | 重み1を満点で加算 |
| △ 要確認(warn) | 有効なSRIのない外部CSSが1件以上 | 重み1×0.45 |
- 根拠欄には「SRIなし: 未設定件数/外部CSS件数」を表示します。
- 動的に生成されるCSS(Webフォントサービス等)にはSRIを付けられない正当な理由があり、ASVS上もL3要件であるため、×(fail)ではなく△としています。
自治体サイトでの判定例
| 外部CSSの状態 | 判定 |
|---|---|
CDNのアイコンフォントCSS(版固定)に integrity="sha384-..." crossorigin="anonymous" | ○ |
Webフォントサービスの css2?family=... を読み込み、SRIなし | △(SRIは適用困難。自己ホストかCSPで補う) |
| すべてのCSSを自サイトから配信 | 対象外 |
検出の限界
rel="stylesheet"の値が完全一致する(大文字小文字は区別しない)link要素のみを対象とするため、rel="alternate stylesheet"や引用符なしのrel=stylesheetは数えません。hrefの値を引用符で囲んでいないものも数えません。- CSS内の
@importで読み込む外部CSS、JavaScriptが追加するlink要素、style要素内の外部参照は対象外です。 integrityの形式が正しくても、実ファイルのハッシュと一致しなければブラウザはスタイルを適用しません。診断が○でも、表示崩れがないかブラウザで確認してください。
外部CSSの種類別の対応目安
| 外部CSSの種類 | 推奨対応 |
|---|---|
| CDNの版固定ライブラリのCSS(アイコン、UI部品) | SRI+crossorigin、または自己ホスト |
| 版指定なしのCDNのCSS | 版を固定してからSRI、または自己ホスト |
| Webフォントサービスの動的CSS | フォントの自己ホスト、またはCSPで配信元限定 |
| 地図・SNS部品が読み込むCSS | 部品ごとiframe埋め込みにする、必要ページに限定する |
外部CSSが少数で、すべて版固定のライブラリであれば、自己ホストに切り替えるのが最も簡単で確実です。自己ホストにすればこの項目は対象外となり、外部依存の管理対象も減ります。
外部CSSにSRIがないとどんなリスクがあるか
- 偽情報の表示:改ざんされたCSSで、避難所や窓口の電話番号、受付時間などを偽の内容に見せかけることができます。自治体サイトは住民が信頼して行動の根拠にするため、影響は小さくありません。
- 入力内容の一部漏えい:CSSインジェクションの手法により、HTML属性に出力された値(検索語や入力欄の値など)が外部へ送信される可能性があります。
- サプライチェーン経由の改ざん:外部CDNのアカウント侵害やドメイン譲渡が起きた場合、自治体側は何も変更していなくても表示が改ざんされます。2024年のpolyfill.ioの事例は、配信元ドメインの所有者変更で配信内容が改変されうることを示しました(この事例はJavaScriptです)。
外部CSSにSRIを設定する方法・自己ホストへの移行(Apache・nginx・IIS・Next.js)
1. SRI値の作成と記述
curl -s https://cdn.example.net/icons/2.1.0/icons.min.css \
| openssl dgst -sha384 -binary | openssl base64 -A
<link rel="stylesheet"
href="https://cdn.example.net/icons/2.1.0/icons.min.css"
integrity="sha384-(上で計算した値)"
crossorigin="anonymous">
CSSが相対パスでフォント等を参照している場合、SRIはCSSファイル本体だけを検証し、参照先のフォントは検証しません。フォントの改ざん対策が必要なら、フォントも自己ホストします。
2. 自己ホストへの移行(推奨)
外部CSSの多くは、ファイルを自サイトに置くことで外部依存そのものをなくせます。
<!-- 変更前 -->
<link rel="stylesheet" href="https://cdn.example.net/icons/2.1.0/icons.min.css">
<!-- 変更後 -->
<link rel="stylesheet" href="/assets/vendor/icons-2.1.0/icons.min.css">
Webフォントは、利用規約で自己ホストが認められているフォントを選び、@font-face で自サイトから配信します。
@font-face {
font-family: "SiteSans";
src: url("/assets/fonts/sitesans-regular.woff2") format("woff2");
font-display: swap;
}
3. CSPで配信元を限定
Apache(.htaccess)
<IfModule mod_headers.c>
Header always set Content-Security-Policy-Report-Only "style-src 'self' https://cdn.example.net; font-src 'self' https://cdn.example.net"
</IfModule>
nginx
add_header Content-Security-Policy-Report-Only "style-src 'self' https://cdn.example.net; font-src 'self' https://cdn.example.net" always;
IIS(web.config)
<add name="Content-Security-Policy-Report-Only" value="style-src 'self' https://cdn.example.net; font-src 'self' https://cdn.example.net" />
Next.js
next.config.js の headers() で同じ値を返します。
4. 段階的な導入手順
- 外部CSSを一覧化し、版固定のライブラリと動的に生成されるCSSに分ける
- 版固定のものは、まず自己ホストへの移行を検討する(ライセンスと利用規約を確認)
- 外部配信を続けるものは、検証環境で
integrityとcrossoriginを付けて、主要ページの表示をPCとスマートフォンで確認する - 本番に反映し、コンソールのエラーと表示崩れがないことを確認する
- ライブラリ更新時にSRI値を再計算する手順を、更新手順書に追加する
5. 確認方法
curl -s https://www.city.example.lg.jp/ | grep -o -i -E '<link[^>]*stylesheet[^>]*>'
ブラウザの開発者ツールのコンソールで、integrityの不一致やCORSのエラーによりスタイルシートがブロックされていないかを確認します。ブロックされると、その部分のデザインが崩れます。対応後はセキュリティAIチェッカーで再診断し、根拠欄の「SRIなし」の件数を確認してください。
サイトを壊さないための注意点
style-srcを強制すると、インラインのstyle属性やstyle要素が多いCMSでは表示が大きく崩れます。CSPは必ずReport-Onlyから始め、インラインスタイルの扱い('unsafe-inline'を残すか、nonce/hashに移行するか)を決めてから強制してください。インラインの許可は「CSPでunsafe-inlineを許可していない」で確認します。- CDN側でファイルが更新される版指定なしのURLにSRIを付けると、更新時に突然スタイルが適用されなくなります。版を固定してから付与してください。
crossorigin属性を付けずにintegrityだけを付けると、別オリジンのCSSは読み込みに失敗します。
よくある質問(FAQ)
CSSにもSRIは必要ですか?
CSSはJavaScriptのように任意の処理を実行できませんが、改ざんされると表示の偽装や情報の外部送信に悪用される可能性があります。ASVS 5.0.0 V3.6.1はCSSやWebフォントも明示的に対象にしています。ただし重大度はJavaScriptより低く、診断の重みは1です。
Webフォントサービスが配信するCSS(css2?family=… など)にSRIを付けられますか?
ブラウザの種類や要求内容によって中身が変わるCSSには、SRIを付けられません。フォントとCSSを自己ホストするか、CSPの style-src と font-src で配信元を限定します。
CSSにSRIを付ければ、CSSが読み込むフォントも検証されますか?
検証されません。SRIはCSSファイル本体だけを検証し、CSSから参照されるフォントは検証しません。フォントの改ざん対策が必要なら、フォントも自己ホストします。
integrity を付けたらデザインが崩れました。原因は何ですか?
ハッシュが実ファイルと一致しない、または crossorigin 属性がなく別オリジンのCSSの読み込みに失敗している可能性があります。ブラウザの開発者ツールのコンソールで、integrityの不一致やCORSのエラーを確認してください。
@import で読み込んでいる外部CSSも診断されますか?
されません。対象は rel="stylesheet" を持つ link 要素だけで、CSS内の @import、JavaScriptが追加する link 要素、style 要素内の外部参照は対象外です。
外部CSSを自己ホストにするとどう判定されますか?
外部CSSが0件になるため、この項目は対象外(na)になります。外部依存の管理対象も減るため、版固定のライブラリなら自己ホストが最も簡単で確実な方法です。
この項目を含む127項目を、URLを入れるだけで無料診断します。