빌드 작업이 대화형 터미널에서는 정상적으로 실행되지만, 무인 runner로 전환하면 “열 수 없음”, “작업이 허용되지 않음” 오류가 발생하거나 프로세스가 시작 직후 종료되는 경우가 있습니다. 많은 사람이 가장 먼저 chmod +x를 실행하지만, 파일에 이미 실행 권한이 있다면 실제 원인은 대개 Gatekeeper, 코드 서명 평가 또는 다운로드된 파일에 포함된 격리 속성입니다. 브라우저로 도구를 다운로드했거나, 다른 세션의 산출물을 복사했거나, 확장 속성을 보존하는 아카이브에서 캐시를 복원했을 때 흔히 발생합니다.
실행 실패를 먼저 네 가지 유형으로 구분하기
“실행할 수 없음”이라는 메시지만 보고 곧바로 속성을 삭제해서는 안 됩니다. 먼저 파일 형식, 권한, 아키텍처, 확장 속성을 수집하십시오. 이 네 가지 결과만으로도 대부분의 잘못된 판단을 배제할 수 있습니다.
TOOL="/opt/build-tools/example-tool"
ls -leO@ "$TOOL"
file "$TOOL"
uname -m
xattr -l "$TOOL"
ls로 소유자와 실행 비트를 확인하고, file 결과에는 노드와 일치하는 실행 파일 아키텍처가 표시되어야 합니다. xattr에 com.apple.quarantine이 나타난다는 사실은 해당 파일이 격리 평가 절차를 거쳤다는 의미일 뿐, 파일이 안전하다는 직접적인 증거는 아닙니다. 오류가 Permission denied라면 먼저 디렉터리 탐색 권한이 있는지, 마운트 지점에 실행 제한이 설정되어 있는지 확인하십시오. 오류가 Bad CPU type in executable이라면 격리 속성을 조작할 것이 아니라 올바른 아키텍처의 산출물로 교체해야 합니다.
| 증상 | 우선 확인할 항목 | 즉시 해서는 안 되는 작업 |
|---|---|---|
| Permission denied | 파일과 상위 디렉터리의 권한 | 확장 속성을 재귀적으로 제거 |
| Bad CPU type | file과 uname -m |
실행 비트를 반복해서 변경 |
| 손상되었거나 확인할 수 없음 | 서명과 Gatekeeper 결과 | 시스템 보안 검사 비활성화 |
| runner에서만 실패 | 실제 경로, 사용자, 캐시 출처 | 대화형 환경과 완전히 같다고 가정 |
격리 속성은 출처를 추적하기 위한 단서이지, 그 자체가 장애는 아닙니다. 먼저 예상한 파일을 확보했는지 입증한 다음 허용 여부를 결정하십시오.
Gatekeeper의 명확한 판정 확인하기
개별 바이너리 또는 애플리케이션 평가하기
명령줄 도구는 먼저 서명을 검사한 다음 시스템 정책에 판정을 요청합니다. 애플리케이션 번들이라면 TOOL을 해당 .app 경로로 변경하면 됩니다.
codesign --display --verbose=4 "$TOOL"
codesign --verify --deep --strict --verbose=2 "$TOOL"
spctl --assess --type execute --verbose=4 "$TOOL"
서명되지 않은 내부 도구라고 해서 반드시 문제가 있는 것은 아니지만, 통제된 빌드 절차에서 생성되어야 하며 해시 검증으로 무결성을 입증해야 합니다. 서명된 것으로 안내된 타사 사전 빌드 도구가 검증에 실패하면 사용을 중단하고 신뢰할 수 있는 산출물을 다시 받아야 합니다. 격리 속성을 삭제해 서명 변경을 숨겨서는 안 됩니다.
정책 로그 조회하기
팝업과 runner의 표준 오류에는 원인이 생략되는 경우가 많습니다. 문제를 재현한 직후 최근 보안 정책 기록을 확인하면 실제로 평가된 경로를 파악할 수 있으므로, 캐시 A를 검사했지만 실제로는 캐시 B가 실행되는 상황을 피할 수 있습니다.
log show --last 10m \
--predicate 'subsystem == "com.apple.security.syspolicy"' \
--style compact
로그에 나온 경로를 command -v, runner 설정, 스크립트 변수와 하나씩 대조하십시오. 특히 심볼릭 링크는 경로 불일치를 일으키기 쉽습니다. 진입점은 도구 디렉터리에 있지만 최종 파일은 오래된 캐시에서 가져올 수 있습니다.
허용하기 전에 산출물의 신원 검증하기
가장 안전한 절차는 도구 배포자나 내부 아티팩트 파이프라인에서 SHA-256 해시를 제공하고, 해시 파일을 도구 버전과 함께 저장소 설정에 포함하는 것입니다. 다운로드한 결과에서 임시로 해시를 계산한 뒤 동일한 파일을 검증하는 데 사용해서는 안 됩니다. 이는 파일을 읽는 동안 변경되지 않았다는 사실만 증명할 뿐, 출처가 올바르다는 사실은 입증하지 못합니다.
cd /opt/build-tools
shasum -a 256 -c example-tool.sha256
codesign --verify --deep --strict --verbose=2 example-tool
내부에서 직접 빌드한 도구에는 외부 배포용 서명이 없어도 되지만, 최소한 커밋 버전, 빌드 스크립트 버전, 예상 해시는 보존해야 합니다. 도구가 압축 파일로 제공된다면 먼저 압축 파일을 검증한 뒤 임시 디렉터리에 압축을 풀고, 최종 실행 파일을 검사한 다음 운영 경로를 원자적으로 교체하십시오. 이렇게 해야 업데이트 도중 runner가 불완전한 파일을 읽는 일을 방지할 수 있습니다.
대상의 격리 속성만 제거하기
해시, 버전, 서명이 예상과 일치하는지 확인한 뒤 검증된 대상만 처리하십시오. 먼저 기존 값을 읽어 작업 로그에 기록한 다음 지정된 속성을 삭제합니다.
TOOL="/opt/build-tools/example-tool"
xattr -p com.apple.quarantine "$TOOL" 2>/dev/null || true
if xattr -p com.apple.quarantine "$TOOL" >/dev/null 2>&1; then
xattr -d com.apple.quarantine "$TOOL"
fi
spctl --assess --type execute --verbose=4 "$TOOL"
"$TOOL" --version
작업 공간에서 xattr -cr .을 실행하지 마십시오. 이 명령은 저장소, 종속성, 스크립트, 임시 산출물의 여러 확장 속성을 한꺼번에 제거합니다. 허용 범위가 불필요하게 넓어질 뿐 아니라 이후 조사에 필요한 출처 증거도 사라집니다. 애플리케이션 번들은 내부에 상속된 속성을 처리해야 할 수 있지만, 이 경우에도 runner의 전체 캐시 루트가 아니라 검증이 끝난 개별 번들로 범위를 제한해야 합니다.
검사를 설치 게이트로 정착시키기
안정적인 클라우드 Mac CI라면 빌드 작업마다 임시로 권한을 수정해서는 안 됩니다. 도구 준비 과정을 별도의 설치 단계로 분리하십시오. 임시 디렉터리에 다운로드하고, 해시를 대조하고, 아키텍처와 서명을 검사하고, 격리 상태를 확인하고, 해당 대상만 허용하고, 버전 자체 검사를 실행한 다음 공유 도구 디렉터리에 기록해야 합니다.
캐시 키에는 최소한 도구 이름, 버전, CPU 아키텍처, 해시가 포함되어야 합니다. 캐시가 적중해도 사람이 내용을 덮어썼을 수 있으므로 가벼운 검사를 계속 수행해야 합니다. runner가 시작될 때 id -un, uname -m, 해석된 도구 경로와 버전을 기록할 수 있지만, 자격 증명이나 전체 환경 변수를 출력해서는 안 됩니다.
마지막으로 세 가지 실패 원칙을 유지하십시오. 해시가 일치하지 않으면 즉시 중단하고, 원래 서명이 있어야 하는데 검증에 실패하면 다시 받아야 하며, 격리 평가만이 검증된 산출물의 실행을 막는 경우에만 대상 속성을 삭제해야 합니다. 이 방식은 전역 검사를 비활성화하는 것보다 몇 가지 명령이 더 필요하지만, 도구의 출처와 허용 작업, 실제 실행 버전을 모두 감사할 수 있게 해 줍니다.
자주 묻는 질문
실행 권한이 있는데도 macOS가 도구를 차단하는 이유는 무엇인가요?
실행 권한은 파일 권한만 결정합니다. Gatekeeper는 격리 속성, 코드 서명, 출처와 시스템 정책도 평가하므로 chmod +x만으로는 차단이 해제되지 않습니다.
CI 작업 디렉터리 전체에 xattr -cr을 실행해도 되나요?
권장하지 않습니다. 검증되지 않은 산출물을 포함한 모든 파일의 속성이 제거됩니다. 해시와 서명을 확인한 뒤 대상 파일의 com.apple.quarantine만 삭제해야 합니다.
같은 도구가 매번 다시 차단되는 문제는 어떻게 방지하나요?
다운로드, 해시 검증, 압축 해제와 대상별 허용을 통제된 설치 단계로 묶고 도구 버전, 아키텍처, 해시를 포함한 키로 검증 완료 파일을 캐시합니다.
전용 Apple Silicon 물리 노드에서 빌드 실행
기종, 지역 및 대여 기간에 따라 노드를 구성할 수 있으며, 실제 사용 가능 여부는 콘솔에서 실시간으로 확인되는 상태를 따릅니다.