[インデックス 14640] ファイルの概要
このコミットは、Go言語の公式ドキュメントツールであるgodoc
が提供するexample.html
テンプレートに対する変更です。godoc
は、Goのソースコードからドキュメントを生成し、ウェブブラウザを通じて提供するツールです。example.html
は、godoc
がGoのサンプルコード("play code")を表示する際に使用するHTMLテンプレートの一部であり、特にユーザーがブラウザ上でコードを実行できる「Go Playground」のような機能に関連しています。このファイルは、Goの標準ライブラリの一部として提供されるgodoc
ツールの内部リソースであり、Goのドキュメント表示機能のコアを構成しています。
コミット
このコミットは、lib/godoc/example.html
ファイル内のGoテンプレート構文を修正し、Go Playgroundのコード表示部分でHTMLエスケープを適用するように変更しています。これにより、表示されるコードがHTML特殊文字を含んでいても、正しくプレーンテキストとして表示され、クロスサイトスクリプティング(XSS)などのセキュリティ脆弱性を防ぐ効果があります。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/e470b3354cb61332585cd85bf814fe1131abe14b
元コミット内容
commit e470b3354cb61332585cd85bf814fe1131abe14b
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Thu Dec 13 19:08:51 2012 +0800
lib/godoc/example.html: htmlify the play code
Fixes #4539.
R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/6942043
---
lib/godoc/example.html | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n
diff --git a/lib/godoc/example.html b/lib/godoc/example.html
index a6df54be6f..cda2a8491e 100644
--- a/lib/godoc/example.html
+++ b/lib/godoc/example.html
@@ -8,7 +8,7 @@
{{$output := .Output}}\n \t\t{{with .Play}}\n \t\t\t<div class=\"play\">\n-\t\t\t\t<div class=\"input\"><textarea class=\"code\">{{.}}</textarea></div>\n+\t\t\t\t<div class=\"input\"><textarea class=\"code\">{{html .}}</textarea></div>\n \t\t\t\t<div class=\"output\"><pre>{{html $output}}</pre></div>\n \t\t\t\t<div class=\"buttons\">\n \t\t\t\t\t<a class=\"run\" title=\"Run this code [shift-enter]\">Run</a>\n```
## 変更の背景
この変更の背景には、Go Playgroundのコード表示におけるセキュリティと表示の正確性の問題がありました。以前の`example.html`テンプレートでは、Goのサンプルコードが`<textarea>`要素内に直接挿入されていました。もしこのサンプルコード自体がHTMLの特殊文字(例: `<`, `>`, `&`など)を含んでいた場合、それらの文字はHTMLとして解釈されてしまい、意図しない表示崩れや、最悪の場合にはクロスサイトスクリプティング(XSS)脆弱性を引き起こす可能性がありました。
具体的には、`Fixes #4539`という記述から、このコミットがGoのIssueトラッカーで報告された特定のバグや脆弱性に対応するものであることが示唆されます。このIssueは、おそらくGo Playgroundで表示されるコードが適切にエスケープされていないことによる表示問題やセキュリティリスクに関するものだったと考えられます。
`{{html .}}`というテンプレートアクションを導入することで、Go Playgroundに表示されるコードの内容が常にHTMLエンティティとして適切にエスケープされるようになり、ブラウザがそれをプレーンテキストとして安全に解釈できるようになります。これにより、コードの正確な表示が保証され、悪意のあるスクリプトの挿入を防ぐことができます。
## 前提知識の解説
### Go言語の`html/template`パッケージ
Go言語の標準ライブラリには、ウェブアプリケーションで安全なHTML出力を生成するための`html/template`パッケージが含まれています。このパッケージは、テンプレートエンジンとして機能し、データ構造をHTMLにレンダリングする際に、自動的にコンテキストに応じたエスケープ処理を行います。
* **コンテキストに応じたエスケープ**: `html/template`パッケージの最も重要な機能の一つは、出力されるデータがHTMLドキュメントのどの部分(例: 要素の内容、属性値、JavaScriptコード、CSSスタイル)に挿入されるかに応じて、適切なエスケープ処理を自動的に適用することです。これにより、開発者が手動でエスケープ処理を記述する手間を省き、同時にXSSなどのセキュリティ脆弱性を防ぎます。
* **`{{html .}}`アクション**: これは、テンプレート内で変数の内容をHTMLとして安全にエスケープして出力するためのアクションです。具体的には、`<`を`<`に、`>`を`>`に、`&`を`&`に、`'`を`'`に、`"`を`"`に変換します。これにより、元の文字列がHTMLタグや属性として解釈されることを防ぎ、プレーンテキストとして表示されることを保証します。
### `godoc`ツール
`godoc`は、Go言語のソースコードからドキュメントを生成し、HTTPサーバーとして提供するツールです。開発者は`godoc`を実行することで、ローカル環境でGoの標準ライブラリや自身のプロジェクトのドキュメントをブラウザで閲覧できます。また、`godoc`はGoのサンプルコードをインタラクティブな「Go Playground」形式で表示する機能も持っており、ユーザーがブラウザ上で直接コードを編集・実行し、その結果を確認することができます。この機能は、Goの学習やデモンストレーションにおいて非常に有用です。
### HTML `textarea`要素
`<textarea>`要素は、複数行のプレーンテキスト入力領域を定義するHTML要素です。この要素の内部に記述された内容は、基本的にプレーンテキストとして扱われます。しかし、HTMLのパーサーは、`<textarea>`の開始タグと終了タグの間に存在する内容を解析する際に、HTML特殊文字(例: `<`や`>`)をHTMLタグの一部として解釈しようとします。そのため、`<textarea>`内に表示したい文字列がこれらの特殊文字を含んでいる場合、それらをHTMLエンティティにエスケープしないと、ブラウザが意図しないHTML構造を生成したり、表示が崩れたりする可能性があります。
### XSS (Cross-Site Scripting)
XSSは、ウェブアプリケーションにおける一般的なセキュリティ脆弱性の一つです。攻撃者がウェブページに悪意のあるスクリプト(通常はJavaScript)を注入し、そのスクリプトが他のユーザーのブラウザで実行されることで発生します。これにより、セッションハイジャック、データの盗難、ウェブサイトの改ざんなど、様々な攻撃が可能になります。不適切なHTMLエスケープは、XSS脆弱性の主要な原因の一つです。例えば、ユーザーが入力したデータが適切にエスケープされずにHTMLページに表示される場合、攻撃者は`<script>`タグなどを挿入して悪意のあるコードを実行させることができます。
## 技術的詳細
このコミットの技術的詳細の中心は、Goの`html/template`パッケージが提供するコンテキストに応じたエスケープ機能、特に`{{html .}}`アクションの適用です。
Goのテンプレートエンジンは、デフォルトで安全な出力を心がけていますが、特定のコンテキストでは明示的なエスケープ指示が必要になる場合があります。`<textarea>`要素の内部は、HTMLパーサーが特殊な方法で内容を処理するため、通常のHTMLエスケープだけでは不十分な場合があります。
* **`{{.}}`から`{{html .}}`への変更**:
* 元のコードでは、`{{.}}`が使用されていました。これは、Goテンプレートにおいて、現在のコンテキストの値をそのまま出力する(または、デフォルトのエスケープルールに従ってエスケープする)ことを意味します。しかし、`<textarea>`のコンテキストでは、このデフォルトの挙動が不十分でした。
* `{{html .}}`に変更することで、テンプレートエンジンは、出力される値がHTMLコンテンツとして扱われることを明示的に認識し、HTML特殊文字をそのHTMLエンティティ表現(例: `<` → `<`)に変換します。これにより、ブラウザは`<textarea>`内の内容を純粋なテキストとして解釈し、HTMLタグとしてではなく、文字通りに表示します。
* **セキュリティの向上**:
* この変更により、Go Playgroundに表示されるサンプルコードに、例えば`<script>alert('XSS')</script>`のような文字列が含まれていても、それがHTMLとして実行されることはありません。代わりに、`<script>alert('XSS')</script>`のようにエスケープされて表示されるため、セキュリティが大幅に向上します。
* これは、ウェブアプリケーション開発における「出力エンコーディング」または「コンテキストに応じたエスケープ」の原則を遵守する典型的な例です。信頼できないデータをHTMLページに表示する際には、常にそのデータが挿入されるHTMLのコンテキストに合わせて適切にエスケープする必要があります。
* **表示の正確性**:
* セキュリティ上の利点だけでなく、表示の正確性も向上します。例えば、Goのコードスニペットに`fmt.Println("<a>")`のような行が含まれていた場合、エスケープなしでは`<a>`がHTMLタグとして解釈され、表示が崩れる可能性がありました。`{{html .}}`を適用することで、このようなコードも正確に`fmt.Println("<a>")`として表示され、意図した通りのコードスニペットがユーザーに提示されます。
このコミットは、Goの`godoc`ツールが提供するGo Playground機能の堅牢性とセキュリティを向上させるための、小さくも重要な修正です。
## コアとなるコードの変更箇所
```diff
--- a/lib/godoc/example.html
+++ b/lib/godoc/example.html
@@ -8,7 +8,7 @@
{{$output := .Output}}\n \t\t{{with .Play}}\n \t\t\t<div class=\"play\">\n-\t\t\t\t<div class=\"input\"><textarea class=\"code\">{{.}}</textarea></div>\n+\t\t\t\t<div class=\"input\"><textarea class=\"code\">{{html .}}</textarea></div>\n \t\t\t\t<div class=\"output\"><pre>{{html $output}}</pre></div>\n \t\t\t\t<div class=\"buttons\">\n \t\t\t\t\t<a class=\"run\" title=\"Run this code [shift-enter]\">Run</a>\n```
## コアとなるコードの解説
変更は`lib/godoc/example.html`ファイルの1行に集中しています。
* **変更前**:
```html
<div class="input"><textarea class="code">{{.}}</textarea></div>
```
この行では、Goテンプレートの`{{.}}`アクションを使用して、現在のコンテキスト(おそらくGoのサンプルコードの文字列)を`<textarea>`要素の内部に直接挿入していました。前述の通り、これはHTML特殊文字が適切にエスケープされないリスクを伴いました。
* **変更後**:
```html
<div class="input"><textarea class="code">{{html .}}</textarea></div>
```
変更後では、`{{.}}`が`{{html .}}`に置き換えられています。この`html`パイプライン(またはアクション)は、`html/template`パッケージによって提供される組み込み関数であり、入力された文字列をHTMLエンティティにエスケープする役割を担います。これにより、`<textarea>`内に挿入されるGoのサンプルコードが、たとえHTML特殊文字を含んでいても、それらがHTMLタグとしてではなく、文字通りのテキストとして安全に表示されるようになります。
この修正は、Go Playgroundのコード表示機能の堅牢性を高め、潜在的なセキュリティ脆弱性(XSS)を防ぐための重要な改善です。
## 関連リンク
* GitHubコミットページ: [https://github.com/golang/go/commit/e470b3354cb61332585cd85bf814fe1131abe14b](https://github.com/golang/go/commit/e470b3354cb61332585cd85bf814fe1131abe14b)
* Gerrit Change-Id (Goのコードレビューシステム): [https://golang.org/cl/6942043](https://golang.org/cl/6942043)
## 参考にした情報源リンク
* Go言語 `html/template` パッケージのドキュメント: [https://pkg.go.dev/html/template](https://pkg.go.dev/html/template)
* Go言語 `text/template` パッケージのドキュメント (html/templateの基盤): [https://pkg.go.dev/text/template](https://pkg.go.dev/text/template)
* MDN Web Docs - `<textarea>`: [https://developer.mozilla.org/ja/docs/Web/HTML/Element/textarea](https://developer.mozilla.org/ja/docs/Web/HTML/Element/textarea)
* OWASP Cross-Site Scripting (XSS): [https://owasp.org/www-community/attacks/xss/](https://owasp.org/www-community/attacks/xss/)