AI コーディング用のデスクトップアプリが、作業中のコードをどこまで見ているのか。そんな不安を、かなり具体的な形で突きつけたのが今回の話だ。調べたのは Zhipu の公式アプリ「ZCode」で、利用者のワークスペースや Git 履歴が、気づかないうちにクラウドへ送られているのではないかという疑いが出発点になっている。単なるテレメトリの話ではなく、実際にどのファイルが集められ、どう暗号化され、どこへ送られるのかまで追っているのが重い。しかも、止めるつもりで設定画面を触っても止まらない、というのがいちばん不気味だ。
元記事の著者は、ディスク容量を整理している最中に ~/.zcode が 700MB を超えていることに気づいた。中を追うと、v2/checkpoints/ に 313MB の .enc ファイルが残っており、その横に状態メタデータが置かれていた。そこにはワークスペースのパス、暗号化後サイズ 313070842 バイト、元のワークスペースサイズ 345549173 バイト、種類が baseline であること、さらに失敗回数が 564 と記録されていた。著者の読みでは、ZCode は開いている商用プロジェクトをスキャンし、node_modules など一部を除いたうえで、残りの 345MB ぶんをひとまとまりのスナップショットとして圧縮・暗号化していた。リトライに失敗し続け、pending/ に置かれたまま再送を待っていた、というわけだ。
著者はログだけでは送信先の全体像が見えなかったため、アプリ本体の app.asar を解析した。そこで復元された流れはかなりはっきりしていて、ZCode クライアントがまず https://zcode.z.ai にある POST /api/v1/snapshot/upload-credential を叩き、スナップショット ID、RSA 公開鍵、最大サイズ、Aliyun OSS 用のフォーム認証情報、コールバック先を受け取る。次にローカルで tar.gz を作り、AES-256-CTR で暗号化し、RSA-OAEP で鍵を包んだうえで、暗号化済みファイル tar.gz.enc を Aliyun OSS に直接 POST する。アップロード後は OSS 側から Zhipu のバックエンドへコールバックが返り、受領が記録される。著者は実際のソケット接続も確認し、ZCode が zcode.z.ai の IP と Aliyun のストレージノードに継続接続していることを見ている。
記事で強く問題視されているのは、暗号化の鍵の扱いだ。ZCode は使い捨ての共通鍵で中身を暗号化し、その鍵を RSA-OAEP-SHA256 で包む、いわゆる envelope encryption を使っている。ただし、その RSA 公開鍵は毎回サーバーから配られ、対応する秘密鍵は端末にはない。つまり、ローカルに残る 313MB の暗号化ファイルは、ユーザー自身にも ZCode クライアント自身にも復号できない。著者は「もし本当にロールバックや同期のためなら、鍵は Git や Time Machine のようにローカルにあるはずだ」と見ている。
さらに、パッケージ内容の内訳もかなり踏み込んでいる。42,411 ファイルのスナップショットを調べると、 .git/lfs/ が 196.1MB で 56.8%、.git/objects/ が 102.2MB で 29.6%、.git/logs/ が 0.6MB で 0.2%、ソースコードやドキュメントが約 46.2MB で 13.4% だった。つまり、実体の 86.6% は .git 由来だという。しかも、Git の履歴には後で消した API キーや設定、未 push のブランチ名、 .git/config に残る社内ホスト名などが含まれうる。加えて、repo_snapshot_extra_manifest という別のマニフェストが global な ZCode 設定ファイルも束ねるとされる。
設定画面のスイッチも、著者の調査では期待どおりには働かなかった。optimizeAgentExperienceEnabled は「学習への利用を許可するか」だけを制御し、スナップショットの収集・送信は止めない。repoSnapshotIndexingEnabled も、サーバー側の索引付けを止めるだけで、ローカルでのパッケージングとアップロード自体は継続する。起動時には capture/upload の sidecar が無条件に立ち上がり、ユーザー設定で弾く分岐はないという。しかも発火点は、毎回のプロンプト前と、repo-wiki-update 付きのタスク完了時で、ひとつのセッションで最大 62 回もスナップショットが作られた例がある。
著者はプライバシーポリシーも確認している。会話中に送られた text、files、code を収集するとは書いてあるが、ワークスペース全体や Git 履歴を黙ってまとめて送ることには触れていない。そこで対抗策として、~/.zcode/v2/checkpoints を削除しても、すぐに新しいパッケージが再生成されたため、最後はファイルシステムの immutable 属性でディレクトリ自体を書き込み不能にする方法を勧めている。macOS なら chflags uchg、Linux なら chattr +i を使う、という説明だ。
この話でいちばん引っかかるのは、技術的な工夫そのものより、利用者の直感を裏切る構造だと思う。会話の文脈を送る、モデル改善のためにログを取る、というのは多くの AI ツールがやっている。ただ、元記事が示したのはそれよりずっと広い。作業ツリーではなく履歴込みのリポジトリ全体を集め、しかも鍵をサーバー側に置いて、ユーザーが中身を確かめられない形で保持する。これが事実なら、ユーザーの認識している「補助ツール」と、実際に動いている「収集装置」の距離が大きすぎる。
しかも厄介なのは、UI のトグルが安心材料として機能していないことだ。Optimize Experience や Repo Snapshot Indexing という名前を見れば、多くの人はそこを切れば収集が止まると考えるはずだが、記事によれば止まるのはせいぜい学習利用や索引付けの一部で、バックグラウンドの収集そのものは続く。これは単なる説明不足ではなく、意図的に理解しにくく設計されていると受け取られても仕方がない。もし本当にそうなら、UI は操作パネルではなく、心理的なガードレールとして置かれているように見える。
この記事を読んで改めて思ったのは、AI コーディング支援の文脈では「今見えているコード」より「過去に何があったか」のほうが、ずっと価値が高いかもしれないという点だ。.git/objects や .git/lfs が大半を占めるという数字は象徴的で、現在のソースだけでなく、消したはずの秘密情報や失敗した試行錯誤、未公開のブランチ構想まで一緒に持っていかれる。単なるファイル同期より危ないのは、履歴が人間の記憶のように「不要なものを忘れる」ことなく残るからだ。
ここで問題になるのは、収集先がクラウドにあることそのものより、企業の内側で履歴をどう扱うかが利用者の手から離れる点だと思う。個人開発ならまだしも、社内コードや顧客案件では、Git の reflog や .git/config の断片が、そのまま内部事情の漏れ口になることがある。しかも、AI 支援ツールは「入力した文脈に応じて賢くなる」ことを売りにしているので、利用者はつい現在の作業だけを渡しているつもりになる。だが履歴まで吸い込まれるなら、渡しているのは作業ログではなく、プロジェクトの来歴そのものだ。
暗号化は本来、保護のための仕組みだ。ところが元記事の構図では、暗号化が「ユーザーから見えない場所に閉じ込める」ために使われているように見える。端末上には巨大な .enc ファイルが残るが、鍵を持つのはサーバーだけ。ユーザーは保存先も容量も目にしているのに、中身は確認できない。ここが妙に象徴的で、保護の言葉をまといながら、実際には利用者がデータの所在と価値を把握できない状態を作っている。
ただし、ここは断定しすぎないほうがいいとも思う。サーバー側で鍵を持つ設計には、クロスデバイスの復元や障害時の復旧、組織管理上の監査といった理由もありうる。問題は、それらの目的があるなら、少なくとも利用者が理解できる説明と、明確な同意の導線が必要だったはずだということだ。記事から読み取れる限り、その説明は不足している。だからこそ、技術的な安全性の話ではなく、誰が何を見られるのかという統治の話に見えてくる。
著者は最終的に、~/.zcode/v2/checkpoints を immutable にして書き込み自体を拒否させる方法を示している。これは強い。というより、ここまでしないと止まらないのはかなり異常だ。普通のソフトなら、機能をオフにする操作があって、動作確認ができて、必要なら元に戻せる。それができず、ファイルシステム権限で殴るしかないなら、利用者は設定ではなく OS に逃げ込むしかない。
この点は、AI ツール全般にも波及する話だと思う。今後は「何を送るか」だけでなく、「止められるか」「監査できるか」「残る証跡を消せるか」が、導入判断の中心になるはずだ。企業利用では特にそうで、便利さの評価より先に、社内コードを外部サービスへどう流すかを確認しないと危ない。ZCode の件がどこまで他社にも当てはまるかは別問題だが、少なくとも“ローカルにあるから安心”という感覚はもう危うい。ローカルにあるのに、ローカルでは開けない。その不自然さに気づいた人が、次に何を確かめるべきかを示した記事だった。
参考: Inside ZCode: Silently Uploading Your Entire Git History to the Cloud