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

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

このコミットは、Go言語の標準ライブラリである encoding/json パッケージにおける変更です。具体的には、JSONエンコーダがアンパサンド & をエスケープするようになったことについて、ドキュメントのコメントを更新しています。

コミット

commit 8a2dd16c7489493dab025a2edf3c58c3acab3d3e
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Wed Feb 5 01:24:51 2014 -0500

    encoding/json: mention escaping of '&'
    Fixes #7034.
    
    LGTM=iant
    R=golang-codereviews, iant
    CC=golang-codereviews
    https://golang.org/cl/57140043

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

https://github.com/golang/go/commit/8a2dd16c7489493dab025a2edf3c58c3acab3d3e

元コミット内容

encoding/json: mention escaping of '&'
Fixes #7034.

LGTM=iant
R=golang-codereviews, iant
CC=golang-codereviews
https://golang.org/cl/57140043

変更の背景

このコミットの背景には、Webブラウザにおけるセキュリティ上の懸念があります。JSONデータをHTMLドキュメント内に埋め込む際、特定の文字(特に <>&)がエスケープされていないと、クロスサイトスクリプティング(XSS)などの脆弱性を引き起こす可能性があります。

具体的には、Goの encoding/json パッケージは、以前からHTMLのタグと解釈される可能性のある <>\u003c\u003e にエスケープしていました。しかし、アンパサンド & もまた、HTMLエンティティ(例: &amp;&lt;)の開始文字として特殊な意味を持つため、エスケープされないと、ブラウザがJSON文字列を誤ってHTMLとして解釈し、意図しないスクリプト実行やコンテンツの改ざんにつながるリスクがありました。

このコミットは、Fixes #7034 とあるように、GoのIssue 7034に対応するものです。Issue 7034では、JSONエンコーダがアンパサンドをエスケープしないことによる潜在的なセキュリティリスクが指摘されており、このコミットはその問題を解決するために、アンパサンドのエスケープ処理が追加されたことをドキュメントに明記するものです。実際のアンパサンドのエスケープ処理自体は、このコミット以前に導入されていた可能性が高いですが、このコミットはドキュメントの整合性を保つためのものです。

前提知識の解説

JSON (JavaScript Object Notation)

JSONは、人間が読んで理解しやすく、機械が生成・解析しやすいデータ交換フォーマットです。Webアプリケーションでデータを送受信する際によく用いられます。JSONは、JavaScriptのオブジェクトリテラル構文に基づいていますが、言語に依存しないデータフォーマットとして広く利用されています。

エスケープ処理

エスケープ処理とは、特定の文字が持つ特別な意味を打ち消し、その文字自体を表現するために行われる変換です。例えば、JSON文字列内でダブルクォーテーション " を表現したい場合、それは文字列の区切り文字として解釈されるため、\" のようにバックスラッシュ \ を前置してエスケープする必要があります。

HTMLエンティティとXSS (Cross-Site Scripting)

HTMLでは、特定の文字(例: <>&"')は特殊な意味を持ちます。これらの文字をそのまま表示したい場合、HTMLエンティティ(例: <&lt;>&gt;&&amp;)に変換して記述します。

XSSは、Webアプリケーションの脆弱性の一種で、攻撃者が悪意のあるスクリプトをWebページに注入し、そのスクリプトがユーザーのブラウザで実行されることで発生します。JSONデータがHTMLドキュメント内に埋め込まれる際、JSON文字列内の特殊文字が適切にエスケープされていないと、ブラウザがJSONをHTMLとして誤解釈し、注入されたスクリプトを実行してしまう可能性があります。

例えば、JSONデータとして {"name": "<script>alert('XSS')</script>"} のような文字列が返され、これがHTMLにそのまま埋め込まれると、ブラウザは <script> タグをHTMLとして解釈し、アラートが表示されてしまいます。アンパサンド & も同様に、&lt;&gt; のようなHTMLエンティティの開始文字として解釈される可能性があるため、セキュリティ上のリスクとなります。

Unicodeエスケープ

JSONでは、非ASCII文字や特殊文字を \uXXXX の形式で表現するUnicodeエスケープが利用されます。ここで XXXX は4桁の16進数です。例えば、アンパサンド & のUnicodeコードポイントはU+0026なので、JSONでは \u0026 とエスケープされます。

技術的詳細

Goの encoding/json パッケージは、Goのデータ構造をJSON形式に変換(エンコード)する機能を提供します。このパッケージのエンコーダは、JSON仕様に準拠しつつ、Webブラウザでの安全な利用を考慮して、特定のHTML特殊文字を自動的にエスケープするよう設計されています。

このコミットが関連する encode.go ファイルは、JSONエンコーディングの核心部分を担っています。特に、文字列をJSON形式に変換する際の文字エスケープロジックが含まれています。

以前から、JSONエンコーダはセキュリティ上の理由から、HTMLのタグと解釈される可能性のある < (U+003C) と > (U+003E) をそれぞれ \u003c\u003e にエスケープしていました。これは、JSONデータが <script> タグ内やHTML属性値として埋め込まれた場合に、ブラウザがJSONをHTMLとして誤解釈し、XSS攻撃につながるのを防ぐためです。

このコミットは、その既存のエスケープ処理の説明に、アンパサンド & (U+0026) も同様に \u0026 にエスケープされることを追記するものです。アンパサンドもHTMLエンティティの開始文字として特殊な意味を持つため、適切にエスケープされないと、ブラウザがJSON文字列をHTMLとして解釈し、意図しない挙動を引き起こす可能性があります。例えば、&&amp; のようにエスケープされずにHTMLに埋め込まれると、ブラウザはそれをHTMLエンティティとして解釈しようとします。

この変更は、コードの動作自体を変更するものではなく、既存の動作(アンパサンドのエスケープ)をドキュメントに明記することで、開発者が encoding/json パッケージのセキュリティ特性をより正確に理解できるようにすることを目的としています。これにより、JSONデータをHTMLに埋め込む際の潜在的なセキュリティリスクに対する認識を高め、より安全なWebアプリケーション開発を促進します。

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

変更は src/pkg/encoding/json/encode.go ファイルにあります。

--- a/src/pkg/encoding/json/encode.go
+++ b/src/pkg/encoding/json/encode.go
@@ -44,6 +44,7 @@ import (
 // if an invalid UTF-8 sequence is encountered.
 // The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e"
 // to keep some browsers from misinterpreting JSON output as HTML.
+// Ampersand "&" is also escaped to "\u0026" for the same reason.
 //
 // Array and slice values encode as JSON arrays, except that
 // []byte encodes as a base64-encoded string, and a nil slice
@@ -804,7 +805,7 @@ func (e *encodeState) string(s string) (int, error) {
 			e.WriteByte('r')
 			default:
 				// This encodes bytes < 0x20 except for \n and \r,
-				// as well as < and >. The latter are escaped because they
+				// as well as <, > and &. The latter are escaped because they
 				// can lead to security holes when user-controlled strings
 				// are rendered into JSON and served to some browsers.
 				e.WriteString(`\u00`)

コアとなるコードの解説

このコミットは、src/pkg/encoding/json/encode.go 内の2つのコメント行を変更しています。

  1. import ブロック付近のコメント追加 (行44付近):

    // The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e"
    // to keep some browsers from misinterpreting JSON output as HTML.
    +// Ampersand "&" is also escaped to "\u0026" for the same reason.
    

    この変更は、encoding/json パッケージのドキュメントコメントに、アンパサンド & も同様に \u0026 にエスケープされることを明記しています。これは、<> がエスケープされるのと同じ理由(ブラウザがJSON出力をHTMLとして誤解釈するのを防ぐため)であることを強調しています。このコメントは、パッケージの動作の概要を説明する部分に追加され、開発者がパッケージのセキュリティ特性を理解するのに役立ちます。

  2. encodeState.string メソッド内のコメント修正 (行804付近):

    // This encodes bytes < 0x20 except for \n and \r,
    -// as well as < and >. The latter are escaped because they
    +// as well as <, > and &. The latter are escaped because they
    // can lead to security holes when user-controlled strings
    // are rendered into JSON and served to some browsers.
    

    この変更は、encodeState.string メソッド内のコメントを修正し、エスケープされる文字のリストに & を追加しています。このコメントは、JSON文字列エンコーディングの内部ロジックの一部として、なぜこれらの文字がエスケープされるのか(ユーザー制御の文字列がJSONとしてレンダリングされ、一部のブラウザに提供される際にセキュリティホールにつながる可能性があるため)を説明しています。この修正により、コードのコメントが実際の動作(アンパサンドもエスケープされる)と一致するようになります。

これらの変更は、Goの encoding/json パッケージが提供するセキュリティ機能に関するドキュメントの正確性と完全性を向上させるものです。コードの動作自体は変更されていませんが、その動作がより明確に説明されるようになりました。

関連リンク

参考にした情報源リンク

```markdown
# [インデックス 18414] ファイルの概要

このコミットは、Go言語の標準ライブラリである `encoding/json` パッケージにおける変更です。具体的には、JSONエンコーダがアンパサンド `&` をエスケープするようになったことについて、ドキュメントのコメントを更新しています。

## コミット

commit 8a2dd16c7489493dab025a2edf3c58c3acab3d3e Author: Shenghou Ma minux.ma@gmail.com Date: Wed Feb 5 01:24:51 2014 -0500

encoding/json: mention escaping of '&'
Fixes #7034.

LGTM=iant
R=golang-codereviews, iant
CC=golang-codereviews
https://golang.org/cl/57140043

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

[https://github.com/golang/go/commit/8a2dd16c7489493dab025a2edf3c58c3acab3d3e](https://github.com/golang/go/commit/8a2dd16c7489493dab025a2edf3c58c3acab3d3e)

## 元コミット内容

encoding/json: mention escaping of '&' Fixes #7034.

LGTM=iant R=golang-codereviews, iant CC=golang-codereviews https://golang.org/cl/57140043


## 変更の背景

このコミットの背景には、Webブラウザにおけるセキュリティ上の懸念があります。JSONデータをHTMLドキュメント内に埋め込む際、特定の文字(特に `<`、`>`、`&`)がエスケープされていないと、クロスサイトスクリプティング(XSS)などの脆弱性を引き起こす可能性があります。

具体的には、Goの `encoding/json` パッケージは、以前からHTMLのタグと解釈される可能性のある `<` と `>` を `\u003c` と `\u003e` にエスケープしていました。しかし、アンパサンド `&` もまた、HTMLエンティティ(例: `&amp;`、`&lt;`)の開始文字として特殊な意味を持つため、エスケープされないと、ブラウザがJSON文字列を誤ってHTMLとして解釈し、意図しないスクリプト実行やコンテンツの改ざんにつながるリスクがありました。

このコミットは、`Fixes #7034` とあるように、GoのIssue 7034に対応するものです。Issue 7034では、JSONエンコーダがアンパサンドをエスケープしないことによる潜在的なセキュリティリスクが指摘されており、このコミットはその問題を解決するために、アンパサンドのエスケープ処理が追加されたことをドキュメントに明記するものです。実際のアンパサンドのエスケープ処理自体は、このコミット以前に導入されていた可能性が高いですが、このコミットはドキュメントの整合性を保つためのものです。

## 前提知識の解説

### JSON (JavaScript Object Notation)

JSONは、人間が読んで理解しやすく、機械が生成・解析しやすいデータ交換フォーマットです。Webアプリケーションでデータを送受信する際によく用いられます。JSONは、JavaScriptのオブジェクトリテラル構文に基づいていますが、言語に依存しないデータフォーマットとして広く利用されています。

### エスケープ処理

エスケープ処理とは、特定の文字が持つ特別な意味を打ち消し、その文字自体を表現するために行われる変換です。例えば、JSON文字列内でダブルクォーテーション `"` を表現したい場合、それは文字列の区切り文字として解釈されるため、`\"` のようにバックスラッシュ `\` を前置してエスケープする必要があります。

### HTMLエンティティとXSS (Cross-Site Scripting)

HTMLでは、特定の文字(例: `<`、`>`、`&`、`"`、`'`)は特殊な意味を持ちます。これらの文字をそのまま表示したい場合、HTMLエンティティ(例: `<` は `&lt;`、`>` は `&gt;`、`&` は `&amp;`)に変換して記述します。

XSSは、Webアプリケーションの脆弱性の一種で、攻撃者が悪意のあるスクリプトをWebページに注入し、そのスクリプトがユーザーのブラウザで実行されることで発生します。JSONデータがHTMLドキュメント内に埋め込まれる際、JSON文字列内の特殊文字が適切にエスケープされていないと、ブラウザがJSONをHTMLとして誤解釈し、注入されたスクリプトを実行してしまう可能性があります。

例えば、JSONデータとして `{"name": "<script>alert('XSS')</script>"}` のような文字列が返され、これがHTMLにそのまま埋め込まれると、ブラウザは `<script>` タグをHTMLとして解釈し、アラートが表示されてしまいます。アンパサンド `&` も同様に、`&lt;` や `&gt;` のようなHTMLエンティティの開始文字として解釈される可能性があるため、セキュリティ上のリスクとなります。

### Unicodeエスケープ

JSONでは、非ASCII文字や特殊文字を `\uXXXX` の形式で表現するUnicodeエスケープが利用されます。ここで `XXXX` は4桁の16進数です。例えば、アンパサンド `&` のUnicodeコードポイントはU+0026なので、JSONでは `\u0026` とエスケープされます。

## 技術的詳細

Goの `encoding/json` パッケージは、Goのデータ構造をJSON形式に変換(エンコード)する機能を提供します。このパッケージのエンコーダは、JSON仕様に準拠しつつ、Webブラウザでの安全な利用を考慮して、特定のHTML特殊文字を自動的にエスケープするよう設計されています。

このコミットが関連する `encode.go` ファイルは、JSONエンコーディングの核心部分を担っています。特に、文字列をJSON形式に変換する際の文字エスケープロジックが含まれています。

以前から、JSONエンコーダはセキュリティ上の理由から、HTMLのタグと解釈される可能性のある `<` (U+003C) と `>` (U+003E) をそれぞれ `\u003c` と `\u003e` にエスケープしていました。これは、JSONデータが `<script>` タグ内やHTML属性値として埋め込まれた場合に、ブラウザがJSONをHTMLとして誤解釈し、XSS攻撃につながるのを防ぐためです。

このコミットは、その既存のエスケープ処理の説明に、アンパサンド `&` (U+0026) も同様に `\u0026` にエスケープされることを追記するものです。アンパサンドもHTMLエンティティの開始文字として特殊な意味を持つため、適切にエスケープされないと、ブラウザがJSON文字列をHTMLとして解釈し、意図しない挙動を引き起こす可能性があります。例えば、`&` が `&amp;` のようにエスケープされずにHTMLに埋め込まれると、ブラウザはそれをHTMLエンティティとして解釈しようとします。

この変更は、コードの動作自体を変更するものではなく、既存の動作(アンパサンドのエスケープ)をドキュメントに明記することで、開発者が `encoding/json` パッケージのセキュリティ特性をより正確に理解できるようにすることを目的としています。これにより、JSONデータをHTMLに埋め込む際の潜在的なセキュリティリスクに対する認識を高め、より安全なWebアプリケーション開発を促進します。

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

変更は `src/pkg/encoding/json/encode.go` ファイルにあります。

```diff
--- a/src/pkg/encoding/json/encode.go
+++ b/src/pkg/encoding/json/encode.go
@@ -44,6 +44,7 @@ import (
 // if an invalid UTF-8 sequence is encountered.
 // The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e"
 // to keep some browsers from misinterpreting JSON output as HTML.
+// Ampersand "&" is also escaped to "\u0026" for the same reason.
 //
 // Array and slice values encode as JSON arrays, except that
 // []byte encodes as a base64-encoded string, and a nil slice
@@ -804,7 +805,7 @@ func (e *encodeState) string(s string) (int, error) {
 			e.WriteByte('r')
 			default:
 				// This encodes bytes < 0x20 except for \n and \r,
-				// as well as < and >. The latter are escaped because they
+				// as well as <, > and &. The latter are escaped because they
 				// can lead to security holes when user-controlled strings
 				// are rendered into JSON and served to some browsers.
 				e.WriteString(`\u00`)

コアとなるコードの解説

このコミットは、src/pkg/encoding/json/encode.go 内の2つのコメント行を変更しています。

  1. import ブロック付近のコメント追加 (行44付近):

    // The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e"
    // to keep some browsers from misinterpreting JSON output as HTML.
    +// Ampersand "&" is also escaped to "\u0026" for the same reason.
    

    この変更は、encoding/json パッケージのドキュメントコメントに、アンパサンド & も同様に \u0026 にエスケープされることを明記しています。これは、<> がエスケープされるのと同じ理由(ブラウザがJSON出力をHTMLとして誤解釈するのを防ぐため)であることを強調しています。このコメントは、パッケージの動作の概要を説明する部分に追加され、開発者がパッケージのセキュリティ特性を理解するのに役立ちます。

  2. encodeState.string メソッド内のコメント修正 (行804付近):

    // This encodes bytes < 0x20 except for \n and \r,
    -// as well as < and >. The latter are escaped because they
    +// as well as <, > and &. The latter are escaped because they
    // can lead to security holes when user-controlled strings
    // are rendered into JSON and served to some browsers.
    

    この変更は、encodeState.string メソッド内のコメントを修正し、エスケープされる文字のリストに & を追加しています。このコメントは、JSON文字列エンコーディングの内部ロジックの一部として、なぜこれらの文字がエスケープされるのか(ユーザー制御の文字列がJSONとしてレンダリングされ、一部のブラウザに提供される際にセキュリティホールにつながる可能性があるため)を説明しています。この修正により、コードのコメントが実際の動作(アンパサンドもエスケープされる)と一致するようになります。

これらの変更は、Goの encoding/json パッケージが提供するセキュリティ機能に関するドキュメントの正確性と完全性を向上させるものです。コードの動作自体は変更されていませんが、その動作がより明確に説明されるようになりました。

関連リンク

参考にした情報源リンク