flawopen.com/Teardowns/cve-2026-102437-deepseek-reasonix-git-filter-command-injection
CVE-2026-102437:Reasonixのdiff表示でGitコマンド注入
細工した.gitattributesと.git/configの組み合わせで、Reasonixのdiff表示時にGit cleanフィルターが動作します。npmは1.39.3、Studioは2.21.0へ更新。[1], [2], [3], [6], [7]
2枚のラベルを比べるだけだと約束する仕分け台を想像してください。荷物には、内容を比べる前に登録済みの補助処理を実行するよう指示する経路メモを付けられます。ReasonixはGitのいくつかの補助機能を無効にしていましたが、ファイル単位のcleanフィルターは別の経路でした。差分画面がGitにファイルの準備を依頼すると、このフィルターが開発者の権限で実行される可能性がありました。[1], [3]
主要な概念と専門用語
.gitattributes- 特定のパスに名前付きフィルターを割り当てられる、リポジトリで追跡されるファイル。[1]
差分ビューアー- Gitにファイルの作業ツリー上の内容を準備させ、コミット済みの内容と比較する機能。[1]
フレームワーク対応
- このガイドで説明する弱点の CWE 参照: CWE-78
根本原因の分析 (Root Cause)
Reasonixは git diff に --no-ext-diff と --no-textconv を付けていましたが、これらは外部diffとテキスト変換を制御するオプションであり、Gitのcleanコンテンツフィルターは無効にしません。ワークスペースの変更ビューは選択されたパスに対して git diff を呼び出します。リポジトリの .gitattributes がそのパスにフィルターを割り当て、ローカルGit設定がドライバーのコマンドを定義していると、比較用blobの生成中にGitがそのコマンドを実行する可能性があります。このCVEはローカル攻撃者を想定し、ユーザーが差分を表示する操作を必要とします。GitLabの開示によると、通常のcloneでは .git/config は転送されません。アーカイブ、同期フォルダー、キャッシュ、事前構築されたdevcontainerには含まれる場合があります。また、同じユーザー権限で動作するローカルエージェントがリポジトリのローカル設定を書き込む経路も説明されています。影響はReasonixユーザーの権限でのローカルコマンド実行であり、GitLab上のリポジトリを開くだけで発生するリモートコード実行ではありません。[1], [3]
ステップ・バイ・ステップの攻撃フロー
ソースコード比較:脆弱 vs 堅牢化
これは説明用の引数ビルダーであり、そのまま適用できるパッチではありません。呼び出し側は .gitattributes、.git/info/attributes、およびグローバル/システムの属性ファイルで選択されるすべての driver を列挙し、完全な走査が成功した場合に限り discoveryComplete を設定する必要があります。この関数は渡された名前を検証してコマンドライン設定の上書きを生成するだけで、driver の検出や確認は行いません。脆弱な呼び出しは GitLab の開示から引用し、防御パターンはメンテナーの指針とマージ済みの強化 PR を独自に統合したものです。[1], [3], [4], [5]
ソース抜粋: desktop/workspace_changes.go
// GitLab Threat Research が引用したソースの呼び出し箇所です。関数全体ではありません。
args := []string{"-C", base, "diff", "--no-ext-diff", "--no-textconv", "--relative", "HEAD", "--", filepath.FromSlash(rel)}
// Go の引数ビルダーを示す例であり、ベンダーパッチの逐語的な再現ではありません。
package gitguard
import (
"errors"
"fmt"
"path/filepath"
"regexp"
)
// 呼び出し側は有効な属性が選択するすべてのフィルターを検出し、完全な集合を渡す必要があります。
// このヘルパーが行うのは、Git の全設定スコープでそれらの driver キーを無効化することだけです。
var filterDriverName = regexp.MustCompile(`^[A-Za-z0-9_-]{1,64}$`)
func hardenedDiffArgs(base, rel string, drivers []string, discoveryComplete bool) ([]string, error) {
if !discoveryComplete {
return nil, errors.New("cannot safely diff: filter-driver discovery failed")
}
args := []string{"-C", base}
seen := map[string]struct{}{}
for _, driver := range drivers {
if !filterDriverName.MatchString(driver) {
return nil, fmt.Errorf("cannot safely diff: unsupported Git filter driver name %q", driver)
}
// Git config のサブセクション名は大文字小文字を区別します。driver 名の大小文字を変換しないでください。
key := driver
if _, ok := seen[key]; ok {
continue
}
seen[key] = struct{}{}
for _, setting := range []string{"clean", "smudge", "process", "required"} {
args = append(args, "-c", "filter."+driver+"."+setting+"=")
}
}
return append(args, "diff", "--no-ext-diff", "--no-textconv", "--relative", "HEAD", "--", filepath.FromSlash(rel)), nil
}
エンジニアリング&システム堅牢化チェックリスト
- ✓✓ プロジェクトの最新案内に従い、Reasonix npmを1.39.3以降、またはReasonix Studioを2.21.0以降に更新します。[2], [6], [7]
- ✓✓ ユーザーが管理するワークスペースでGitを実行するツールでは、リポジトリローカル設定と追跡対象の属性を信頼できない入力として扱います。[1], [3]
- ✓✓ 内容を変換するホストGit呼び出しごとに、
.gitattributes、.git/info/attributes、global/system属性ファイルが選択するフィルターを特定し、system、global、local、worktreeの設定スコープで対応するドライバーキーを無効化します。検出が不完全なら安全側で失敗させます。[1], [3], [4], [5] - ✓✓
--no-ext-diffと--no-textconvは別々の制御として維持し、フィルタードライバーの対策の代用にしません。[1] - ✓✓ 実際のGitを使う回帰テストを追加し、リポジトリが設定した悪意あるフィルターがdiff、status、staging、checkoutやwrapperが対応する他の内容処理で実行されないことを確認します。[4], [5]
- ✓✓ アーカイブ、共有フォルダー、キャッシュ、devcontainerにローカル提供の
.git/configが入る経路を確認します。通常のcloneがこのファイルを運ぶとは説明しません。[1], [3]
参考資料
- GitLab Threat Research — DeepSeek-Reasonix vulnerability details and affected call site
- GitLab Advisory Database — CVE-2026-102437
- DeepSeek-Reasonix maintainer advisory — GHSA-grg2-7gc6-36m6
- DeepSeek-Reasonix Studio host Git hardening PR #11110
- DeepSeek-Reasonix 1.x host Git hardening PR #11114
- DeepSeek-Reasonix 1.39.3 release
- DeepSeek-Reasonix Studio 2.21.0 release
- MITRE CWE-78 — Improper Neutralization of Special Elements used in an OS Command