Watch at Ease세상을 읽고, 일상의 답을 찾다.

기술 · 실용 가이드

Git “detected dubious ownership”: safe.directory 추가 전 소유권 경계를 확인하세요

치명적 메시지를 귀찮은 경고가 아니라 실행 사용자와 소유자의 불일치로 다룹니다. Git 사용자, 저장소 소유자, 마운트 경로와 설정 범위를 확인한 뒤 정확한 한 경로만 예외로 둘지 결정하세요.

계층 파일시스템 사이에서 사용자와 컨테이너 주체의 저장소 소유권을 비교하는 원본 편집 일러스트.
원본 일러스트: 신뢰를 추가하기 전에 실행 주체, 저장소 소유자와 마운트 경계를 비교합니다. Watch at Ease

작업 트리가 다른 주체의 소유라면 Git은 해당 경로가 명시적으로 신뢰되지 않는 한 저장소 설정을 읽지 않습니다. 안전한 해결은 Git 실행 사용자와 정규 저장소 경로의 소유자를 증명하고, 잘못된 소유권은 수정하며, 의도적 공유에만 정확한 예외 하나를 추가하는 것입니다.

1. 실패한 사용자와 정규 경로 기록

실제로 실패한 같은 셸, 서비스, 컨테이너 또는 CI 단계에서 재현합니다. 유효 사용자, Git이 출력한 정확한 경로와 정규 작업 트리 경로를 기록합니다. Unix 계열에서는 id -u와 id -g를 저장소 및 모든 상위 디렉터리 소유자와 비교하고, Windows에서는 같은 Git 클라이언트 문맥에서 소유자 SID를 확인합니다. 대화형 셸, GUI, sudo, 서비스와 컨테이너가 같은 사용자나 설정 파일을 공유한다고 가정하지 마세요.

2. 변경 전에 불일치 분류

복원, 관리자 clone, 디스크 이동 또는 root 빌드로 소유자가 잘못됐다면 소유자를 고치거나 의도한 사용자로 실행합니다. 공유 때문에 의도적으로 다르다면 소유자를 유지하고 정확한 예외 하나를 만듭니다. 파일시스템 경계가 불안정한 메타데이터를 보고한다면 반복 측정하고, 저장소를 마운트 루트 한 단계 아래에 두거나 상위 디렉터리를 마운트해 본 뒤 신뢰 설정을 원인으로 판단합니다.

3. 실패 프로세스가 실제 읽는 설정 확인

--global은 명령을 실행한 사용자의 설정에 기록됩니다. 다른 서비스 계정, 컨테이너 사용자 또는 CI 프로세스는 다른 HOME을 읽을 수 있습니다. 실패 문맥에서 git config --show-origin --get-all safe.directory를 실행해 값과 출처 파일을 확인합니다. system 범위는 관리자가 장비 전체 정책을 의도할 때만 사용합니다. 저장소 로컬 설정으로 자기 자신을 안전하다고 표시할 수는 없습니다.

4. 가장 좁은 수정 적용

소유자가 우연히 잘못됐다면 관련 없는 상위 경로 권한을 넓히지 말고 저장소 트리만 의도한 계정으로 되돌립니다. 공유가 의도됐다면 Git을 실행하는 주체의 보호된 설정에 정규 저장소 경로 하나만 추가합니다. * 값은 모든 저장소를 안전하다고 보는 완전한 검사 해제입니다. 경로 끝의 /* 역시 아래 모든 저장소를 신뢰하므로 통제된 공유 루트에만 사용합니다.

5. 원래 작업과 중첩 저장소 재시험

원래 프로세스 사용자로 git status와 실패한 명령을 다시 실행하고, 서브모듈, worktree, 중첩 저장소도 따로 확인합니다. root나 다른 HOME으로 성공한 것은 증거가 아닙니다. 유효 사용자와 show-origin을 다시 확인하고, 좁은 경로로 해결된 뒤 오래된 항목과 와일드카드를 제거합니다. 공유 소유권을 신뢰하는 이유도 짧게 남깁니다.

이 경고를 존중해야 하는 이유

소유권 경계 규칙은 CVE-2022-24765 이후 도입됐습니다. GitHub는 다중 사용자 시스템에서 공격자가 상위 위치에 .git을 만들고 Git이 명령 실행 가능 설정을 읽게 할 수 있다고 설명했습니다. 질문은 “어떻게 숨길까”가 아니라 “누가 이 경로를 소유하며, 왜 정당하고, 예외를 얼마나 좁힐 수 있는가”입니다.

소유권 수정과 단일 경로 예외를 나란히 보여 주고 광범위 신뢰 경로는 닫아 둔 원본 기술 일러스트.
원본 일러스트: 잘못된 소유권은 고치고 의도적 공유는 정확한 경로 하나만 신뢰합니다. Watch at Ease