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

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

このコミットは、Go言語の標準ライブラリであるnet/rpcパッケージにおいて、HTMLレンダリングに使用するテンプレートエンジンをtext/templateからhtml/templateへ変更するものです。この変更は、主にセキュリティと正確性の向上を目的としています。

コミット

net/rpcパッケージがHTMLをレンダリングする際に、text/templateではなくhtml/templateを使用するように変更されました。これは、vetツールによるチェック(CL 106370045)によって発見された問題に対応するものです。このコミットは、以前の試み(CL 101670044)でdeps_testの変更が漏れていたことに対する再度の修正となります。この変更により、net/rpcencoding, encoding/base64, encoding/json, html, unicode/utf16といった追加の依存関係を持つことになります。これらの追加依存は、明確な正確性とセキュリティ上の利点のために正当化されます。

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

https://github.com/golang/go/commit/76ce843afeb7af56fe32d6e4351799b2046f7cbb

元コミット内容

net/rpc: use html/template to render html

Found using the vet check in CL 106370045.

This is a second attempt at CL 101670044, which omitted the deps_test change.

This adds dependencies to net/rpc:

        encoding
        encoding/base64
        encoding/json
        html
        unicode/utf16

The obvious correctness and security warrants the additional dependencies.

LGTM=rsc
R=r, minux, rsc, adg
CC=golang-codereviews
https://golang.org/cl/110890043

変更の背景

この変更の背景には、Go言語のnet/rpcパッケージが提供するデバッグインターフェースにおける潜在的なセキュリティ脆弱性がありました。net/rpcは、RPCサービスの状態をブラウザで確認できるデバッグページを提供しています。このデバッグページはHTMLでレンダリングされますが、以前は汎用的なテキストテンプレートエンジンであるtext/templateを使用していました。

text/templateは、HTMLのコンテキストを考慮せずにテキストをそのまま出力するため、もし表示されるデータに悪意のあるスクリプトやHTMLタグが含まれていた場合、クロスサイトスクリプティング(XSS)攻撃のリスクがありました。例えば、RPCサービスがユーザー提供の文字列をデバッグページに表示するようなケースで、その文字列に<script>alert('XSS')</script>のような内容が含まれていた場合、それがエスケープされずにそのままHTMLとして解釈されてしまう可能性がありました。

この問題は、Goのコード品質チェックツールであるvetによって検出されました。vetは、Goのソースコードを静的に解析し、疑わしい構造や潜在的なバグを報告するツールです。vetnet/rpcのデバッグページレンダリングコードを分析した結果、text/templateの使用がセキュリティ上の懸念を引き起こす可能性があると判断されたと考えられます。

このコミットは、そのセキュリティリスクを軽減し、より堅牢なHTMLレンダリングを実現するために行われました。

前提知識の解説

Go言語のテンプレートパッケージ

Go言語には、主に2つの標準テンプレートパッケージがあります。

  1. text/template:

    • 汎用的なテキスト出力のためのテンプレートエンジンです。
    • HTML、XML、JSONなど、特定のフォーマットに特化していません。
    • 入力されたデータをそのまま出力するため、自動的なエスケープ処理は行いません
    • そのため、HTMLコンテンツを生成する際にユーザーからの入力など信頼できないデータを含める場合、開発者が手動でエスケープ処理を行う必要があります。これを怠ると、XSSなどのセキュリティ脆弱性につながる可能性があります。
  2. html/template:

    • HTMLコンテンツの生成に特化したテンプレートエンジンです。
    • 最も重要な特徴は、コンテキストに応じた自動エスケープ機能を提供することです。
    • これは、テンプレート内のデータがHTMLのどの部分(例: 要素のテキスト、属性値、JavaScriptコード、CSSスタイル、URLなど)に挿入されるかを解析し、そのコンテキストに最適なエスケープ処理を自動的に適用します。
    • これにより、開発者が明示的にエスケープ処理を記述しなくても、XSS攻撃などのインジェクション攻撃を効果的に防ぐことができます。
    • ただし、template.HTMLなどの型を使用して「安全なHTML」としてマークされたコンテンツは、エスケープ処理がスキップされるため、そのコンテンツが本当に信頼できるものであることを開発者が保証する必要があります。

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

XSSは、Webアプリケーションのセキュリティ脆弱性の一種です。攻撃者は、Webサイトに悪意のあるスクリプト(通常はJavaScript)を注入し、そのスクリプトが他のユーザーのブラウザで実行されるようにします。これにより、攻撃者はセッションクッキーの盗難、個人情報の取得、Webサイトの改ざんなど、様々な悪意のある行為を行うことができます。

XSS攻撃は、Webアプリケーションがユーザーからの入力を適切にサニタイズまたはエスケープせずに、そのままHTMLページに表示してしまう場合に発生します。text/templateのような自動エスケープ機能を持たないテンプレートエンジンを使用している場合、このリスクが高まります。

go vet ツール

go vetは、Go言語のソースコードを静的に解析し、潜在的なバグや疑わしいコード構造を報告するコマンドラインツールです。例えば、フォーマット文字列の不一致、到達不能なコード、ロックの誤用、そしてこのケースのようにセキュリティ上の懸念があるテンプレートの使用などを検出できます。go vetは、Go開発者がコードの品質と信頼性を向上させるために広く利用されています。

技術的詳細

このコミットの技術的な核心は、net/rpcパッケージのデバッグインターフェースがHTMLを生成する際に、より安全なhtml/templateパッケージを利用するように変更された点にあります。

具体的には、以下の変更が行われました。

  1. src/pkg/net/rpc/debug.goの変更:

    • このファイルは、net/rpcのデバッグページを生成するロジックを含んでいます。
    • 変更前は、text/templateパッケージをインポートし、それを使用してHTML文字列をレンダリングしていました。
    • 変更後、text/templateのインポートが削除され、代わりにhtml/templateがインポートされました。
    • これにより、デバッグページに表示されるデータ(例えば、登録されているRPCメソッド名など)が、html/templateのコンテキストに応じた自動エスケープ機能によって処理されるようになります。これにより、もしこれらのデータにHTML特殊文字やスクリプトが含まれていても、それらが安全にエスケープされ、ブラウザによって悪意のあるコードとして実行されることを防ぎます。
  2. src/pkg/go/build/deps_test.goの変更:

    • このファイルは、Goのビルドシステムにおけるパッケージ間の依存関係をテストするためのものです。
    • pkgDepsというマップがあり、各パッケージが依存するパッケージのリストを定義しています。
    • このコミットでは、net/rpcの依存関係リストからtext/templateが削除され、html/templateが追加されました。
    • これは、net/rpcがもはやtext/templateに依存せず、代わりにhtml/templateに依存することをビルドシステムに正確に反映させるための変更です。この変更は、以前の関連コミット(CL 101670044)で漏れていた部分であり、このコミットで修正されました。

追加された依存関係

コミットメッセージに記載されているように、この変更によりnet/rpcパッケージには以下の追加依存関係が生じます。

  • encoding
  • encoding/base64
  • encoding/json
  • html
  • unicode/utf16

これらの依存関係は、html/templateパッケージが内部的に利用するものです。例えば、html/templateは、HTMLエンティティのエンコードや、JavaScript文字列のエスケープ、URLのエスケープなど、様々なコンテキストに応じた処理を行うために、これらのパッケージの機能を利用します。特にencoding/jsonunicode/utf16は、JavaScriptコンテキストでの安全なデータ埋め込みや、Unicode文字の適切な処理のために必要となる場合があります。

この変更は、net/rpcのデバッグインターフェースのセキュリティを向上させるだけでなく、Go言語の標準ライブラリ全体におけるセキュリティプラクティスの一貫性を保つ上でも重要です。

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

このコミットにおけるコアとなるコードの変更は、以下の2つのファイルに集中しています。

  1. src/pkg/go/build/deps_test.go

    --- a/src/pkg/go/build/deps_test.go
    +++ b/src/pkg/go/build/deps_test.go
    @@ -327,7 +327,7 @@ var pkgDeps = map[string][]string{\
     	"net/http/httptest": {"L4", "NET", "OS", "crypto/tls", "flag", "net/http"},\
     	"net/http/httputil": {"L4", "NET", "OS", "net/http"},\
     	"net/http/pprof":    {"L4", "OS", "html/template", "net/http", "runtime/pprof"},\
    -	"net/rpc":           {"L4", "NET", "encoding/gob", "net/http", "text/template"},\
    +	"net/rpc":           {"L4", "NET", "encoding/gob", "html/template", "net/http"},\
     	"net/rpc/jsonrpc":   {"L4", "NET", "encoding/json", "net/rpc"},\
     }\
    

    この変更は、net/rpcパッケージの依存関係リストを更新し、text/templateからhtml/templateへの移行を反映させています。

  2. src/pkg/net/rpc/debug.go

    --- a/src/pkg/net/rpc/debug.go
    +++ b/src/pkg/net/rpc/debug.go
    @@ -11,9 +11,9 @@ package rpc
     
     import (
     	"fmt"
    +	"html/template"
     	""net/http"
     	"sort"
    -	"text/template"
     )
     
     const debugText = `<html>
    

    この変更は、net/rpc/debug.goファイル内でインポートされるテンプレートパッケージをtext/templateからhtml/templateに直接切り替えています。これにより、このファイル内で定義されているdebugTextテンプレートがhtml/templateによって処理されるようになります。

コアとなるコードの解説

src/pkg/go/build/deps_test.goの変更

このファイルは、Goのビルドシステムがパッケージの依存関係を正しく解決できることを確認するためのテストデータを含んでいます。pkgDepsマップは、各Goパッケージが直接的または間接的に依存する他のパッケージのリストを定義しています。

変更前は、"net/rpc"のエントリに"text/template"が含まれていました。これは、net/rpctext/templateパッケージを使用していることを示していました。 変更後は、"text/template""html/template"に置き換えられています。これは、net/rpctext/templateへの依存を解消し、代わりにhtml/templateに依存するようになったという事実を正確に反映しています。このテストデータの更新は、ビルドの整合性を保つために重要です。

src/pkg/net/rpc/debug.goの変更

このファイルは、net/rpcパッケージが提供するデバッグHTTPエンドポイント(通常は/debug/rpc)のハンドラを実装しています。このエンドポイントは、登録されているRPCサービスやメソッドに関する情報を含むHTMLページを生成します。

変更の核心は、importセクションにあります。

  • - "text/template": 以前は、汎用的なtext/templateパッケージがインポートされていました。このパッケージは、HTMLのコンテキストを認識しないため、XSS脆弱性のリスクがありました。
  • + "html/template": 新しいコードでは、html/templateパッケージがインポートされています。このパッケージは、HTMLの構造を理解し、コンテキストに応じた自動エスケープを実行することで、XSS攻撃を自動的に防ぎます。

このインポートの変更に伴い、debug.go内のテンプレートのパースと実行ロジックも、html/templateのAPIを使用するように内部的に調整されているはずです(このdiffにはその部分の変更は含まれていませんが、インポートの変更がその意図を示しています)。これにより、debugText定数で定義されているHTMLテンプレートが、より安全な方法でレンダリングされることが保証されます。

例えば、debugTextテンプレート内でRPCメソッド名などを表示する際に、もしその名前に<script>タグのような悪意のある文字列が含まれていても、html/templateが自動的にそれを&lt;script&gt;のようにエスケープするため、ブラウザでスクリプトが実行されることはありません。

この変更は、net/rpcのデバッグインターフェースのセキュリティを大幅に向上させるものであり、Go言語のセキュリティベストプラクティスに沿ったものです。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント (html/template, text/template, cmd/vet)
  • Web検索結果: "Go net/rpc html/template security vs text/template" (Google Search)
  • OWASP (Open Web Application Security Project) のXSSに関する情報