ZCodeはGitの全履歴をAliyun OSSに密かにアップロードしている

ZCodeはGitの全履歴をクラウドに密かにアップロードしている

要点: ZCode(智譜AIの公式AIコーディングデスクトップ)は、ログインしている間、ワークスペース全体(完全な .git 履歴、LFSキャッシュ、reflog、グローバルアプリ設定を含む)を自動的にパッケージ化し、サーバーから提供されたRSA公開鍵で暗号化して、その暗号文をAliyun OSSに直接アップロードします。このアップロードパイプラインは無条件に実行され、UIの切り替えスイッチではオフにできず、復号鍵は智譜のバックエンドにのみ存在するため、ユーザーがローカルでデータを復号することはできません。


発端: pending 状態でスタックした313 MBの暗号化アーカイブ

  • ~/.zcode ディレクトリ(ZCodeのデータルート)が700 MB以上を占有していた。
  • ~/.zcode/v2/checkpoints/ 内に313 MBの baseline.enc ファイルが見つかり、それには345 MBのワークスペーススナップショットが含まれていること、および564回のアップロード試行に失敗していることを示すメタデータが記録されていた。
  • このスナップショットは、リポジトリ全体のサイズが10 GBある商用プロジェクトのものであり、node_modules を除外した後のパッケージ化されたペイロードは345 MB、つまりほぼすべてが知的財産であった。

アップロードフロー: クライアント側でのパッケージ化 → OSSへの直接POST

リバースエンジニアリングされた app.asar は、2段階のパイプラインを明らかにしている:

  1. 認証情報の要求 – クライアントは https://zcode.z.ai/api/v1/snapshot/upload-credential にPOSTする。サーバーは以下を返す:
    • スナップショットID
    • RSA公開鍵(エンベロープ暗号化に使用)
    • 最大サイズ制限
    • Aliyun OSSのフォーム認証情報(policy, x-oss-signature
    • 動的なオブジェクトキー
  2. 直接アップロード – クライアントは tar.gz アーカイブを作成し、AES-256-CTRで暗号化し、提供された公開鍵を使用してRSA-OAEP-SHA256で対称鍵をラップし、結果として生成された *.enc ファイルをAliyun OSSに直接POSTする。その後、OSSは智譜のバックエンドにコールバックして受信を確認する。

ネットワークトレースは、zcode.z.ai と2つのAliyun OSSノードの両方への永続的なHTTPS接続を示している。

暗号化鍵はサーバーのみが所有している

この実装は、教科書通りのエンベロープ暗号化に従っている:

keyId: "<version>",
keyWrapAlgorithm: "rsa-oaep-sha256",
publicKeySpkiPem: "<server‑provided PEM>"
  • コンテンツは、一時的なAES-256-CTR鍵でローカルに暗号化される。
  • AES鍵は、認証情報要求時にサーバーから提供されたRSA公開鍵でラップされる。
  • 対応する秘密鍵はクライアントマシンには決して現れず、ローカルで鍵をアンラップしようとしても失敗する。

結果:

  • ディスクに保存された313 MBの暗号文は、ユーザーやZCodeクライアントでは復号できない。
  • 智譜のバックエンドのみがスナップショットを復号でき、実質的にサービス側がリポジトリ履歴全体に対する無制限の読み取りアクセス権を持っていることになる。

実際にアップロードされるもの: 86%が .git

パッケージ化中に生成されたマニフェスト(プレーンテキストで保存)には、42,411個のファイルがリストされている。サイズの内訳:

パス サイズ ペイロードの割合 主な内容
.git/lfs/ 196.1 MB 56.8 % ダウンロードされたすべての巨大バイナリアセット
.git/objects/ 102.2 MB 29.6 % 完全なコミットオブジェクトストア(コミット、ツリー、ブロブ)
.git/logs/ 0.6 MB 0.2 % Reflog、ローカルブランチ履歴
ソースコードとドキュメント ~46.2 MB 13.4 % src/、設定ファイル、ドキュメント

つまり、アップロードされたペイロードの 86.6% は生のGitデータであり、以下が露出している:

  • 後に削除された過去のAPIキーやシークレット。
  • 未リリースの機能が明らかになる未プッシュのブランチ名。
  • 内部ホスト名やリポジトリURLを含む .git/config のエントリ。

追加のマニフェスト(repo_snapshot_extra_manifest)は、グローバルなZCode設定ファイルをハッシュ化し、すべてのスナップショットにバンドルしている。

UIの切り替えスイッチではキャプチャを停止できない

UIには2つの設定が表示されている:

設定 意図された効果 実際の効果
Optimize Experience (optimizeAgentExperienceEnabled) テレメトリ/モデル学習データの送信抑制 モデル学習用のデータ送信を無効にするだけ。スナップショットのキャプチャは継続される
Repo Snapshot Indexing (repoSnapshotIndexingEnabled) スナップショット機能を無効化 すでにアップロードされたスナップショットのサーバー側インデックス作成を停止するだけ。ローカルでのパッケージ化とアップロードは継続される

コードを調査すると、スナップショットのサイドカーは 起動時に無条件で インスタンス化されていることがわかる。唯一のゲート条件は tokenProvider からの有効なJWTトークンである。キャプチャのトリガーは、LLMプロンプトの前(captureBeforePrompt)および repo-wiki-update とタグ付けされたタスク完了時に発生する。1回のセッションで数十回のキャプチャイベントが生成される可能性がある。

プライバシーポリシーの不備

ZCodeのプライバシーポリシーには、「会話中に送信されたテキスト、ファイル、コード」を収集すると記載されており、これはLLMのコンテキストとしては標準的である。しかし、ポリシー、FAQ、変更履歴には、自動的なワークスペース全体のパッケージ化やGit履歴の流出については一切言及されていない。唯一関連する条項は、「最適化プログラムはデフォルトでオフになっており、同意なしに学習に利用されることはない」という一般的な注記のみである。

防御策: チェックポイントディレクトリをロックする

保留中のアーカイブを削除しても、新たなキャプチャがトリガーされるだけである(再試行カウンターが増加する)。確実な緩和策は、~/.zcode/v2/checkpoints ディレクトリを不変(immutable)にし、クライアントが新しいアーカイブを書き込めないようにすることである。

macOS

rm -rf ~/.zcode/v2/checkpoints
mkdir -p ~/.zcode/v2/checkpoints
chflags uchg ~/.zcode/v2/checkpoints   # 不変フラグを設定
# 確認: touchコマンドが「Operation not permitted」で失敗することを確認

Linux

rm -rf ~/.zcode/v2/checkpoints
mkdir -p ~/.zcode/v2/checkpoints
sudo chattr +i ~/.zcode/v2/checkpoints   # 不変属性を設定
# 確認: touchコマンドが「Operation not permitted」で失敗することを確認

影響: キャプチャパイプラインはアーカイブを書き込めなくなると中断されるため、データはアップロードされない。トレードオフとして、ZCodeの「チェックポイントのロールバック/タイムライン」UI機能が失われるが、通常のチャット、オートコンプリート、ツール実行は機能し続ける。元に戻すには、不変フラグを解除する(macOSでは chflags nouchg、Linuxでは chattr -i)。


コミュニティの反応と公式回答

  • Hacker Newsのコメントでは、他のAIエージェントがドットファイルを読むことへの懸念、サンドボックス化の無意味さ、中国のAIベンダーに対する不信感が強調された。
  • 智譜の声明(コメント欄にスクリーンショットへのリンクあり)は、この動作はローカルリポジトリのインデックス作成と一時的なWiki生成を目的とした初期リリースの「コードベースインデックス作成」機能に起因するものだと主張した。声明では、アップロードされたデータはWiki生成直後に破棄されると断言し、問題は修正済みであるとして謝罪し、ユーザーに対して1週間分のクォータをリセットした。
  • 批判者は、声明(一時的でデータは破棄される)と技術的な証拠(サーバーが保持する鍵でOSSに永続的に暗号化アップロードされる)との間の矛盾を指摘している。

結論

ZCodeのバックグラウンドプロセスは、ログインしているユーザーのワークスペース全体(完全なGit履歴を含む)をキャプチャし、ユーザーがオプトアウトできない状態でサードパーティのクラウドに暗号化してアップロードしている。暗号化鍵は智譜のサーバーにのみ存在するため、サービス側はいつでもデータを復号できる。このレベルのデータ収集を受け入れられないユーザーは、さらなる流出を防ぐためにZCodeのチェックポイントディレクトリをロックする(またはアプリをアンインストールする)べきである。

Sources

関連