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]
두 라벨만 비교한다고 약속한 분류대를 떠올려 보세요. 소포에는 내용을 비교하기 전에 등록된 도우미를 실행하라는 경로 메모가 붙을 수 있습니다. Reasonix는 Git의 일부 도우미를 비활성화했지만 파일별 clean 필터는 별도의 경로였습니다. diff 화면이 Git에 파일 준비를 요청할 때 이 필터가 개발자 권한으로 실행될 수 있었습니다.[1], [3]
핵심 개념 및 용어
.gitattributes- 저장소에서 추적되는 파일로, 특정 경로에 이름이 지정된 필터를 할당할 수 있습니다.[1]
Diff 뷰어- Git에 파일의 작업 트리 내용을 준비하고 커밋된 내용과 비교하도록 요청하는 기능입니다.[1]
프레임워크 매핑
- 이 가이드에서 설명하는 약점의 CWE 참조: CWE-78
근본 원인 분석 (Root Cause)
Reasonix는 git diff 호출에 --no-ext-diff 와 --no-textconv 를 적용했지만, 이 옵션은 외부 diff와 텍스트 변환 메커니즘을 제어하며 Git의 clean 콘텐츠 필터를 비활성화하지 않습니다. 작업 공간 변경 화면은 선택한 경로에 대해 git diff 를 호출했습니다. 저장소 내용이 .gitattributes 로 해당 경로에 필터를 할당하고 로컬 Git 설정이 그 드라이버의 명령을 정의하면 Git은 비교 blob을 만들 때 해당 명령을 실행할 수 있습니다. CVE는 로컬 공격자를 설명하며 사용자가 diff를 열어야 합니다. GitLab 공개 내용에 따르면 일반 clone은 .git/config 를 전달하지 않습니다. 아카이브, 동기화 폴더, 캐시 또는 미리 구성된 devcontainer에는 이 파일이 포함될 수 있습니다. 동일한 사용자 권한을 가진 로컬 에이전트가 저장소의 로컬 설정을 작성하는 경우도 설명합니다. 영향은 Reasonix 사용자 권한으로 로컬 명령이 실행되는 것이며, GitLab 호스팅 저장소를 열기만 해도 원격 코드가 실행되는 것은 아닙니다.[1], [3]
단계별 공격 실행 흐름
소스 코드 비교: 취약한 구현 vs 보안 패치
이 인자 빌더는 설명용 예시이며 그대로 적용할 수 있는 패치가 아닙니다. 호출자는 .gitattributes, .git/info/attributes, 전역/시스템 속성 파일이 선택한 모든 driver를 열거하고, 전체 검색을 성공적으로 마친 뒤에만 discoveryComplete를 설정해야 합니다. 이 함수는 전달된 이름을 검증하고 명령줄 설정 재정의를 생성할 뿐 driver 집합을 찾아내거나 검증하지 않습니다. 취약한 호출은 GitLab 공개 자료에서 인용했으며, 방어 패턴은 유지관리자 지침과 병합된 hardening 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을 실행하는 도구는 저장소 로컬 설정과 추적 중인 attributes를 신뢰할 수 없는 입력으로 취급하세요.[1], [3]
- ✓✓ 콘텐츠를 변환하는 각 host-Git 호출에서
.gitattributes,.git/info/attributes, 전역/시스템 attribute 파일이 선택하는 모든 필터를 확인하고 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