Comoji がキー入力をどこにも送信していないことを確かめる方法
Comoji は、Mac のすべてのアプリに Slack 風の :emoji: 補完を無料で追加します。
Comoji は、macOS でもっとも踏み込んだ 2 つの権限、アクセシビリティと入力監視を求めます。私たちは、すべてローカルで処理され、入力した内容が外部にアップロードされることはないと説明しています。Reddit で、ある方がもっともな疑問をうまく言葉にしてくれました。ほぼ信じてはいるけれど、こちらの言葉だけを頼りにそれらの権限を渡すのはやはり落ち着かない、というものです。
もっともな疑問ですし、その答えが「もっと信じてください」であってはいけません。この記事はその手順書です。以下のコマンドはすべて読み取り専用で、5 分ほどで終わり、Comoji がネットワーク上で何をして何をしていないかを、ご自身のマシンで確かめられます。接続先ホストの完全な一覧を含む参照版は セキュリティのページ にあります。
実際に何を確かめるのか
キーロガーは、取得したものを何かに使わなければなりません。どこかに送信するか、どこかに書き込むかです。それは検証できる小さく具体的な主張で、macOS にはそれを検証する道具がそろっています。プロセスが開いているネットワークソケットをすべて一覧にし、送信したバイト数をすべて数え、配布されたバイナリに埋め込まれたホスト名を読み、ネットワークへのアクセスを完全に遮断して何が動かなくなるかを見ることができます。
ここで紹介する方法は Comoji 専用ではありません。これらの権限を求める Mac の App なら、私たちのものも含め、まったく同じ手順で確かめられます。それこそが大事な点です。
始める前に
Comoji を起動した状態で、ターミナル(Applications → Utilities → Terminal、日本語環境では「アプリケーション」→「ユーティリティ」→「ターミナル」)を開きます。以下のコマンドはすべて読み取り専用の確認で、何かをインストールしたり、変更したり、削除したりすることはありません。開発版をインストールしている場合はプロセス名が ComojiDev なので、Comoji と書かれている箇所をすべてそれに置き換えてください。
まず、起動していることを確認してプロセス ID を取得します:
pgrep -x Comoji数字が返ってくるはずです。何も返ってこなければ、Comoji は起動していません(メニューバー App なので、Dock ではなくメニューバーを確認してください)。
ステップ 1:入力中のネットワーク接続を監視する
lsof は開いているファイルを一覧表示します。Unix システムではネットワークソケットもファイルです。Comoji のプロセス ID に絞ると、App が今開いているすべての接続が表示されます:
lsof -nP -i -a -p "$(pgrep -x Comoji)"期待される結果は 何も出力されないこと です。何も返ってこなければ、そのプロセスはネットワーク接続を持っていません。では実際に入力してみましょう。メッセージを開いて :fire、:tada、:liz の補完をいくつか使い、1、2 段落ほど文章を書いてから、もう一度コマンドを実行します。やはり何も出ません。
1 回だけのスナップショットでは、確認と確認の間に開いて閉じる接続を見逃す可能性が理論上あるので、代わりに継続的に監視します。空いているターミナルのウインドウにこれを貼り付け、Mac を普段どおり使う間、実行したままにしておきます:
while :; do
printf '%s ' "$(date +%T)"
lsof -nP -i -a -p "$(pgrep -x Comoji)" | tail -n +2 | awk '{print $9}' | paste -sd' ' -
echo
sleep 2
doneどれだけ入力しても、2 秒ごとにタイムスタンプだけが表示され、そのあとには何も続きません。止めるには Control-C を押します。
次に、そのループを実行したまま、ネットワークを使う *はずの* ことをしてみます。メッセージで /gif と入力して何か検索してください。すると、タイムスタンプの横に api.giphy.com と giphy.com の CDN ホストが表示されます。この対比こそが、このテストの肝です。接続があればループがそれを表示していたことが証明されるので、入力中に何も出なかった行は、見たとおりの意味を持つことになります。
ステップ 2:バイト数を数える
nettop はプロセスごとの累積通信量を記録するので、サンプリングによる確認では捉えきれないほど短い通信も捉えられます:
nettop -P -p "$(pgrep -x Comoji)"開いたまま数分間入力し、/gif と /sticker のピッカーには触れないでください。bytes_in と bytes_out の列はゼロのままです。終了するには q を押します。
ステップ 3:ダウンロードした App からホスト名を読み出す
プロセスは知っている場所にしか接続できず、ホスト名はバイナリの中に保存されている必要があります。strings はコンパイル済みのファイルから読める文字列を取り出すので、ソースコードがなくてもホスト名を一覧にできます:
strings -a /Applications/Comoji.app/Contents/MacOS/Comoji \
| grep -Eo 'https?://[A-Za-z0-9._-]+' | sort -u
/usr/libexec/PlistBuddy -c 'Print :SUFeedURL' \
/Applications/Comoji.app/Contents/Info.plist返ってくるのは、Google のステッカー画像 CDN(fonts.gstatic.com)、Firebase Storage にあるアップデートフィード(storage.googleapis.com)、そして App 内のリンクをクリックしたときにブラウザに渡されるだけの、comoji.io や他のプロジェクトのアドレスがいくつかです。
整えた説明ではなく、実際に見えるものと一致させるために、正直な注意点を 2 つ挙げておきます。api.giphy.com は完全な URL として保存されているのではなく、コードの中でホスト名から組み立てられるため、最初の一覧には表示されません。strings -a … | grep -Eo '[a-z0-9.-]*giphy\.com' で直接検索してください。このパターンはホスト名だけに一致するので、同じくバンドルに含まれている API キーは表示されません。また、同梱している Sparkle のアップデートフレームワークは Contents/Frameworks の中に独自のドキュメント URL(sparkle-project.org、andymatuschak.org)を含んでいますが、これはサードパーティのライブラリ内の文字列であって、Comoji が接続するホストではありません。
ステップ 4:遮断して何が動かなくなるかを見る
これがいちばん強力なテストです。どの出力も信用する必要がないからです。送信方向のファイアウォールをインストールします。LuLu は無料のオープンソースで、Little Snitch は長く使われている有料の選択肢です。すべての送信接続で通知するように設定し、Comoji からの通信をすべて恒久的に拒否します。
絵文字の自動補完は、そもそもネットワークを必要としていないので、これまでとまったく同じように、ずっと動き続けます。動かなくなるのは、アップデートの確認と、まだキャッシュされていないステッカーや GIF の画像のダウンロードだけです。もしローカル処理という主張が嘘なら、ここで派手に破綻するはずです。
ステップ 5:App が本当に私たちのものか確認する
ここまでのテストはすべて、ディスク上にあるコピーを対象にしています。そのコピーが Apple の公証を受けたものであり、その後誰にも改変されていないことも確認しておく価値があります:
codesign -dv --verbose=4 /Applications/Comoji.app
spctl -a -vvv -t exec /Applications/Comoji.app
codesign -d --entitlements - /Applications/Comoji.appcodesign は App の署名に使われている Developer ID を表示し、spctl は source=Notarized Developer ID とともに accepted と答えるはずです。エンタイトルメントの出力は、そもそも App に何が許可されているかを示します。
私たちの側で行っていること
自分で行える検証は約束よりも価値がありますが、約束もどこかで担保されているべきです。App のすべてのビルドで、2 つのことが実行されています:
- Comoji が接続しうるホストの完全な一覧はソースコード内で宣言されていて、ネットワーク通信の全体像 として公開し、App 内の「環境設定 → プライバシー」にも表示しています。その一覧に記載されていないホストに App が接続できる場合、自動テストがビルドを失敗させます。
- もうひとつのテストは、実際にキー入力を扱うコード(イベントタップ、トークンバッファ、照合処理、挿入処理)を走査し、そこにネットワーク API やリモート URL が含まれていればビルドを失敗させます。入力内容を見る Comoji の部分にはネットワーク処理が一切含まれておらず、こっそり追加されることもありません。
同じページには、入力処理部分のオープンソース化や有料の第三者レビューの依頼など、私たちが *行わない* と決めたこととその理由も記録しています。推測ではなく、その理由を踏まえて判断していただけます。
これらを試して、私たちが公開している内容と矛盾するものが見つかったら、support@comoji.io までメールしてください。主張がひっそりと間違ったままになるより、ページや App を修正するほうを選びます。
App がそれらの権限で実際に何をしているかについては、機能ページで Comoji が使えるすべての App とサイト と、使いたくない場所で黙らせておける App ごと、Web サイトごとの無効化リスト を紹介しています。
よくある質問
Mac の App がキー入力をどこかに送信しているかどうかを確かめるには?
ターミナルで lsof -nP -i -a -p "$(pgrep -x AppName)" を実行すると、その App が現在開いているネットワーク接続が一覧表示されます。nettop -P -p "$(pgrep -x AppName)" では送受信した累積バイト数がわかります。決定的なテストとしては、LuLu や Little Snitch のような送信方向のファイアウォールをインストールして App を完全に遮断し、機能が動き続けるかどうかを確認してください。
Comoji は入力内容をアップロードしますか?
いいえ。Comoji にはアカウントも、テレメトリも、アナリティクスも、クラッシュレポーターもありません。キー入力はコロンで始まるショートカットを検出するためだけに短時間メモリ上のバッファに保持され、ディスクに書き込まれることも送信されることもありません。App が接続するホストはちょうど 4 つで、アップデートフィード、Google のステッカー画像 CDN、そして /gif ピッカーを使ったときの GIPHY の API と CDN です。
Comoji にアクセシビリティと入力監視が必要なのはなぜですか?
入力監視は、:fire のようなショートカットを入力したことに気づくために使います。アクセシビリティは、フォーカスのあるテキスト欄とカーソルの位置を見つけてポップアップを正しい場所に表示し、その欄に絵文字を入力するために使います。どちらもテキスト欄の内容を読むためには使われず、パスワードのようなセキュアな欄は完全に無視されます。
Comoji はオープンソースですか?
現時点ではオープンソースではありません。comoji.io のセキュリティのページ では、その判断と理由を記録し、ネットワーク通信の全体像を公開し、ダウンロードした公証済みのバイナリに対してローカル処理の主張を検証する手順をコマンド付きで紹介しています。
Mac 版 Comoji を無料でダウンロード
Slack や Discord と同じ :emoji: 補完を、Mac のどこでも。無料。