サードパーティCookieについて
サードパーティCookieは2024年以降、基本的に禁止されます。
この理由の大きなひとつが、サイトAとサイトBの情報を紐付けされてしまうことです。
※画像出典:Chrome 114 の新機能
tracking.com
はa.com
上でのあなたの動きを監視することができますし、tracking.com
はb.com
上でのあなたの動きを監視することができます。
そしてtracking.com
は、a.com
とb.com
の情報を紐付けることが可能です。
すなわち、多数のサイトで紐付けを行うことで、あなたの趣味嗜好思想信条が完全に把握されてしまうわけです。
FacebookやInstagramでは聖人面しておきながら裏ではあんなサイトやこんなサイトを見ているんだ、みたいなことが現在のCookieの仕組みでは可能です。
可能ですというかおそらく実際やっているでしょう。
逆に言うと、サイトを横断して情報収集ができないのであればサードパーティCookieを発行できても問題ないわけです。
という発想で作られたのがCookies Having Independent Partitioned State、通称CHIPSという仕組みです。
tracking.com
はa.com
上でのあなたの動きを監視することができますし、tracking.com
はb.com
上でのあなたの動きを監視することができます。
しかしtracking.com
は、a.com
とb.com
の情報を紐付けることはできません。
めでたしめでたし。
使い方としてはcookieにPartitioned属性を発行するだけであり、簡単に切り替えることができます。
setcookieの問題点
ということでPHPでもCHIPSに対応したいですね。
ところが実はそう素直にはいきません。
以下はsetcookie関数のシグネチャです。
setcookie(string $name, string $value = "", array $options = []): bool
// 古い書き方
setcookie(
string $name,
string $value = "",
int $expires_or_options = 0,
string $path = "",
string $domain = "",
bool $secure = false,
bool $httponly = false
): bool
元々は引数を個々に受け取るシグネチャだけでしたが、引数が多くなりすぎてしまったためPHP7.3において配列で受け取るオプションが追加されたという歴史があります。
また複数のシグネチャを持つ関数は徐々に整理されつつあるため、古い書き方は今後使用できなくなる可能性があります。
従って、今後は配列で渡すほうを使うようにしましょう。
さてこの$options
引数ですが、ひとつ問題があります。
なにかっつーと対応している属性以外受け取ってくれないんだなこれが。
setcookie('name', 'value', ['secure'=>true, 'Partitioned'=>true]);
Partitioned
なんて知らねーよのFatal errorが出ます。
なんで。
PHP8.3時点では$options
に渡せることのできる属性はexpires
・path
・domain
・secure
・httponly
・samesite
だけであり、それ以外の値を渡すことはできません。
なんで。
setcookieでPartitionedを渡せるようにするプルリクエスト
ということでPartitioned
を渡せるようにするプルリクエストが投げられていました。
メーリングリストにも投稿がありますが、特に大きな反応もないまま埋もれているようです。
このプルリクは、おそらくRFCを通さずマージされるんじゃないかなと思います。
というかこの程度でRFCとかいらんやろ。
と言いたいところですがかつてSameSiteが追加されたときはわざわざRFCが立ってたので、もしかしたらRFC経由になるかもしれません。
こんなんそのまま通してええやろ…
旧バージョンでもPartitionedを発行したいんだけど
この対応によって、今後のバージョンでPartitionedなCookieが発行できるようになる予定です。
しかし、諸事情でサーバの更新ができない、あるいは今すぐPartitionedを発行したいという場合はどうすればいいのでしょうか。
$options = [
'expires' => 0,
'path' => '/',
'samesite' => 'strict; Partitioned; Priority=Low; hoge=fuga',
'secure' => true,
'httponly' => true,
];
setcookie('name', 'value', $options);
マジかよ…
正直バグというか脆弱性なのでは?という挙動ですが、現状では関数が対応していない属性のCookieを発行するにはこんなことをしなければなりません。
これずっと前から既知の動作なので、このような場合のためにあえて潰さずに残しているのかもしれませんね。
あとMixiが公式にこの方法を案内しているのはちょっと笑う。
感想
というかむしろ、そもそも渡せる引数の制限を外してくれんかね。
今の仕様だと、今後もキーが増えるたびに毎回対応する必要があるわけで、それなら最初から好きな値を渡せるようにしておいた方がいいと思うのだが。
実際既に、SamePartyやPriorityといった一部ブラウザの独自属性には、まともな方法では対応できず、バグっぽい怪しい方法を使わざるを得ません。
まあ独自実装など知ったこっちゃねえという話ではあるのですが、実際そう言われても困ることもあるので、ここはまあどうにかしてほしいところですね。