Safariは危険なJavaScriptに対応しない

[Firefox](https://qiita.com/rana_kualu/items/8803f02c72a54f366f2a) / Safari

先日Appleが、Safariは幾つかのWebAPIに対応しないと[公言しました](https://www.zdnet.com/article/apple-declined-to-implement-16-web-apis-in-safari-due-to-privacy-concerns/)。
日本語記事も[幾](https://it.srad.jp/story/20/06/30/1428255/)[つ](https://gigazine.net/news/20200629-apple-web-api-decline/)[か](https://article.auone.jp/detail/1/3/7/48_7_r_20200629_1593410623227367)出ています。

しかし、どのサイトも対応しないAPIの一覧を並べてはいるのですが、それぞれのAPIが具体的にどのようなものなのかを記載した記事が見当たらなかったので、以下はそれらについて調べてみたものです。


# 対応しない理由

`a threat to user privacy`、すなわち、あくまでブラウザフィンガープリントなどの手段によって個人を特定・追跡できてしまうからという理由です。
セキュリティ的にも問題なAPIが並んでいるのですが、そちらは理由ではありません。


# 対応しないWeb API

## Web Bluetooth

[caniuse](https://caniuse.com/#feat=web-bluetooth)
[RFC](https://webbluetoothcg.github.io/web-bluetooth/)
[非公式日本語訳](https://tkybpp.github.io/web-bluetooth-jp/)

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/2c819af4-39ff-533f-4d4a-dd81a42ae68f.png)

### 解説

ブラウザからBluetoothを通して接続先のデバイスにアクセスすることができます。
データ転送形式は[GATT](http://www.silex.jp/blog/wireless/2015/10/gatt.html)で、データを取得するだけではなく送り込むこともできます。

接続先の機器にもよりますが、接続可能なデバイスの例はデジカメだったり心拍計だったり血圧計だったりと、そりゃもう個人情報の塊ですから、物によってはひとつでも許可した時点で完全に個人を特定できるようになるでしょう。


### Qiita内関連記事

[Web Bluetooth API で BLE（Chrome と micro:bit をつなぐ）](https://qiita.com/youtoy/items/cd2c3d4770d4ad75a321)
[micro:bitとWebBluetoothで通信してみました](https://qiita.com/yokmama/items/5522fabfb5b9623278e2)


## Web MIDI API

[caniuse](https://caniuse.com/#feat=midi)
[RFC](https://webaudio.github.io/web-midi-api/)

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/e9e39a8c-2813-8037-301f-f1e66fe8ce39.png)


### 解説

ブラウザからMIDI機器にアクセスすることができます。

そもそもブラウザをMIDI機器に繋ぐなんてこと、普通の人はしません。
RFCにも[Few systems will have significant numbers of MIDI devices attached](https://www.w3.org/TR/webmidi/#security-and-privacy-considerations-of-midi)『個体識別できなくなるほどたくさん接続されるMIDI機器はない』とか書かれるくらいですし。
機器のメーカーや機種名、バージョン、そしてその他のフィンガープリントを組み合わせれば、ほぼ完全に特定できるでしょう。
使ってる人が多いから識別できない[Gamepad API](https://caniuse.com/#feat=gamepad)とは対照的ですね。

また、音を鳴らしてそれを別のブラウザで聞き取ることができれば、PCとモバイルを紐付けることもできそうです。

### Qiita内関連記事

[WebAudio/WebMIDI API Advent Calendar 2017 Advent Calendar 2017](https://qiita.com/advent-calendar/2017/webaudiowebmidi)
[WebAudio Web MIDI API Advent Calendar 2016](https://qiita.com/advent-calendar/2016/webaudio)
[Web MIDI APIでシンセサイザーの入力を受け取ってみた](https://qiita.com/uplight_max/items/a1b921c4c70d5943d69b)
[Web MIDI API による Web アプリと DAW の連携](https://qiita.com/tanikawa/items/1a820f662791077e5df7)


## Magnetometer API

[caniuse](https://caniuse.com/#feat=mdn-api_magnetometer)
[RFC](https://www.w3.org/TR/magnetometer/)
[非公式日本語訳](https://triple-underscore.github.io/magnetometer-ja.html)

![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/20e30aa3-6ae2-ac19-b17d-ac6c16cf5912.png)


### 解説

磁力センサです。

そもそもこんなものをブラウザで扱う必要があるのかというのもありますが、RFCでも妙に具体的に[問題となりそうな例を出しています](https://www.w3.org/TR/magnetometer/#security-and-privacy)。
・建物などの磁場変動から、スマホの所有者の位置と移動を理論上特定することができる。
・[Geolocation API](https://www.w3.org/TR/geolocation-API/)の位置情報とMagnetometer APIのデータの差異から、ユーザがVPNを使っているかどうかがわかる。
・場合によってはキーストロークも取得可能。

そんなに懸念があるんだったら最初から作るなよ。

### Qiita内関連記事

見当たらず。


## Web NFC

[caniuse](https://caniuse.com/#feat=webnfc)
[RFC](https://w3c.github.io/web-nfc/)

![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/a68e29f1-5905-e536-5845-2e7f4de353a0.png)


### 解説


ブラウザからNFCにアクセスできます。

今どきのスマホであれば、本体は最初から対応しています。
PCであればNFCリーダー/ライターが必要となります。

実装例は、[【Web NFC】JavaScriptでNFCタグのデータを読み書きしてみた](https://tech.aptpod.co.jp/entry/2020/06/12/090000) などで見ることができます。
思いきりNFCにデータを書き込んでいますね。
これにより個人の特定、複数ブラウザの紐付けが可能になります。

### Qiita内関連記事

見当たらず。


## Navigator API: deviceMemory

[caniuse](https://caniuse.com/#feat=mdn-api_navigator_devicememory)
[RFC](https://w3c.github.io/device-memory/#sec-device-memory-js-api)

![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/29b12099-f764-4a70-c87b-821acb7b68aa.png)


### 解説

[メモリ量を取得します](https://developer.mozilla.org/ja/docs/Web/API/Navigator/deviceMemory)。

取得できる値は厳密値ではなく、0.5・1・2・4・8のような概算値です。
そのため、よっぽど変な仕様のレア端末でもないかぎり、特定の懸念はさほど大きくないのではないかと思われます。
もちろん他情報と組み合わせることで絞り込み精度が上がるのは間違いありませんが、それはこれ以外のどのような情報も同じことです。
このAPIがあえて単独で挙げられている理由はよくわかりませんでした。

まあ、そもそもなんでブラウザごときに搭載メモリ量渡さにゃならんのだっていう話ではありますが。

### Qiita内関連記事

[Webブラウザの世界から始めるIoT入門 #gigttt](https://qiita.com/n0bisuke/items/adeafd02e7a03df654fb#%E3%83%A1%E3%83%A2%E3%83%AA%E3%82%92%E7%9F%A5%E3%82%8B---navigatordevicememory)


## NetworkInformation API

[caniuse](https://caniuse.com/#feat=mdn-api_networkinformation)
[RFC](https://wicg.github.io/netinfo/#idl-def-NetworkInformation)

![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/90596928-cecc-e77f-26c1-bf9bcff640fb.png)


### 解説

ネットワーク接続状況を取得します。

[NetworkInformation.type](https://developer.mozilla.org/ja/docs/Web/API/NetworkInformation/type)で"wifi"や"bluetooth"などの接続種別、[NetworkInformation.effectiveType](https://wicg.github.io/netinfo/#effectivetype-attribute)で最近繋いだネットワークと接続速度を取得したりできます。
またonchangeイベントで、接続先ネットワークの変更を感知することもできます。
遅い環境では画質を荒くしたりと、速度によって送り込むコンテンツを変更するようなことを考えているみたいですが、ゴミが送り付けられる未来しか見えない。

接続種別と応答速度からフィンガープリントが可能になります。
またonchangeイベントの発生頻度や発生時刻から、いつまで職場にいて何時に帰宅したというように行動を推測することも可能です。

ちなみにこの問題への対策は、"they should disable JavaScript, monitor that all outbound requests are made to trusted origins, and make diligent use of anonymizing VPN/proxy services."『JavaScriptを無効にする、全てのアウトバウンド要求が信頼された発信元であるか監視する、匿名VPNを使用する』だそうです。
正気なん？


### Qiita内関連記事

見当たらず。


## Battery Status API

[caniuse](https://caniuse.com/#feat=battery-status)
[RFC](https://www.w3.org/TR/battery-status/)
[非公式日本語訳](https://triple-underscore.github.io/battery-ja.html)

![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/b41dc478-f7c0-6060-bc8c-e52ed85c4706.png)


### 解説

バッテリの残量、および充電状態などを取得するAPIです。

2016年には[フィンガープリントとして利用可能という論文](http://eprint.iacr.org/2015/616.pdf)が発表されています。
またかなり限定的ではありますが、バッテリの消費状況から位置を割り出すことにも[成功しています](https://yro.srad.jp/story/15/02/25/1615233/)。

そのためか本APIは[既にWeb標準から削除されており](https://developer.mozilla.org/ja/docs/Web/API/Battery_Status_API)、かつては対応していたFirefoxも[あえて非対応に戻しています](https://bugzilla.mozilla.org/show_bug.cgi?id=1313580)。
従って、今さらあえて名指しで出すようなAPIでもない気がしますね。

### Qiita内関連記事

[Fx0でBattery Status API](https://qiita.com/nobucci/items/08c16d24e00c03c2389c)


## Web Bluetooth Scanning

caniuse……なし？
[RFC](https://webbluetoothcg.github.io/web-bluetooth/scanning.html)
[ChromeStatus](https://www.chromestatus.com/feature/5346724402954240)

### 解説

デバイスの周囲にあるBluetoothデバイスをスキャンできるようになるという……この時点で有り得ない。
そりゃもう世界中にビーコン置いて回りますよ。

Chrome84時点ではフラグ`enable-experimental-web-platform-features`を有効にしないと使用することができませんが、有効にすべきではなく一生殺しておくべき機能です。


### Qiita内関連記事

見当たらず。


## AmbientLightSensor API

[caniuse](https://caniuse.com/#feat=mdn-api_ambientlightsensor)
[RFC](https://w3c.github.io/ambient-light/)
[非公式日本語訳](https://triple-underscore.github.io/ambient-light-ja.html)

![08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/7e20dcea-1c37-980e-2c3b-a9e05ffbcb86.png)


### 解説

環境光センサの値を読み取ることができます。
[Generic Sensor API](https://www.w3.org/TR/generic-sensor/)というセンサ関連の汎用APIの機能の[一部](https://w3c.github.io/ambient-light/#ambientlightsensor)という位置付けのようです。

規則的な生活をしている人ほど危険です。
毎日同じ時間に同じ光度であれば同一人物である可能性が高いでしょう。
二つのデバイスが似たような光度変化をすれば、同一人物あるいは家族程度に近い人物であると判断できるでしょう。

懸念点には『踏んだことのあるリンクは黒、未訪問のリンクは白で表示することで光度を変え、訪問済みか否かを識別する』みたいなことまで書かれていました。

visitedの色とか[昔は普通に取れていた](https://security.srad.jp/story/10/04/06/0133223/)んですよね。
牧歌的な時代だった。

### Qiita内関連記事

見当たらず。


## EME Extension: HDCP Policy Check

caniuse……なし？
RFC……なし？
[ChromeStatus](https://www.chromestatus.com/feature/5652917147140096)
[GitHub](https://github.com/WICG/hdcp-detection/blob/master/explainer.md)

### 解説

[Encrypted Media Extensions](https://w3c.github.io/encrypted-media/)の追加機能のひとつで、メディアファイルのHDCPステータスをブラウザから見ることができるようになるみたいです。
HDCPはよく見るところだとHDMI接続とかで使われていて、PS3やAndroidを[PCに繋ぐと画面映らん！！](https://twitter.com/rana_kualu/status/1292798757734453254)ってなる面倒で邪魔なやつです。

[解説](https://github.com/WICG/hdcp-detection/blob/master/explainer.md)によると、この機能のプライバシー上の懸念は、EMEと同じ仕組みを使っているのでEMEと同じだということでした。
では、Appleがあえてこの機能だけをあえて非対応にする理由は何なのでしょうか。
正直EME自体が[何言ってるか](https://www.w3.org/2017/09/pressrelease-eme-recommendation.html.ja)[全然わからん](https://www.w3.org/2017/07/EME-backgrounder.html.ja)ので、何がどう危険なのかよくわかりませんでした。
識者あとよろ。

### Qiita内関連記事

見当たらず。


## Proximity API

[caniuse](https://caniuse.com/#feat=proximity)
[RFC](https://www.w3.org/TR/proximity/)

![09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/e8885979-6d12-d71f-eaff-cdd58d460877.png)


### 解説

近接センサです。
通話中にスマホから耳を離すと画面がついたり、逆に耳元に持っていくと画面が消えたりしますが、あれです。
距離の変化をブラウザに通知します。

実際は近付いた/離れたの変化どころか、具体的にセンチメートル単位での距離まで取得できるようです。
こんな情報をブラウザに渡すなんて有り得ないですね。

しかしこれをフィンガープリントとして使うのは難しそうな気がもしますが、[懸念点](https://www.w3.org/TR/proximity/#security-and-privacy)にはユーザ識別・フィンガープリントの危険があると書かれています。
どのようなシナリオが想定されているのかは、よくわかりませんでした。

### Qiita内関連記事

見当たらず。


## WebHID API

caniuse……なし？
[RFC](https://wicg.github.io/webhid/)

### 解説

Human Interface Device、すなわち人間が操作する各種デバイスへのアクセス手段を提供するAPIです。

[ゲームパッド](https://developer.mozilla.org/ja/docs/Web/API/Gamepad_API)やMIDI機器などは、それぞれ専用のAPIによってJavaScriptからアクセスが可能です。
しかし、そのような対応は今のところ機器ごとに個々に行わなければならず、今後も追加したい機器が出るたびにAPI策定・実装ってしていたら大変です。
そこで、このAPIでは特定機器に囚われない、HIDデバイスへの汎用的なアクセス手段を提供します。

[懸念点](https://wicg.github.io/webhid/#security-and-privacy)が3000文字以上ある時点でねーわってかんじですが、たとえばカメラやマイクなどが付いているデバイス、医療機器などに汎用アクセスされたらたまったものではありません。

またWebで公開されることを想定していない、任意にプログラムを登録できるデバイスが繋がっている可能性もあります。
たとえば今のところブラウザはキーボードの入力をキャッチすることはできますが、逆にキーボードに能動的に何かを働きかけることはできません。
このAPIではそれが可能になり、キーボードの種類によってはキーロガーを仕込むこともできるようです。
[その対策](https://wicg.github.io/webhid/#attacking-the-host)は、『ユーザが同意しなければマクロを動かさないように**デバイスのメーカーが**対応する』

不山戯けてんのかこれ？


### Qiita内関連記事

見当たらず。


## Serial API

caniuse……なし？
[RFC](https://wicg.github.io/serial/)

### 解説

ブラウザからシリアルポートに……はい終わり。


### Qiita内関連記事

見当たらず。


## WebUSB

[caniuse](https://caniuse.com/#feat=webusb)
[RFC](https://wicg.github.io/webusb/)

![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/f8882983-9c0e-842d-bd93-b3299cb495e8.png)

### 解説

ブラウザからUSBポートに……はい終わり。


### Qiita内関連記事

[WebUSBを使ってブラウザのJavaScriptからArduinoを制御してみよう！](https://qiita.com/n0bisuke/items/b5a90ead155097dce484)
[micro:bitでWebUSBを使う](https://qiita.com/toyowata/items/5a8a905e6d08265b48f9)


## Idle Detection

caniuse……なし？
RFC……なし？
[GitHub](https://github.com/WICG/idle-detection)
[ChromeStatus](https://www.chromestatus.com/feature/4590256452009984)

### 解説

アイドル状態を通知します。

スクリーンセーバーが起動した、画面がロックされた、などのイベントをブラウザが検知できるようになります。
これにより、複数のWebサイトで同時に画面ロックイベントが発生すると、それは同じブラウザ、あるいは一つの端末である可能性が高い、すなわち同一人物であると判断できます。

この緩和策としてイベント発生をランダムに遅延させるという方法が考えられましたが、30秒遅らせたところで[長期収集することで十分に特定可能だ](https://github.com/WICG/idle-detection#event-timing-fuzzing)ということがわかったので却下されました。

その代替策として策定されたのが『パーミッションを要求する』はい役に立たないやつ来た。


### Qiita内関連記事

見当たらず。


## Geolocation Sensor

caniuse……なし？
[RFC](https://www.w3.org/TR/geolocation-sensor/)
[非公式日本語訳](https://triple-underscore.github.io/geolocation-sensor-ja.html)

### 解説

位置情報センサです。

既存の[Geolocation API](https://w3c.github.io/geolocation-api/)の拡張という立場です。

何が拡張されたかというと、Geolocation APIでは不可能だったバックグラウンド動作が可能になります。
すなわち、いったん他の手段で端末を特定さえしてしまえば、自宅と職場と移動ルートを完全に把握されるということです。

このAPI単体での個人特定は余程の田舎でもないかぎり難しいかもしれませんが、他のフィンガープリントと組み合わせることで、とてつもなく危険なAPIになります。


### Qiita内関連記事

見当たらず。

# 感想

なんでもかんでもブラウザで実行できてしまうとネイティブアプリに誘導できなくなって稼ぎが減ってしまう、という打算はもちろん有るでしょう。
しかし、それを別としても、ほとんどは対応しないのが当然すぎるAPIばかりですね。
特にNetworkInformation APIやらWeb Bluetooth Scanningなど、発想するまでは自由ですが、実装する時点で正気を疑うレベルです。
そんなわけでSafariがこれらのAPIから距離を取るのは、まあ妥当ですね。

なお、これらのAPIのほとんどは、Googleが先行して策定・開発し、W3CにWeb標準として提案するという形になっています。
すなわち、Chromeにはこれらの多くが既に実装されているということです。
おおこわいこわい。