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

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

このコミットは、Go言語の標準ライブラリ net/http パッケージにおけるクッキーの Domain 属性の扱いに関する修正です。具体的には、Set-Cookie ヘッダーを送信する際に、クッキーの Domain 属性の先頭に付与されるドット (.) を取り除くように変更されました。これは、RFC 6265 の仕様に準拠するための修正です。

コミット

commit f1d61b959fc0f759a619025eebd3c76d8a897553
Author: Volker Dobler <dr.volker.dobler@gmail.com>
Date:   Mon Aug 26 07:41:37 2013 -0500

    net/http: do not send leading dot in cookie domain attribute
    
    RFC 6265 allows a leading dot in a cookie domain attribute
    but is clear (see section 4.1.1) that a Set-Cookie header
    should be sent without these dots.
    
    R=bradfitz
    CC=golang-dev
    https://golang.org/cl/13111043

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

https://github.com/golang/go/commit/f1d61b959fc0f759a619025eebd3c76d8a897553

元コミット内容

net/http: do not send leading dot in cookie domain attribute

RFC 6265 では、クッキーのドメイン属性に先頭のドットを許可していますが、Set-Cookie ヘッダーはこれらのドットなしで送信されるべきであると明確に述べています(セクション 4.1.1 を参照)。

変更の背景

この変更の背景には、HTTP クッキーの仕様を定めた RFC 6265 への準拠があります。RFC 6265 は、クッキーの Domain 属性の解釈と送信方法について詳細に規定しています。

以前の Go の net/http パッケージでは、Cookie 構造体の Domain フィールドに先頭のドットが含まれている場合、そのドットを含んだまま Set-Cookie ヘッダーとして送信していました。しかし、RFC 6265 のセクション 4.1.1「The Set-Cookie Header Field」では、Domain 属性の値は「ドットで始まってはならない」と明記されています。

具体的には、RFC 6265 のセクション 4.1.1.2「The Domain Attribute」には、以下のような記述があります。

If the attribute-name is "Domain", the attribute-value is the domain-value. The domain-value is a string that represents a host domain name. If the domain-value is empty, the user agent will apply the default domain. If the domain-value starts with a %x2E (".") character, the user agent will ignore the Domain attribute.

この記述は、Set-Cookie ヘッダーで送信される Domain 属性の値がドットで始まる場合、ユーザーエージェント(ブラウザなど)がその Domain 属性を無視する可能性があることを示唆しています。つまり、先頭にドットが付いた Domain 属性を持つクッキーは、意図した通りに機能しないか、ホストオンリークッキーとして扱われる可能性がありました。

このコミットは、この仕様の不一致を解消し、Go の net/http パッケージが生成する Set-Cookie ヘッダーが RFC 6265 に完全に準拠するようにするために行われました。これにより、異なるブラウザやクライアント間でのクッキーの互換性と予測可能性が向上します。

前提知識の解説

HTTP クッキー (HTTP Cookies)

HTTP クッキーは、ウェブサイトがユーザーのブラウザに保存する小さなデータのことです。主にセッション管理(ログイン状態の維持)、パーソナライゼーション(ユーザー設定の記憶)、トラッキング(ユーザー行動の追跡)などに利用されます。

サーバーがクライアント(ブラウザ)にクッキーを設定する際に使用する HTTP レスポンスヘッダーです。このヘッダーには、クッキーの名前、値、有効期限、パス、ドメインなどの属性が含まれます。

例: Set-Cookie: name=value; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Domain=example.com; Path=/

クッキーの Domain 属性

Domain 属性は、クッキーが送信されるドメインを指定します。

  • Domain 属性が指定されていない場合、クッキーは「ホストオンリークッキー」となり、クッキーを設定したサーバーのホスト名にのみ送信されます。サブドメインには送信されません。
  • Domain 属性が指定されている場合、クッキーはそのドメインと、そのドメインのすべてのサブドメインに送信されます。例えば、Domain=example.com と設定されたクッキーは、example.comwww.example.comsub.example.com などに送信されます。

RFC 6265

RFC 6265 は、HTTP State Management Mechanism (HTTP 状態管理メカニズム) を定義する標準ドキュメントです。これは、HTTP クッキーの動作に関する最新かつ最も権威ある仕様であり、クッキーの作成、送信、保存、およびアクセスに関する詳細なルールを定めています。この RFC は、以前のクッキーに関する非公式な仕様や実装の不整合を解消し、より堅牢で安全なクッキーの利用を促進することを目的としています。

特に、Domain 属性に関するセクション 4.1.1.2 は、クッキーのドメインマッチングのルールと、Set-Cookie ヘッダーで送信される Domain 属性の値の形式について重要な指針を提供しています。

Domain 属性が明示的に指定されていないクッキーは、ホストオンリークッキーと呼ばれます。これらのクッキーは、クッキーを設定したオリジンサーバーの完全なホスト名にのみ送信され、そのサブドメインには送信されません。例えば、www.example.com から設定されたホストオンリークッキーは、www.example.com には送信されますが、example.comsub.example.com には送信されません。

技術的詳細

このコミットの技術的な核心は、net/http パッケージが Set-Cookie ヘッダーを生成する際に、Cookie 構造体の Domain フィールドの先頭にドットが存在するかどうかをチェックし、存在する場合はそのドットを取り除いてからヘッダーに含める点にあります。

RFC 6265 のセクション 4.1.1.2 では、Domain 属性の値がドットで始まる場合、ユーザーエージェントがその Domain 属性を無視する可能性があると述べられています。これは、Set-Cookie ヘッダーの Domain 属性が、常にドットなしの形式で送信されるべきであることを意味します。例えば、Domain=.example.com ではなく、Domain=example.com として送信されるべきです。

この修正により、Go の net/http パッケージは、開発者が Cookie 構造体の Domain フィールドに ".example.com" のように先頭にドットを含む値を設定した場合でも、RFC 6265 に準拠した Set-Cookie ヘッダーを生成するようになります。これにより、クッキーの動作がより予測可能になり、異なるクライアント環境での互換性の問題が減少します。

具体的には、Cookie.String() メソッド内で c.Domain の値が有効なクッキーのドメインであると判断された後、その文字列の最初の文字がドットであるかどうかがチェックされます。もしドットであれば、そのドットを削除した部分文字列が Set-Cookie ヘッダーの Domain 属性の値として使用されます。これにより、内部的にはドットを含む Domain 値を保持しつつも、外部に送信される形式は標準に準拠するようになります。

この変更は、クッキーのセキュリティやプライバシーに直接的な影響を与えるものではありませんが、クッキーの機能的な互換性と標準への準拠を保証する上で重要です。

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

src/pkg/net/http/cookie.go

--- a/src/pkg/net/http/cookie.go
+++ b/src/pkg/net/http/cookie.go
@@ -149,8 +149,13 @@ func (c *Cookie) String() string {
 		if validCookieDomain(c.Domain) {
 			// A c.Domain containing illegal characters is not
 			// sanitized but simply dropped which turns the cookie
-			// into a host-only cookie.
-			fmt.Fprintf(&b, "; Domain=%s", c.Domain)
+			// into a host-only cookie. A leading dot is okay
+			// but won't be sent.
+			d := c.Domain
+			if d[0] == '.' {
+				d = d[1:]
+			}
+			fmt.Fprintf(&b, "; Domain=%s", d)
 		} else {
 			log.Printf("net/http: invalid Cookie.Domain %q; dropping domain attribute",
 			c.Domain)

src/pkg/net/http/cookie_test.go

--- a/src/pkg/net/http/cookie_test.go
+++ b/src/pkg/net/http/cookie_test.go
@@ -26,7 +26,7 @@ var writeSetCookiesTests = []struct {
 	},
 	{
 		&Cookie{Name: "cookie-3", Value: "three", Domain: ".example.com"},
-		"cookie-3=three; Domain=.example.com",
+		"cookie-3=three; Domain=example.com",
 	},
 	{
 		&Cookie{Name: "cookie-4", Value: "four", Path: "/restricted/"},

コアとなるコードの解説

src/pkg/net/http/cookie.go の変更

Cookie 構造体の String() メソッドは、Cookie オブジェクトを Set-Cookie ヘッダーの文字列形式に変換する役割を担っています。このメソッド内で、Domain 属性の処理が変更されました。

変更前:

			fmt.Fprintf(&b, "; Domain=%s", c.Domain)

c.Domain の値がそのまま Domain 属性としてフォーマットされていました。もし c.Domain".example.com" であれば、Set-Cookie ヘッダーには Domain=.example.com が含まれていました。

変更後:

			// into a host-only cookie. A leading dot is okay
			// but won't be sent.
			d := c.Domain
			if d[0] == '.' {
				d = d[1:]
			}
			fmt.Fprintf(&b, "; Domain=%s", d)
  1. d := c.Domain: まず、c.Domain の値を一時変数 d にコピーします。
  2. if d[0] == '.': d の最初の文字がドット (.) であるかをチェックします。
  3. d = d[1:]: もし最初の文字がドットであれば、スライス操作 d[1:] を用いて、最初の文字(ドット)を取り除いた残りの文字列を d に再代入します。
  4. fmt.Fprintf(&b, "; Domain=%s", d): 最後に、修正された(または元のままの)d の値を Domain 属性としてフォーマットします。

この変更により、Cookie オブジェクトの Domain フィールドが ".example.com" であっても、実際に Set-Cookie ヘッダーとして送信される際には Domain=example.com となり、RFC 6265 の要件に準拠するようになります。コメント A leading dot is okay but won't be sent. は、内部的には先頭ドットを許容しつつも、送信時には取り除くという意図を明確に示しています。

src/pkg/net/http/cookie_test.go の変更

テストファイル cookie_test.go では、writeSetCookiesTests というテストケースのスライスが定義されており、様々な Cookie オブジェクトがどのように Set-Cookie ヘッダー文字列に変換されるかを検証しています。

変更前:

	{
		&Cookie{Name: "cookie-3", Value: "three", Domain: ".example.com"},
		"cookie-3=three; Domain=.example.com",
	},

Domain".example.com" の場合、期待される出力も Domain=.example.com でした。これは、変更前の実装の動作を反映しています。

変更後:

	{
		&Cookie{Name: "cookie-3", Value: "three", Domain: ".example.com"},
		"cookie-3=three; Domain=example.com",
	},

Domain".example.com" の場合でも、期待される出力が Domain=example.com に変更されました。これは、cookie.go で行われた修正が正しく機能し、先頭のドットが取り除かれることを検証するための変更です。このテストケースの更新は、コードの変更が意図した通りに動作することを保証するために不可欠です。

関連リンク

  • Go CL 13111043: https://golang.org/cl/13111043 - このコミットに対応する Go のコードレビューシステム (Gerrit) のチェンジリスト。詳細な議論やレビューコメントが確認できます。
  • RFC 6265 - HTTP State Management Mechanism: https://datatracker.ietf.org/doc/html/rfc6265 - HTTP クッキーの公式仕様。特にセクション 4.1.1.2 "The Domain Attribute" を参照。

参考にした情報源リンク

このコミットは、Go言語の標準ライブラリ net/http パッケージにおけるクッキーの Domain 属性の扱いに関する修正です。具体的には、Set-Cookie ヘッダーを送信する際に、クッキーの Domain 属性の先頭に付与されるドット (.) を取り除くように変更されました。これは、RFC 6265 の仕様に準拠するための修正です。

コミット

commit f1d61b959fc0f759a619025eebd3c76d8a897553
Author: Volker Dobler <dr.volker.dobler@gmail.com>
Date:   Mon Aug 26 07:41:37 2013 -0500

    net/http: do not send leading dot in cookie domain attribute
    
    RFC 6265 allows a leading dot in a cookie domain attribute
    but is clear (see section 4.1.1) that a Set-Cookie header
    should be sent without these dots.
    
    R=bradfitz
    CC=golang-dev
    https://golang.org/cl/13111043

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

https://github.com/golang/go/commit/f1d61b959fc0f759a619025eebd3c76d8a897553

元コミット内容

net/http: do not send leading dot in cookie domain attribute

RFC 6265 では、クッキーのドメイン属性に先頭のドットを許可していますが、Set-Cookie ヘッダーはこれらのドットなしで送信されるべきであると明確に述べています(セクション 4.1.1 を参照)。

変更の背景

この変更の背景には、HTTP クッキーの仕様を定めた RFC 6265 への準拠があります。RFC 6265 は、クッキーの Domain 属性の解釈と送信方法について詳細に規定しています。

以前の Go の net/http パッケージでは、Cookie 構造体の Domain フィールドに先頭のドットが含まれている場合、そのドットを含んだまま Set-Cookie ヘッダーとして送信していました。しかし、RFC 6265 のセクション 4.1.1「The Set-Cookie Header Field」では、Domain 属性の値は「ドットで始まってはならない」と明記されています。

具体的には、RFC 6265 のセクション 4.1.1.2「The Domain Attribute」には、以下のような記述があります。

If the attribute-name is "Domain", the attribute-value is the domain-value. The domain-value is a string that represents a host domain name. If the domain-value is empty, the user agent will apply the default domain. If the domain-value starts with a %x2E (".") character, the user agent will ignore the Domain attribute.

この記述は、Set-Cookie ヘッダーで送信される Domain 属性の値がドットで始まる場合、ユーザーエージェント(ブラウザなど)がその Domain 属性を無視する可能性があることを示唆しています。つまり、先頭にドットが付いた Domain 属性を持つクッキーは、意図した通りに機能しないか、ホストオンリークッキーとして扱われる可能性がありました。

このコミットは、この仕様の不一致を解消し、Go の net/http パッケージが生成する Set-Cookie ヘッダーが RFC 6265 に完全に準拠するようにするために行われました。これにより、異なるブラウザやクライアント間でのクッキーの互換性と予測可能性が向上します。

前提知識の解説

HTTP クッキー (HTTP Cookies)

HTTP クッキーは、ウェブサイトがユーザーのブラウザに保存する小さなデータのことです。主にセッション管理(ログイン状態の維持)、パーソナライゼーション(ユーザー設定の記憶)、トラッキング(ユーザー行動の追跡)などに利用されます。

サーバーがクライアント(ブラウザ)にクッキーを設定する際に使用する HTTP レスポンスヘッダーです。このヘッダーには、クッキーの名前、値、有効期限、パス、ドメインなどの属性が含まれます。

例: Set-Cookie: name=value; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Domain=example.com; Path=/

クッキーの Domain 属性

Domain 属性は、クッキーが送信されるドメインを指定します。

  • Domain 属性が指定されていない場合、クッキーは「ホストオンリークッキー」となり、クッキーを設定したサーバーのホスト名にのみ送信されます。サブドメインには送信されません。
  • Domain 属性が指定されている場合、クッキーはそのドメインと、そのドメインのすべてのサブドメインに送信されます。例えば、Domain=example.com と設定されたクッキーは、example.comwww.example.comsub.example.com などに送信されます。

RFC 6265

RFC 6265 は、HTTP State Management Mechanism (HTTP 状態管理メカニズム) を定義する標準ドキュメントです。これは、HTTP クッキーの動作に関する最新かつ最も権威ある仕様であり、クッキーの作成、送信、保存、およびアクセスに関する詳細なルールを定めています。この RFC は、以前のクッキーに関する非公式な仕様や実装の不整合を解消し、より堅牢で安全なクッキーの利用を促進することを目的としています。

特に、Domain 属性に関するセクション 4.1.1.2 は、クッキーのドメインマッチングのルールと、Set-Cookie ヘッダーで送信される Domain 属性の値の形式について重要な指針を提供しています。

Domain 属性が明示的に指定されていないクッキーは、ホストオンリークッキーと呼ばれます。これらのクッキーは、クッキーを設定したオリジンサーバーの完全なホスト名にのみ送信され、そのサブドメインには送信されません。例えば、www.example.com から設定されたホストオンリークッキーは、www.example.com には送信されますが、example.comsub.example.com には送信されません。

技術的詳細

このコミットの技術的な核心は、net/http パッケージが Set-Cookie ヘッダーを生成する際に、Cookie 構造体の Domain フィールドの先頭にドットが存在するかどうかをチェックし、存在する場合はそのドットを取り除いてからヘッダーに含める点にあります。

RFC 6265 のセクション 4.1.1.2 では、Domain 属性の値がドットで始まる場合、ユーザーエージェントがその Domain 属性を無視する可能性があると述べられています。これは、Set-Cookie ヘッダーの Domain 属性が、常にドットなしの形式で送信されるべきであることを意味します。例えば、Domain=.example.com ではなく、Domain=example.com として送信されるべきです。

この修正により、Go の net/http パッケージは、開発者が Cookie 構造体の Domain フィールドに ".example.com" のように先頭にドットを含む値を設定した場合でも、RFC 6265 に準拠した Set-Cookie ヘッダーを生成するようになります。これにより、クッキーの動作がより予測可能になり、異なるクライアント環境での互換性の問題が減少します。

具体的には、Cookie.String() メソッド内で c.Domain の値が有効なクッキーのドメインであると判断された後、その文字列の最初の文字がドットであるかどうかがチェックされます。もしドットであれば、そのドットを削除した部分文字列が Set-Cookie ヘッダーの Domain 属性の値として使用されます。これにより、内部的にはドットを含む Domain 値を保持しつつも、外部に送信される形式は標準に準拠するようになります。

この変更は、クッキーのセキュリティやプライバシーに直接的な影響を与えるものではありませんが、クッキーの機能的な互換性と標準への準拠を保証する上で重要です。

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

src/pkg/net/http/cookie.go

--- a/src/pkg/net/http/cookie.go
+++ b/src/pkg/net/http/cookie.go
@@ -149,8 +149,13 @@ func (c *Cookie) String() string {
 		if validCookieDomain(c.Domain) {
 			// A c.Domain containing illegal characters is not
 			// sanitized but simply dropped which turns the cookie
-			// into a host-only cookie.
-			fmt.Fprintf(&b, "; Domain=%s", c.Domain)
+			// into a host-only cookie. A leading dot is okay
+			// but won't be sent.
+			d := c.Domain
+			if d[0] == '.' {
+				d = d[1:]
+			}
+			fmt.Fprintf(&b, "; Domain=%s", d)
 		} else {
 			log.Printf("net/http: invalid Cookie.Domain %q; dropping domain attribute",
 			c.Domain)

src/pkg/net/http/cookie_test.go

--- a/src/pkg/net/http/cookie_test.go
+++ b/src/pkg/net/http/cookie_test.go
@@ -26,7 +26,7 @@ var writeSetCookiesTests = []struct {
 	},
 	{
 		&Cookie{Name: "cookie-3", Value: "three", Domain: ".example.com"},
-		"cookie-3=three; Domain=.example.com",
+		"cookie-3=three; Domain=example.com",
 	},
 	{
 		&Cookie{Name: "cookie-4", Value: "four", Path: "/restricted/"},\

コアとなるコードの解説

src/pkg/net/http/cookie.go の変更

Cookie 構造体の String() メソッドは、Cookie オブジェクトを Set-Cookie ヘッダーの文字列形式に変換する役割を担っています。このメソッド内で、Domain 属性の処理が変更されました。

変更前:

			fmt.Fprintf(&b, "; Domain=%s", c.Domain)

c.Domain の値がそのまま Domain 属性としてフォーマットされていました。もし c.Domain".example.com" であれば、Set-Cookie ヘッダーには Domain=.example.com が含まれていました。

変更後:

			// into a host-only cookie. A leading dot is okay
			// but won't be sent.
			d := c.Domain
			if d[0] == '.' {
				d = d[1:]
			}
			fmt.Fprintf(&b, "; Domain=%s", d)
  1. d := c.Domain: まず、c.Domain の値を一時変数 d にコピーします。
  2. if d[0] == '.': d の最初の文字がドット (.) であるかをチェックします。
  3. d = d[1:]: もし最初の文字がドットであれば、スライス操作 d[1:] を用いて、最初の文字(ドット)を取り除いた残りの文字列を d に再代入します。
  4. fmt.Fprintf(&b, "; Domain=%s", d): 最後に、修正された(または元のままの)d の値を Domain 属性としてフォーマットします。

この変更により、Cookie オブジェクトの Domain フィールドが ".example.com" であっても、実際に Set-Cookie ヘッダーとして送信される際には Domain=example.com となり、RFC 6265 の要件に準拠するようになります。コメント A leading dot is okay but won't be sent. は、内部的には先頭ドットを許容しつつも、送信時には取り除くという意図を明確に示しています。

src/pkg/net/http/cookie_test.go の変更

テストファイル cookie_test.go では、writeSetCookiesTests というテストケースのスライスが定義されており、様々な Cookie オブジェクトがどのように Set-Cookie ヘッダー文字列に変換されるかを検証しています。

変更前:

	{
		&Cookie{Name: "cookie-3", Value: "three", Domain: ".example.com"},
		"cookie-3=three; Domain=.example.com",
	},

Domain".example.com" の場合、期待される出力も Domain=.example.com でした。これは、変更前の実装の動作を反映しています。

変更後:

	{
		&Cookie{Name: "cookie-3", Value: "three", Domain: ".example.com"},
		"cookie-3=three; Domain=example.com",
	},

Domain".example.com" の場合でも、期待される出力が Domain=example.com に変更されました。これは、cookie.go で行われた修正が正しく機能し、先頭のドットが取り除かれることを検証するための変更です。このテストケースの更新は、コードの変更が意図した通りに動作することを保証するために不可欠です。

関連リンク

  • Go CL 13111043: https://golang.org/cl/13111043 - このコミットに対応する Go のコードレビューシステム (Gerrit) のチェンジリスト。詳細な議論やレビューコメントが確認できます。
  • RFC 6265 - HTTP State Management Mechanism: https://datatracker.ietf.org/doc/html/rfc6265 - HTTP クッキーの公式仕様。特にセクション 4.1.1.2 "The Domain Attribute" を参照。

参考にした情報源リンク