flawopen.com/AI Security/plugin4shell-ai-agent-plugin-sha-pin-bypass
●
CWE-345 · 높음
보안 연구 · FlawOpen
Plugin4Shell: 플러그인 SHA 고정 우회
네 가지 AI 에이전트 플러그인 설치기는 Git 리비전을 고정하고도 checkout된 commit을 확인하지 않았습니다. Plugin4Shell은 최종 SHA 검증의 필요성을 보여줍니다.[1]
💡 알기 쉬운 설명 (ELI5)
도서관은 고유한 목록 번호로 특정 판본의 책을 예약합니다. 직원이 그 번호를 요청하고도 서가 표지에 같은 글자가 있으면 다른 책을 건넵니다. SHA 고정값은 목록 번호와 같습니다. 설치기는 플러그인을 신뢰하거나 실행하기 전에 실제 checkout된 commit을 확인해야 합니다.[1]
핵심 개념 및 용어
Git ref 모호성- Git은 객체 ID와 브랜치 같은 이름을 모두 리비전 표현식으로 처리합니다. 조건에 따라 commit ID처럼 보이는 이름이 ref로 해석될 수 있습니다.[1]
플러그인 마켓플레이스- 에이전트 확장을 배포하고 검토된 리비전을 기록할 수 있는 카탈로그입니다. 설치 클라이언트도 고정값을 강제해야 합니다.[1]
CWE-345- 데이터 진위 검증 부족: 시스템이 데이터가 예상한 진짜 값인지 충분히 확인하지 않고 사용합니다.[5]
프레임워크 매핑
- 이 가이드에서 설명하는 약점의 CWE 참조: CWE-345
단계별 공격 실행 흐름
소스 코드 비교: 취약한 구현 vs 보안 패치
취약한 경로는 이름 해석의 성공을 객체 동일성의 증명으로 혼동했습니다. 패치는 checkout 후 HEAD를 마켓플레이스 고정값과 비교하고 다른 commit의 materialization을 거부합니다. 이 코드 쌍은 Codex 패치이며 다른 제품은 구현이 다르므로 동일한 수정이 적용됐다고 가정하면 안 됩니다.[2], [6]
취약한 구현
// OpenAI Codex PR #34644 수정 전 형태
if let Some(target) = sha.or(ref_name) {
run_git(&["checkout", target], Some(destination))?;
}
// checkout 성공을 SHA 일치의 증거로 간주했다.
보안 강화 패치
// Codex 수정: 요청 인자만이 아니라 해석된 commit을 검증
if let Some(sha) = sha {
run_git(&["checkout", sha], Some(destination))?;
let checked_out_sha =
run_git_output(&["rev-parse", "HEAD"], Some(destination))?;
if !checked_out_sha.eq_ignore_ascii_case(sha) {
return Err(format!(
"checked out Git SHA {checked_out_sha} does not match requested SHA {sha}"
));
}
} else if let Some(ref_name) = ref_name {
run_git(&["checkout", ref_name], Some(destination))?;
}
엔지니어링 및 시스템 보안 강화 체크리스트
- ✓SHA 고정 checkout을 수행할 때마다 실제 checkout된 commit(예: <code>git rev-parse HEAD</code>)을 해석하고 플러그인 파일을 읽기 전에 요청한 고정값과 정확히 비교하세요.[2], [6]
- ✓FlawOpen 구현 권장 사항: 불일치, HEAD 누락, 명령 오류 또는 예상하지 못한 리비전 형식이면 fail closed하고 브랜치 이름으로 대체하지 마세요.[2]
- ✓기본 브랜치 이름이 다른 commit의 SHA와 충돌하는 임시 로컬 저장소에서 설치기를 시험하고 설치가 거부되며 플러그인 코드가 로드되지 않는지 확인하세요.[6]
- ✓FlawOpen 구현 권장 사항: 타입과 제어 흐름에서 ref 이름 설치와 불변 SHA 고정을 분리하고 검증된 commit을 설치 메타데이터에 기록하세요.[1]
- ✓영향받는 에이전트 버전과 마켓플레이스 Git 호스트를 파악하세요. GitHub는 SHA 형태의 브랜치 이름을 차단하지만 이 호스트 규칙은 다른 지원 호스트나 Gemini의 FETCH_HEAD 경로를 보호하지 않습니다.[1], [4]
- ✓인용된 AIR 공개 내용은 Codex 0.146.0과 Claude Code 2.1.179에서 수정됐다고 하지만 전체 영향 버전 범위는 제공하지 않습니다. Copilot 및 Gemini CLI의 상태나 조치를 안내하기 전에 각 업체의 최신 안내를 확인하세요.[1], [3], [7]
- ✓Codex 회귀 테스트
materialize_git_source_rejects_sha_that_resolves_to_hostile_default_branch를 유지하세요. 임시 로컬 저장소를 만들고 플러그인 소스가 구체화되기 전에 불일치 HEAD가 거부되는지 확인합니다.[6]