ニュース

ZCodeのGit履歴無断アップロード|点検の3手順【2026年9月】

ZCodeのGit履歴無断アップロード|点検の3手順【2026年9月】

この記事の結論

ZCodeのGit履歴無断アップロード問題を一次情報で整理。313MB・42,411ファイルの内訳、設定が効かなかった理由、Claude Code・Codex・Cursorとの比較、環境を30分で点検する3手順まで。

必要なものは3つです。ローカルに立てるプロキシ1本、そのCA証明書1枚、30分の作業時間。この3つがあれば、自分が使っているコーディングエージェントが「いつ・どこへ・何バイト送っているか」は自分の手で確認できます。手順は次の章から順番に書きます。

先に、2026年9月23日時点で一次情報から確認できる数字だけを置いておきます。Z.ai(智譜)のコーディングエージェント ZCode は、ログイン中にワークスペースを丸ごとアーカイブ化して暗号化し、Aliyun OSS(Alibaba Cloud のオブジェクトストレージ)へ直接アップロードしていました。逆解析した開発者 ferstar が2026年9月18日に公開した計測では、商用プロジェクト1件のスナップショットが暗号化後313MB・42,411ファイル、そのうち .git ディレクトリだけで86.6%を占めていました。

2026年9月23日時点で確認できていること

  • 送られていたのは作業中のソースだけではなく、.git/objects(全コミット履歴)、.git/lfs(LFSキャッシュ)、.git/logs(reflog)、そしてZCodeのグローバル設定ファイル。
  • 暗号化はAES-256-CTR+RSA-OAEP-SHA256の封筒方式。RSA公開鍵はサーバーが都度配布し、秘密鍵はクラウド側にしかない。つまり自分のディスク上にある暗号文を、ユーザーもZCodeクライアントも復号できない。
  • UI上の2つのトグル(「Optimize Experience」「Repo Snapshot Indexing」)を切っても、ローカルでのパッケージ化とアップロード自体は止まらなかった。
  • Z.aiは公開当日の2026年9月18日に声明を出し、原因はコードベースのインデックス作成とWiki生成機能であること、初期リリース期間は既定で有効だったこと、修正済みであることを説明。2026年9月20〜21日にZCodeをApache-2.0でGitHubに公開した。
  • ただし公開されたリポジトリのコミットは2本だけで、開発履歴は平坦化されている(筆者がGitHubの公開APIで確認、2026年9月23日時点)。

以下は事件の要約より「自分の環境ではどうか」を確かめる側に重心を置きます。手順自体はClaude Code・Codex CLI・Cursor・社内製エージェントにそのまま使えます。

点検の3手順:プロキシ1本で外向き通信を可視化する

点検の3手順:プロキシ1本で外向き通信を可視化する
点検の3手順:プロキシ1本で外向き通信を可視化する

用意するものは、mitmproxy(またはCharles、Proxymanなど任意のHTTPSインターセプトツール)、その生成するCA証明書、そして検証用の使い捨てリポジトリです。本番の業務リポジトリで最初の検証をしないでください。理由は後半の失敗パターンで説明します。

手順1:ローカル状態を先に見る(5分)

ネットワークを覗く前に、エージェントが自分のホームディレクトリに何を溜めているかを見ます。アップロード系の機能は、ほぼ例外なくローカルに「送信待ちキュー」や「チェックポイント」を残すためです。ZCodeの場合は ~/.zcode/v2/checkpoints/ に状態ファイルが平文で置かれており、ferstarはここに564件の失敗アップロード記録が残っていたことを報告しています。

# エージェントの作業ディレクトリのサイズを一覧する
du -sh ~/.zcode ~/.claude ~/.codex ~/.cursor 2>/dev/null | sort -h

# 50MBを超えるファイルが転がっていないか(アーカイブ=送信待ちの可能性)
find ~/.zcode ~/.claude ~/.codex -type f -size +50M 2>/dev/null | head -20

# JSON状態ファイルを機械的に眺める
grep -ril "snapshot\|upload\|checkpoint" ~/.zcode 2>/dev/null | head -20

動作環境:macOS 15 / Ubuntu 24.04 のいずれでも同じ。du find grep は標準コマンドのみ。注意:本番環境で使用する前に、必ずテスト環境で動作確認してください。

ポイントは、数百MB級のアーカイブは隠せないということです。モデルにコンテキストを渡すだけなら、リポジトリと同じサイズのファイルがローカルに生まれる理由がありません。ディスク使用量は、仕様書より正直です。

手順2:プロキシを立ててエージェントを通す(15分)

次に、実際の外向き通信を記録します。mitmproxyは起動時にCA証明書を ~/.mitmproxy/ に生成し、配布用のPEMファイルは mitmproxy-ca-cert.pem という名前になります(mitmproxy公式ドキュメント)。

# 通常モードでプロキシを起動し、全フローをファイルに保存する
mitmdump --mode regular -p 8080 -w /tmp/agent-egress.flows

# 生成されたCA証明書の場所を確認
ls -l ~/.mitmproxy/mitmproxy-ca-cert.pem

エージェント側をこのプロキシに向けます。Claude Codeは企業ネットワーク向けの変数が公式に定義されており、HTTPS_PROXY / HTTP_PROXY / NO_PROXY と、追加CA証明書の NODE_EXTRA_CA_CERTS を読みます(Claude Code公式ドキュメント「Enterprise network configuration」)。SOCKSプロキシには対応していない点も明記されています。

# Claude Code を検証用プロキシ経由にする(公式に定義された変数のみ使用)
export HTTPS_PROXY=http://127.0.0.1:8080
export NODE_EXTRA_CA_CERTS="$HOME/.mitmproxy/mitmproxy-ca-cert.pem"
export NO_PROXY="localhost,127.0.0.1"

claude --debug
# デバッグ出力は ~/.claude/debug/<session-id>.txt に書かれる。
# CA certs: Appended extra certificates from NODE_EXTRA_CA_CERTS (...)
# の行が出れば証明書を読み込めている。

公式ドキュメントによれば、これらの変数はシェルの起動時に一度だけ読まれます。走っているセッションは後からの変更を拾いません。対話セッション中に /status を実行すると、Proxy行・mTLS client cert行・Additional CA cert(s)行で実際に何が効いているかを確認できます。

手順3:宛先ホストと送信サイズを集計する(10分)

記録したフローは、プロキシを立てずに読み直せます。-n(サーバーを起動しない)と -r(保存済みフローを読む)の組み合わせです。

# 保存したフローを読み直して、宛先ホストと本文サイズを確認する
mitmdump -n -r /tmp/agent-egress.flows

# 並行して、プロキシ設定を無視するプロセスがないかソケットを直接見る
# macOS
lsof -i -nP | grep -i -E "zcode|claude|codex|cursor"
# Linux
ss -tnp | grep -i -E "zcode|claude|codex|cursor"

見るべきは2点だけです。知らないホストが出てこないかと、異常に大きいPOSTがないか。ZCodeのケースでは、資格情報の取得が zcode.z.ai の POST /api/v1/snapshot/upload-credential で行われ、レスポンスにスナップショットID・RSA公開鍵・サイズ上限・OSSのフォーム資格情報・コールバックURLが含まれていました。その後の本体アップロードはZCode自身のサーバーを経由せず、HTTP POSTフォームでAliyun OSSへ直接飛びます。「ベンダーのドメインしか見ていない」監査では、この経路を見落とします。

ソケットを直接見る工程を省かないでください。プロキシ環境変数を読まないクライアントは珍しくありません。Claude Codeの公式ドキュメントも、WebSocket接続は localhost や 127.0.0.0/8 にはプロキシを通さないと明記しています。環境変数は「お願い」であって「強制」ではない、という前提で見るのが安全です。

ZCodeが実際に送っていたものの内訳

ZCodeが実際に送っていたものの内訳
ZCodeが実際に送っていたものの内訳

ferstarが公開した1スナップショットの内訳は次のとおりです。合計345MB(非圧縮)、暗号化後313MB、42,411ファイル。

内容 サイズ 割合 そこに含まれうるもの
.git/lfs/ 196.1MB 56.8% LFSで管理された大容量アセット・メディア
.git/objects/ 102.2MB 29.6% 全コミット履歴。削除済みファイルの過去版を含む
ソースコード・ドキュメント 約46.2MB 13.4% 作業ツリーの現在の内容
.git/logs/ 0.6MB 0.2% reflog。ローカルブランチの操作履歴

ここが事件の核心です。作業ツリーだけなら13.4%でした。残りは履歴です。.git/objects と reflog が出ていくということは、「あとで消したもの」も一緒に出ていくということを意味します。コミットしてしまってから削除した .env、リベースで消したつもりの検証用トークン、force pushで上書きしたつもりのブランチ、社内のレビューで却下された実装案。これらはワーキングツリーには存在しませんが、オブジェクトデータベースには残っています。

トリガーも一度きりではありませんでした。ferstarの解析では、キャプチャは captureBeforePrompt(プロンプト送信前)と repo-wiki-update(タスク完了時)で発火し、1セッションで最大62回のキャプチャイベントが記録されています。

鍵の置き場所が示していたこと

暗号化そのものは真っ当です。tar.gzをAES-256-CTRで暗号化し、その対称鍵をRSA-OAEP-SHA256でラップする封筒暗号は、標準的な設計です。問題は鍵の非対称性でした。暗号化に使うRSA公開鍵はサーバーがその場で配り、秘密鍵はクラウドにしか存在しません。結果として、ユーザーは自分のディスクに置かれた数百MBの暗号文を復号できず、ZCodeクライアント自身にも復号できませんでした。ferstarはこの構造を「サーバーだけが使える鍵は、サーバーがいつでもあなたのコードを読めるようにする、という目的にしか役立たない」と表現しています。

トグルを切っても止まらなかった理由

トグルを切っても止まらなかった理由
トグルを切っても止まらなかった理由

ユーザーが自衛できなかった点が、この件を単なるバグ報告から信頼の問題に変えました。ZCodeのUIには関係しそうなトグルが2つありましたが、どちらもアップロードを止めるスイッチではありませんでした。

設定 内部キー 実際に制御していたもの アップロードは止まるか
Optimize Experience optimizeAgentExperienceEnabled モデル学習にデータを使う許可の可否 止まらない
Repo Snapshot Indexing repoSnapshotIndexingEnabled サーバー側でのインデックス作成の可否 止まらない

「学習に使わない」と「送らない」は、まったく別のことです。この2つを同じ意味だと思い込んだまま設定画面を閉じたユーザーは多かったはずで、ここが最も再現性の高い教訓だと思います。社内でAIツールを審査するとき、チェックすべきは「学習利用の可否」ではなく「送信の有無と範囲」です。

暫定の自衛策として、チェックポイント用ディレクトリを書き込み不可にする方法(Linuxの chattr +i、macOSの chflags uchg)が共有されました。ロールバックUIは使えなくなりますが、パッケージ化の起点は潰せます。緊急避難であり、恒久対策はベンダー側の修正です。

Z.aiの対応と、OSS公開で分かったこと

Z.aiの対応と、OSS公開で分かったこと
Z.aiの対応と、OSS公開で分かったこと

Z.aiの反応は速い部類でした。ferstarの記事公開と同じ2026年9月18日の17:44に声明を出し、要旨は次のとおりです。アップロードはコードベースのインデックス作成とWikiページ生成のためのもので、生成後にデータは即時削除していた。当該機能は初期リリース期間に既定で有効だった。問題はすでに修正した。加えて、中国工業情報化部系の標準化シンクタンクであるCAICTとセキュリティ企業NSFOCUSによる第三者評価を実施した、としています。

バージョンの区切りも示されました。ferstarが解析した対象は3.12.3、アップロードのパイプラインが削除されたのが3.14.0です。upload-credential エンドポイントは404を返すようになりました。

そして2026年9月20〜21日、ZCodeがGitHubで公開されました。ここは自分で確かめられるので、公開APIを叩いて確認しました。

# 誰でも再実行できる確認コマンド(読み取りのみ)
curl -s https://api.github.com/repos/zai-org/ZCode \
  | python3 -c "import sys,json;d=json.load(sys.stdin);print(d['created_at'], d['license']['spdx_id'])"

curl -s "https://api.github.com/repos/zai-org/ZCode/commits?per_page=10" \
  | python3 -c "import sys,json;[print(c['sha'][:8], c['commit']['author']['date'], c['commit']['message'].splitlines()[0]) for c in json.load(sys.stdin)]"

2026年9月23日時点の結果は、リポジトリ作成が2026-09-20、ライセンスはApache-2.0、コミットは2本だけ(Initial commit と feat: open source)でした。つまり開発履歴は平坦化されており、問題のアップロード用サイドカーがどう実装され、どう削除されたかを差分で追うことはできません。監査可能性という意味では、ソース公開の効果は限定的です。

履歴を送っていたツールが、自分の履歴は出さずに公開された形です。「OSS公開=検証可能」ではないという実例として覚えておく価値があります。独立監査フォーク(ZCodium)も立ち上がっており、コミュニティ側の検証はここから始まる段階です。

Claude Code・Codex CLI・Cursorは何をどう規定しているか

Claude Code・Codex CLI・Cursorは何をどう規定しているか
Claude Code・Codex CLI・Cursorは何をどう規定しているか

比較の目的は「どれが安全か」を決めることではなく、公式ドキュメントで何が約束されているかを同じ軸で並べることです。約束されていない挙動は、手順1〜3で自分で確かめるしかありません。

観点 Claude Code Codex CLI Cursor ZCode(3.12.3時点)
リポジトリ丸ごとの自動アップロード 公式ドキュメントに記載なし。送信対象はプロンプトとモデル出力と説明 公式ドキュメントに記載なし ファイル内容を一時キャッシュすると明記 あり(ワークスペース全体+.git)
.git の扱い 個別の規定なし workspace-writeサンドボックスで .git .agents .codex を読み取り専用に保護 個別の規定なし スナップショットに全量を同梱
ネットワークの既定 到達先ホストを公式が一覧化。非必須通信は CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC で停止可 サンドボックス内のネットワークアクセスは既定で無効。network_access = true で明示的に解放 公開ドキュメントに一覧なし ログイン中に自動送信
学習利用 Free/Pro/Maxは設定がオンのとき対象。Team/Enterprise/APIは既定で学習しない ビジネス向け条件では既定で学習しない Privacy Modeオンで学習しない。オフなら学習に使う場合がある 学習には使っていないと説明
保持期間 消費者は学習許可で5年・不許可で30日、商用は30日。条件を満たす組織はZDR 条件を満たす組織はZDRを選択可 Privacy Modeオンで全プロバイダとZDR契約 生成後に即削除と説明

この表でCodexが明確に勝っている観点があります。サンドボックスの既定です。workspace-write モードは .git を含むパスを再帰的に読み取り専用として保護し、ネットワークアクセスは既定で無効、解放するには設定ファイルに明示的に書く必要があります(OpenAI Codex公式ドキュメント「Sandbox and approvals」)。「既定で閉じていて、開けたことが設定ファイルに残る」という形は、ポリシー文よりも強い停止線です。

# ~/.codex/config.toml — 既定値を明示的に書いて、差分で気づけるようにする
approval_policy = "on-request"
sandbox_mode    = "workspace-write"

[sandbox_workspace_write]
network_access = false   # 既定で無効。true にした変更はレビュー対象にする

一方でClaude Codeは、到達先ホストを公式が表で網羅している点が監査しやすさで勝ります。api.anthropic.com や registry.npmjs.org といったホストが用途つきで列挙されているため、手順3で取ったキャプチャと1対1で突き合わせられます。ローカル保存についても、セッション記録が ~/.claude/projects/ に平文で既定30日保存され、cleanupPeriodDays で調整できると明記されています(Claude Code公式ドキュメント「Data usage」)。平文で残ること自体はリスクですが、書いてあるリスクは管理できます。

Cursorは、公式のData Useページで「レイテンシとネットワーク使用量を減らすためにファイル内容をサーバー上で一時的にキャッシュする」「キャッシュはクライアント生成の鍵で暗号化され、恒久保存はしない」と説明しています。Privacy Modeがオフの場合は、コードベースのデータやプロンプトを保存し、AI機能の改善とモデル学習に使う場合があるとも書かれています。送っていること自体は明示されているので、判断材料としては成立しています。ZCodeとの決定的な違いは、送信の存在が文書化されていたかどうかです。

社内導入前チェックリスト:9項目

審査シートに落とすなら、次の9項目を「ドキュメントのどこに書いてあるか」とセットで埋めるのが実務的です。埋まらない欄がある時点で、それが検証タスクになります。

  1. 送信対象の範囲:作業ツリーのみか、リポジトリ全体か、.git を含むか。公式ドキュメントの該当箇所を引用で控える。
  2. 送信のトリガー:ユーザー操作時のみか、バックグラウンドで定期的に走るか。ZCodeは1セッション62回だった。
  3. 宛先:ベンダーのドメインだけか、オブジェクトストレージへ直送する経路があるか。
  4. オプトアウトの実効性:「学習に使わない」トグルと「送信しない」トグルが分かれているか。分かれていないなら、それは送信を止められないという意味。
  5. 復号可能性:暗号化されたローカルアーティファクトを、ユーザー側の鍵で復号できるか。できないなら、それは自分のデータではない。
  6. ローカルの残留物:セッション記録・キャッシュ・チェックポイントの保存先と保持期間、平文かどうか。
  7. 保持期間とZDR:既定の保持日数と、ゼロデータ保持の適用条件・申請経路。
  8. ネットワークの既定:サンドボックスのegressが既定で閉じているか、開ける操作が記録に残るか。
  9. 再検証の手順:バージョンアップのたびに手順1〜3を回す担当と頻度。修正されたのは3.14.0であり、固定されていないバージョンは常に動く前提で扱う。

AIエージェント全般の権限設計としては、送信範囲の話と実行権限の話は必ずセットで詰めることになります。実行側の停止線についてはClaude Code Docker権限プロンプト必須化の理由とClaude Codeサンドボックスmaskモードの解説で扱っています。承認フロー自体を迂回された事例としてはGhostApproval脆弱性の解説も合わせて読むと、今回の「設定が効かない」構図が一般的な問題であることが分かります。

【要注意】この検証でつまずきやすい3つの失敗

失敗1:本番リポジトリでいきなり検証する

❌ 業務で使っている本物のリポジトリを開いて、プロキシを立てて「何が飛ぶか見てみよう」とする。
⭕ 使い捨てのリポジトリを作り、識別可能なダミー文字列をコミットしてから削除し、その文字列が外に出るかを見る。

なぜこれが重要か:検証の最中に、そのツールが本当に履歴を送るなら、検証行為そのものが情報流出になります。ZCodeの件では、検証者が意図せず商用プロジェクトのスナップショットを作らせていました。git init して SENTINEL-ランダム文字列 をコミットし、次のコミットで削除する。オブジェクトには残るので、キャプチャをそのトークンで grep すれば履歴送信の有無が一発で分かります。

失敗2:プロキシ環境変数を設定しただけで「通した」と思い込む

❌ export HTTPS_PROXY=... を打って、キャプチャが空なので「何も送っていない」と結論する。
⭕ 証明書が読み込まれたことをログで確認し、さらに lsof / ss で実際のソケットを見る。

なぜこれが重要か:プロキシ変数を尊重しないクライアント、独自のCAバンドルを使うクライアント、証明書ピンニングをしているクライアントでは、キャプチャが空になります。「空=送っていない」ではなく「空=通せていない」の可能性が常にあります。Claude Codeなら claude --debug のログに CA certs: Appended extra certificates from NODE_EXTRA_CA_CERTS が出るか、/status のAdditional CA cert(s)行を見るのが確実です。

失敗3:「学習に使わない」の一文で審査を終える

❌ ベンダーのFAQに「お客様のコードを学習に使用しません」とあるのを確認して、審査完了とする。
⭕ 「送信するか」「どこへ送るか」「どれだけ保持するか」「ユーザー側で復号できるか」を別々の欄として埋める。

なぜこれが重要か:今回の2つのトグルが示したとおり、学習利用の可否と送信の有無は独立した論点です。Z.aiも学習には使っていないと説明しており、その説明自体は争点ではありませんでした。問題は、学習に使わないまま、全履歴がクラウドに置かれていたことです。プロンプトインジェクション経由の情報持ち出しまで含めた多層の考え方はプロンプトインジェクション対策の記事にまとめています。

よくある質問

ZCodeを使っていました。過去に送られたデータはどうなりますか

Z.aiは、アップロードされたデータはインデックスとWiki生成の後に即時削除しており、学習には使っていないと説明しています。CAICTとNSFOCUSによる第三者評価でも、コードは削除済みでクラウド側に保持されていないという結果が示されたと報じられています。ただしこれは第三者評価を含むベンダー側の説明であり、ユーザーが自分で検証できる性質のものではありません。履歴に認証情報が含まれていた可能性がある場合は、説明を待つよりも該当するトークン・鍵の失効とローテーションを先に実施するのが実務的です。

「暗号化されていた」なら問題は小さいのでは?

暗号化の強度は争点ではありません。争点は鍵の所在です。今回は復号に必要なRSA秘密鍵がサーバー側にのみ存在し、ユーザーは自分のディスクにある暗号文を開けませんでした。第三者による通信傍受には強い一方で、受け取った側が読めるかどうかについては何の制限にもなっていません。「暗号化済み」は、送信先を信頼できるかという問いを置き換えません。

Claude CodeやCursorでも同じことが起きますか

2026年9月23日時点で、Claude Codeがリポジトリ全体や .git 履歴を自動でアップロードするという記載は公式ドキュメントにありません。Cursorは、レイテンシ削減のためにファイル内容を一時キャッシュすると公式に明記しています。いずれも仕様として文書化されている範囲であり、ZCodeのように文書化されないまま送られていたケースとは性質が異なります。ただし「文書に書かれていない=送っていない」の証明にはならないため、本記事の手順1〜3で確かめる価値はあります。

チームで最低限やるべきことを1つ挙げるなら

使っているコーディングエージェントごとに、「送信範囲」「トリガー」「宛先」「オプトアウトが送信を止めるか」の4欄を公式ドキュメントの引用で埋めることです。埋まらない欄が検証タスクになり、検証は本記事の3手順で30分程度です。導入判断より先に、この4欄が埋まっているかを確認してください。

OSSとして公開されたなら、もう安全と考えてよいですか

公開リポジトリのコミットは2本のみで、開発履歴は平坦化されています(2026年9月23日時点、GitHub公開APIで確認)。現在のコードは読めますが、問題のアップロード機能がどう実装され、どう削除されたかを差分で追うことはできません。ソース公開は監査可能性の必要条件であって十分条件ではない、というのが今回の教訓です。独立した監査フォークやコミュニティのレビューが積み上がるまでは、公開の事実だけを根拠に判断を変えないのが妥当です。

結論

今回の件で一般化できることは3つです。第1に、「学習に使わない」は「送らない」ではない。設定画面の言葉ではなく、送信の有無と範囲を審査軸にすること。第2に、履歴は作業ツリーより危険。.git が送信対象に含まれるなら、削除したはずの認証情報も一緒に出ていきます。第3に、egressは既定で閉じているものを選ぶ。Codex CLIのようにサンドボックスのネットワークが既定で無効で、解放が設定ファイルに残る形は、ポリシー文より強い停止線になります。

そして今日できることは1つだけです。手元のエージェントに対して、使い捨てリポジトリとプロキシで30分の検証を回すこと。ドキュメントに書いていないことを確かめられるのは、いまのところこの方法だけです。

運営元 Uravation よりAIエージェントを構想から本番運用まで進める順番と、体制・KPIの決め方をまとめた資料を無料で公開しています。 AIエージェント導入ロードマップを受け取る(無料)

参考・出典

あわせて読みたい

この記事を読んで、社内のAIツール審査基準を整理したくなった方へ

UravationではAIエージェント導入の研修・コンサルを行っています。送信範囲の審査シート作成や、開発チーム向けの検証ワークショップもご相談いただけます。

著者:佐藤傑(さとう・すぐる)。株式会社Uravation代表取締役。X(@SuguruKun_ai)フォロワー約10万人。著書『AIエージェント仕事術』。

Need help moving from reading to rollout?

この記事を読んで導入イメージが固まってきた方へ

Uravationでは、AIエージェントの要件整理、PoC設計、社内導入、研修まで一気通貫で支援しています。

この記事をシェア

X Facebook LINE

※ 本記事の情報は2026年9月時点のものです。サービスの料金・仕様は変更される可能性があります。最新情報は各サービスの公式サイトをご確認ください。

関連記事