[インデックス 11283] ファイルの概要
このコミットは、Go言語の標準ライブラリ html/template
パッケージのドキュメント (src/pkg/html/template/doc.go
) におけるAPI使用例の修正を目的としています。具体的には、html/template
パッケージのAPI変更に伴い、テンプレートの初期化方法 (template.Set{}
から template.New
へ) とテンプレートの実行方法 (Execute
から ExecuteTemplate
へ) の記述を更新し、さらにエスケープされた出力の表現をより厳密なHTMLエンティティ ('
) に修正しています。
コミット
html/template: fix docs after API changes
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5528109
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/369454d7b2f3b03ee5bdfde1eae6092bace14951
元コミット内容
commit 369454d7b2f3b03ee5bdfde1eae6092bace14951
Author: Gustavo Niemeyer <gustavo@niemeyer.net>
Date: Thu Jan 19 21:49:28 2012 -0200
html/template: fix docs after API changes
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5528109
---
src/pkg/html/template/doc.go | 14 +++++++-------\n 1 file changed, 7 insertions(+), 7 deletions(-)\n
変更の背景
このコミットは、html/template
パッケージのAPIが変更されたことに伴い、その公式ドキュメントに記載されているコード例が古くなったために行われました。Go言語の標準ライブラリは、開発の初期段階においてAPIの改善や洗練のために変更が行われることがあります。この場合、テンプレートの作成と実行に関するAPIが変更され、それに合わせてドキュメントのサンプルコードを最新の状態に保つ必要が生じました。特に、セキュリティを考慮したHTMLエスケープの挙動も改善されたため、その出力例も更新されています。
前提知識の解説
Go言語の text/template
と html/template
パッケージ
Go言語には、テキストベースのテンプレートを扱うための text/template
パッケージと、HTMLコンテンツを安全に生成するための html/template
パッケージがあります。
text/template
: 任意のテキスト形式の出力を生成するための汎用的なテンプレートエンジンです。例えば、設定ファイル、コード生成、プレーンテキストのレポートなどに使用できます。このパッケージは、出力されるコンテンツがHTMLとして解釈されることを前提としていないため、セキュリティ上のエスケープ処理は行いません。html/template
:text/template
を基盤としつつ、HTMLコンテンツを生成する際にクロスサイトスクリプティング (XSS) などの脆弱性を防ぐための自動エスケープ機能を提供するパッケージです。テンプレート内でユーザー入力などの動的なデータを表示する際、html/template
は自動的に適切なエスケープ処理(例:<
を<
に変換)を行い、悪意のあるスクリプトの埋め込みを防ぎます。
テンプレートの初期化と実行
Goのテンプレートパッケージでは、通常以下の手順でテンプレートを扱います。
- テンプレートの作成: テンプレート文字列を解析し、
*template.Template
型のインスタンスを作成します。 - データの結合: 作成したテンプレートにデータを渡し、テンプレートを「実行」して最終的な出力を生成します。
自動エスケープ (Autoescaping)
html/template
の最も重要な機能の一つが自動エスケープです。これは、テンプレート内で表示されるデータが、そのコンテキスト(例: HTML要素のテキスト、属性値、URLなど)に応じて自動的に適切なエスケープ処理が施される仕組みです。これにより、開発者が手動でエスケープ処理を記述する手間を省き、同時にXSS攻撃のリスクを大幅に低減します。例えば、<script>alert('XSS')</script>
のような文字列がHTMLコンテンツに挿入される場合、html/template
はこれを <script>alert('XSS')</script>
のようにエスケープし、ブラウザがスクリプトとして実行するのを防ぎます。
技術的詳細
このコミットにおける技術的な変更点は、主に html/template
パッケージのAPI利用方法と、エスケープされた出力の表現に関するものです。
-
テンプレートの初期化方法の変更:
- 変更前:
(&template.Set{}).Parse(...)
- 変更後:
template.New("foo").Parse(...)
これは、テンプレートセットを初期化する際の推奨される方法が変更されたことを示しています。以前はtemplate.Set{}
のような構造体リテラルを直接使用していましたが、新しいAPIではtemplate.New("name")
関数を使用して、名前付きの新しいテンプレートセットを作成するようになりました。template.New
は、テンプレートセットに一意の名前を割り当てることで、複数のテンプレートセットを管理しやすくする目的があります。この変更は、APIの設計思想の成熟と、より明確なテンプレート管理の促進を反映していると考えられます。
- 変更前:
-
テンプレートの実行方法の変更:
- 変更前:
t.Execute(out, "T", ...)
- 変更後:
t.ExecuteTemplate(out, "T", ...)
Execute
メソッドは、通常、テンプレートセット内のルートテンプレート(名前が空文字列のテンプレート)を実行するために使用されます。一方、ExecuteTemplate
メソッドは、テンプレートセット内の特定の名前を持つテンプレートを実行するために使用されます。この変更は、ドキュメントの例が{{define "T"}}
のように名前付きテンプレートT
を定義しているため、そのテンプレートを明示的に実行するExecuteTemplate
の方が適切であるというAPIの意図を反映しています。これにより、コードの意図がより明確になります。
- 変更前:
-
エスケープされた出力の表現の変更:
- 変更前:
Hello, <script>alert('you have been pwned')</script>!
- 変更後:
Hello, <script>alert('you have been pwned')</script>!
この変更は、シングルクォート'
のエスケープ方法が'
というHTMLエンティティに統一されたことを示しています。HTMLでは、シングルクォートは属性値などで特別な意味を持つため、安全のためにエスケープされるべき文字です。'
はシングルクォートの数値文字参照であり、より厳密で普遍的なエスケープ表現です。この変更は、html/template
が提供する自動エスケープ機能の堅牢性とセキュリティが向上したことを示唆しています。
- 変更前:
コアとなるコードの変更箇所
変更は src/pkg/html/template/doc.go
ファイルに集中しており、主にGoのテンプレートAPIの使用例が更新されています。
--- a/src/pkg/html/template/doc.go
+++ b/src/pkg/html/template/doc.go
@@ -31,8 +31,8 @@ Example
import "text/template"
...
- t, err := (&template.Set{}).Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
- err = t.Execute(out, "T", "<script>alert('you have been pwned')</script>")
+ t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
+ err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")
produces
@@ -42,12 +42,12 @@ but with contextual autoescaping,
import "html/template"
...
- t, err := (&template.Set{}).Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
- err = t.Execute(out, "T", "<script>alert('you have been pwned')</script>")
+ t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
+ err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")
produces safe, escaped HTML output
- Hello, <script>alert('you have been pwned')</script>!
+ Hello, <script>alert('you have been pwned')</script>!
Contexts
@@ -57,8 +57,8 @@ functions to each simple action pipeline, so given the excerpt
<a href="/search?q={{.}}\">{{.}}</a>
-At parse time each {{.}} is overwritten to add escaping functions as necessary,
-in this case,
+At parse time each {{.}} is overwritten to add escaping functions as necessary.
+In this case it becomes
<a href=\"/search?q={{. | urlquery}}\">{{. | html}}</a>
コアとなるコードの解説
上記の差分は、html/template
パッケージのドキュメント内の3つの主要なセクション(text/template
の例、html/template
の例、コンテキストの例)におけるコードスニペットと出力例を更新しています。
-
text/template
の例の修正:t, err := (&template.Set{}).Parse(...)
がt, err := template.New("foo").Parse(...)
に変更されました。これは、text/template
でもtemplate.New
を使用してテンプレートセットを初期化する新しい推奨パターンを反映しています。err = t.Execute(out, "T", ...)
がerr = t.ExecuteTemplate(out, "T", ...)
に変更されました。これは、名前付きテンプレートT
を実行するためにExecuteTemplate
を使用する、より正確な方法を示しています。
-
html/template
の例の修正:text/template
の例と同様に、テンプレートの初期化と実行方法がtemplate.New
とExecuteTemplate
を使用するように更新されました。- 最も重要な変更は、出力例の
Hello, <script>alert('you have been pwned')</script>!
がHello, <script>alert('you have been pwned')</script>!
に変更された点です。これは、html/template
がシングルクォート'
を'
というHTMLエンティティにエスケープするようになったことを示しており、より堅牢なセキュリティ対策が講じられていることを強調しています。
-
コンテキストの例の修正:
At parse time each {{.}} is overwritten to add escaping functions as necessary, in this case,
という説明文がAt parse time each {{.}} is overwritten to add escaping functions as necessary. In this case it becomes
に変更されました。これは、文法的な修正であり、より自然な英語表現になっています。このセクションは、html/template
がどのようにコンテキストに基づいて自動的にエスケープ関数(例:urlquery
,html
)を挿入するかを説明しています。
これらの変更は、html/template
パッケージのAPIがより洗練され、セキュリティが強化されたことをドキュメントを通じてユーザーに伝えるための重要な更新です。
関連リンク
- Go CL 5528109: https://golang.org/cl/5528109
参考にした情報源リンク
- Go言語の公式ドキュメント:
html/template
およびtext/template
パッケージの現在のドキュメント (コミット当時のバージョンとは異なる可能性がありますが、基本的な概念は共通です)。 - HTMLエンティティに関する情報:
- https://www.w3.org/TR/html4/sgml/entities.html (HTML 4 の文字実体参照)