Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 12301] ファイルの概要

このコミットは、Go言語のhtml/templateパッケージにおけるテストファイルの更新です。具体的には、encoding/jsonパッケージがHTMLに影響を与える文字(<>など)をより厳密にエスケープするようになった変更に対応するため、関連するテストケースの期待される出力が修正されています。これにより、html/templateが生成するHTMLが、encoding/jsonによって生成されたJSONを安全に埋め込めることを保証します。また、テストケース名におけるタイプミス(MarshallerからMarshalerへ)の修正も含まれています。

コミット

commit 289a1638aa2af9b0cd633480c426285a10861c42
Author: David Symonds <dsymonds@golang.org>
Date:   Thu Mar 1 17:52:05 2012 +1100

    html/template: encoding/json does more escaping now, so update the html/template test that uses it.
    
    R=golang-dev, r
    CC=golang-dev
    https://golang.org/cl/5714052
---
 src/pkg/html/template/escape_test.go | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/pkg/html/template/escape_test.go b/src/pkg/html/template/escape_test.go
index a92a0596c7..2bbb1b1bc9 100644
--- a/src/pkg/html/template/escape_test.go
+++ b/src/pkg/html/template/escape_test.go
@@ -223,14 +223,14 @@ func TestEscape(t *testing.T) {
 			`<button onclick='alert(&quot;\x3cHello\x3e&quot;)'`
 		},
 		{
-			"badMarshaller",
+			"badMarshaler",
 			`<button onclick='alert(1/{{.B}}in numbers)'`,
 			`<button onclick='alert(1/ /* json: error calling MarshalJSON for type *template.badMarshaler: invalid character &#39;f&#39; looking for beginning of object key string */null in numbers)'`,
 		},
 		{
-			"jsMarshaller",
+			"jsMarshaler",
 			`<button onclick='alert({{.M}})'`,
-			`<button onclick='alert({&#34;&lt;foo&gt;&#34;:&#34;O&#39;Reilly&#34;})'>`,
+			`<button onclick='alert({&#34;\\u003cfoo\\u003e&#34;:&#34;O&#39;Reilly&#34;})'>`,
 		},
 		{
 			"jsStrNotUnderEscaped",

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/289a1638aa2af9b0cd633480c426285a10861c42

元コミット内容

html/template: encoding/json does more escaping now, so update the html/template test that uses it.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5714052

変更の背景

このコミットの背景には、Go言語の標準ライブラリであるencoding/jsonパッケージのセキュリティ強化があります。以前のバージョンでは、JSON文字列内にHTMLの特殊文字(<>&など)が含まれていても、それらがUnicodeエスケープシーケンス(例: <\u003c)に変換されずにそのまま出力される場合がありました。

このような挙動は、生成されたJSONが直接HTMLドキュメント、特に<script>タグ内やHTML属性値として埋め込まれる場合に、クロスサイトスクリプティング(XSS)脆弱性を引き起こす可能性がありました。例えば、悪意のあるユーザーが入力したデータに<script>タグが含まれていた場合、それがJSONとしてエスケープされずにHTMLに埋め込まれると、ブラウザがそのスクリプトを実行してしまう恐れがあります。

encoding/jsonパッケージがこれらのHTML特殊文字をより積極的にUnicodeエスケープするようになったため、html/templateパッケージ内の関連するテストケースも、この新しいエスケープ挙動を反映するように更新する必要が生じました。html/templateは、HTMLの安全な生成を目的としており、その内部でencoding/jsonを使用する際には、常に安全な出力が期待されます。この変更は、Go言語全体のセキュリティ体制を強化する一環として行われました。

前提知識の解説

Go言語のhtml/templateパッケージ

html/templateパッケージは、Go言語でHTMLコンテンツを安全に生成するためのテンプレートエンジンです。このパッケージの主な目的は、クロスサイトスクリプティング(XSS)などの一般的なWeb脆弱性からアプリケーションを保護することです。テンプレート内でユーザー提供のデータや動的なコンテンツを埋め込む際、html/templateは自動的に適切なエスケープ処理を施します。これにより、開発者が手動でエスケープ処理を行う手間を省き、セキュリティ上のミスを減らすことができます。例えば、JavaScriptのコンテキストではJavaScriptのエスケープ、HTML属性ではHTML属性のエスケープなど、コンテキストに応じたエスケープが行われます。

Go言語のencoding/jsonパッケージ

encoding/jsonパッケージは、Goのデータ構造とJSONデータの間でエンコード(Marshal)およびデコード(Unmarshal)を行うための標準ライブラリです。Goの構造体をJSON文字列に変換したり、JSON文字列をGoの構造体にパースしたりする機能を提供します。Webアプリケーションでは、APIのレスポンスや設定ファイルの読み込みなど、JSONデータの扱いは非常に一般的です。このパッケージは、JSONの仕様に厳密に従ってデータを処理しますが、セキュリティ上の理由から、特定の文字(特にHTMLの特殊文字)をUnicodeエスケープシーケンスに変換する場合があります。

クロスサイトスクリプティング(XSS)

XSSは、Webアプリケーションにおける代表的なセキュリティ脆弱性の一つです。攻撃者がWebページに悪意のあるスクリプト(通常はJavaScript)を注入し、そのスクリプトが他のユーザーのブラウザで実行されることで発生します。これにより、セッションハイジャック、個人情報の窃取、Webサイトの改ざんなど、様々な被害が生じる可能性があります。XSS攻撃を防ぐためには、ユーザーからの入力を信頼せず、表示する際には常に適切なエスケープ処理を施すことが不可欠です。

Unicodeエスケープシーケンス

Unicodeエスケープシーケンスは、Unicode文字をASCII文字の組み合わせで表現する方法です。JSONやJavaScriptの文字列では、特定の特殊文字(例: ダブルクォーテーション"、バックスラッシュ\、改行、タブなど)や、直接記述すると問題が生じる可能性のある文字(例: HTMLの<>)を、\uXXXX(XXXXは4桁の16進数)の形式で表現します。これにより、文字列の構文を壊すことなく、またセキュリティ上のリスクを低減しながら、任意のUnicode文字を安全に埋め込むことができます。

技術的詳細

このコミットの核心は、encoding/jsonパッケージがJSON文字列内でHTMLの特殊文字(特に<>)をUnicodeエスケープするようになったことです。

具体的には、以前のencoding/jsonは、JSON文字列として出力される際に、HTMLのコンテキストで特別な意味を持つ文字(<>)をそのまま出力することがありました。例えば、Goの文字列"<foo>"をJSONにエンコードすると、"\"<foo>\""のように出力されることがありました。

しかし、この挙動はセキュリティ上のリスクをはらんでいました。もしこのJSON文字列が、例えば以下のようにHTMLの<script>タグ内に直接埋め込まれた場合を考えます。

<script>
  var data = JSON.parse("{\"key\": \"<foo>\"}");
</script>

この場合、ブラウザは"{\"key\": \"<foo>\"}"をJSON文字列として解釈する前に、HTMLパーサーとして解釈します。すると、<foo>がHTMLタグとして認識され、スクリプトの構文が壊れたり、予期せぬHTML要素が挿入されたりする可能性があります。特に、<script>タグが挿入されるとXSSに直結します。

新しいencoding/jsonの挙動では、このようなリスクを軽減するために、JSON文字列内の<>をそれぞれ\u003c\u003eというUnicodeエスケープシーケンスに変換します。これにより、上記の例は以下のように出力されるようになります。

<script>
  var data = JSON.parse("{\"key\": \"\\u003cfoo\\u003e\"}");
</script>

この変更により、HTMLパーサーは\u003c\u003eを単なる文字列の一部として扱い、HTMLタグとして解釈することはありません。JSONパーサーはこれらのエスケープシーケンスを正しく元の文字にデコードするため、JSONとしての意味は保たれます。

html/templateパッケージは、テンプレート内でGoのデータ構造をJSONとして出力する際に、内部的にencoding/jsonを使用します。したがって、encoding/jsonのこのセキュリティ強化に伴い、html/templateのテストも、新しいエスケープされた出力を期待するように更新する必要がありました。このコミットは、そのテストの調整を行っています。

コアとなるコードの変更箇所

変更はsrc/pkg/html/template/escape_test.goファイルに集中しています。

  1. テストケース名のタイプミス修正:

    • "badMarshaller""badMarshaler" に変更されました。
    • "jsMarshaller""jsMarshaler" に変更されました。 これは機能的な変更ではなく、単なるスペル修正です。
  2. jsMarshalerテストケースの期待される出力の変更: 最も重要な変更は、jsMarshalerという名前のテストケースにおける期待される出力(wantフィールド)の修正です。

    • 変更前:
      `<button onclick='alert({&#34;&lt;foo&gt;&#34;:&#34;O&#39;Reilly&#34;})'>`
      
    • 変更後:
      `<button onclick='alert({&#34;\\u003cfoo\\u003e&#34;:&#34;O&#39;Reilly&#34;})'>`
      

この変更は、JSON文字列内の<foo>\u003cfoo\u003eとしてエスケープされるようになったことを反映しています。HTMLエンティティ(&#34;&#39;)はそのままですが、JSON文字列内部のHTML特殊文字がUnicodeエスケープに変わった点がポイントです。

コアとなるコードの解説

jsMarshalerテストケースは、Goのデータ構造がJSONとしてJavaScriptコンテキストに埋め込まれる際の挙動を検証しています。

変更前の期待される出力では、JSON文字列内の<foo>がHTMLエンティティとしてエスケープされず、そのまま<foo>として残っていました(ただし、JSONのダブルクォーテーションは&#34;に、シングルクォーテーションは&#39;にエスケープされています)。これは、encoding/jsonがHTML特殊文字をJSON文字列内でエスケープしない場合、html/templateが最終的にHTML属性値として出力する際に、そのJSON文字列がHTMLパーサーによって誤って解釈されるリスクがあることを示唆していました。

変更後の期待される出力では、JSON文字列内の<foo>\u003cfoo\u003eというUnicodeエスケープシーケンスに変換されています。これは、encoding/jsonパッケージが、JSON文字列内にHTMLの特殊文字(<>)が含まれる場合に、それらをUnicodeエスケープするようになったことを明確に示しています。

この修正により、html/templateは、encoding/jsonによって生成されたJSONが、たとえHTMLの特殊文字を含んでいても、HTMLコンテキストに安全に埋め込まれることを保証できるようになります。ブラウザは\u003c\u003eを単なる文字列として解釈し、HTMLタグとして誤認識することはありません。これにより、XSS脆弱性のリスクが低減されます。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント(html/templateおよびencoding/jsonパッケージ)
  • クロスサイトスクリプティング(XSS)に関する一般的なセキュリティ情報
  • Unicodeエスケープシーケンスに関する情報