아카이브 파이프라인이 수개월 동안 안정적으로 실행됐더라도 빌드 계정, 저장소 디렉터리, 심지어 임시 작업 공간 이름이 산출물에 기록될 수 있습니다. 흔히 남는 흔적으로는 /Users/runner/, DerivedData, 마운트된 볼륨 경로, 소스 파일의 전체 경로 등이 있습니다. 이러한 정보가 App 동작을 직접 바꾸는 경우는 드물지만, 설치 패키지나 심볼 파일, 로그를 입수한 사람에게 내부 구조를 노출할 수 있습니다. 클라우드 Mac은 여러 작업에 반복해서 사용되므로, 경로 검사를 일회성 문자열 검색이 아니라 릴리스 전 필수 단계로 운영해야 합니다.
검사할 산출물의 범위부터 구분하기
한 번의 Xcode 아카이브에서도 최소한 세 가지 대상을 구분해야 합니다. 배포할 .app, 팀 내부에 보관할 .dSYM, 그리고 파이프라인 로그입니다. 각각의 위험을 한데 묶어 판단해서는 안 됩니다.
배포 가능한 App에 실제 사용자 디렉터리가 포함되어 있다면 높은 우선순위로 처리해야 합니다. dSYM에 소스 경로가 기록되는 것은 디버그 정보의 일부이므로, 경로가 보인다는 이유만으로 삭제해서는 안 됩니다. 실제 문제는 dSYM이 잘못 공개되거나, 경로에 외부로 전파해서는 안 되는 작업 식별자가 포함된 경우입니다. 로그의 노출 범위는 읽기 권한과 보존 기간에 따라 달라지지만, 임시 자격 증명 디렉터리와 개인 사용자 이름을 장기간 남겨서는 안 됩니다.
| 대상 | 일반적인 경로 출처 | 권장 조치 |
|---|---|---|
| App 실행 파일 | 어설션, 디버그 문자열, 생성된 코드 | 실제 로컬 경로가 발견되면 차단 |
| dSYM | DWARF 컴파일 디렉터리 및 소스 경로 | 접두사를 매핑하고 심볼리케이션 재검증 |
| 빌드 로그 | 명령어 에코, 스크립트, 도구 출력 | 민감 정보를 제거한 뒤 보존 기간 제한 |
| 테스트 첨부 파일 | 스크린샷, 진단 패키지, 결과 패키지 | 별도로 검사한 뒤 아카이브 |
경로 감사의 목적은 모든 디버그 정보를 없애는 것이 아니라, 빌드 머신의 실제 디렉터리 구조가 필요하지 않은 배포 범위까지 유출되지 않도록 하는 것입니다.
깨끗한 아카이브에서 스캔 시작하기
먼저 아카이브 경로를 고정해 스캔 스크립트 자체가 무작위 디렉터리를 만들지 않도록 합니다. Release 구성은 파이프라인에서 명시적으로 전달해야 하며, 개발 머신에서 마지막으로 선택한 Scheme 상태에 의존해서는 안 됩니다.
set -euo pipefail
ARCHIVE="$PWD/output/App.xcarchive"
rm -rf "$ARCHIVE"
xcodebuild archive \
-workspace App.xcworkspace \
-scheme App \
-configuration Release \
-destination 'generic/platform=iOS' \
-archivePath "$ARCHIVE"
App의 주 실행 파일을 찾은 다음, 시스템에 기본 제공되는 strings로 중요한 패턴을 검색합니다. /Users/뿐 아니라 /Volumes/, DerivedData, .xcworkspace, 그리고 팀에서 실제로 사용하는 임시 디렉터리 접두사도 검사해야 합니다.
APP="$ARCHIVE/Products/Applications/App.app"
EXEC=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "$APP/Info.plist")
BIN="$APP/$EXEC"
REPORT="$PWD/output/app-paths.txt"
strings -a "$BIN" |
grep -E '/Users/|/Volumes/|DerivedData|\.xcworkspace|\.xcodeproj' \
> "$REPORT" || true
if [ -s "$REPORT" ]; then
cat "$REPORT"
exit 1
fi
주 프로그램이 검사를 통과했다고 해서 전체 패키지가 깨끗한 것은 아닙니다. 포함된 framework, 확장 프로그램, 리소스 파일도 순회하며 검사해야 합니다. 스캔 보고서에는 “파일 경로, 일치한 내용, 산출물 유형”을 기록하되, 바이너리 전체나 환경 변수를 로그에 직접 업로드해서는 안 됩니다.
dSYM 별도 검사하기
dSYM 검사에서는 일반 문자열의 개수가 아니라 DW_AT_comp_dir와 소스 파일 기록을 중점적으로 확인해야 합니다. 먼저 DWARF 파일을 찾고 실제 작업 공간을 가리킬 가능성이 있는 항목을 출력합니다.
DSYM="$ARCHIVE/dSYMs/App.app.dSYM"
DWARF="$DSYM/Contents/Resources/DWARF/App"
xcrun dwarfdump --debug-info "$DWARF" |
grep -E 'DW_AT_(comp_dir|decl_file).*("/Users/|"/Volumes/)' \
> "$PWD/output/dsym-paths.txt" || true
xcrun dwarfdump --uuid "$DWARF"
UUID는 아카이브에 포함된 실행 파일과 일치해야 합니다. 일치하지 않으면 경로를 올바르게 처리했더라도 이후에 크래시 주소를 신뢰성 있게 복원할 수 없습니다.
컴파일 접두사 매핑으로 실제 디렉터리 감추기
Swift 컴파일러에서는 -debug-prefix-map을 사용해 작업 공간 접두사를 안정적인 논리 디렉터리로 바꿀 수 있으며, Clang에서는 -fdebug-prefix-map을 사용합니다. Xcode의 Release 구성에 각각 다음 설정을 추가할 수 있습니다.
OTHER_SWIFT_FLAGS = $(inherited) -debug-prefix-map $(SRCROOT)=/src
OTHER_CFLAGS = $(inherited) -fdebug-prefix-map=$(SRCROOT)=/src
OTHER_CPLUSPLUSFLAGS = $(inherited) -fdebug-prefix-map=$(SRCROOT)=/src
/Users 전체를 바로 매핑하지 마십시오. 지나치게 넓은 규칙은 외부 의존성의 출처를 가릴 수 있고, 서로 다른 디렉터리가 의도치 않게 같은 논리 경로로 합쳐질 수도 있습니다. 우선 $(SRCROOT)를 매핑하고, 의존성을 체크아웃하는 디렉터리가 고정되어 있다면 해당 디렉터리에 별도 규칙을 추가합니다.
매핑한 뒤에는 반드시 다시 아카이브해야 하며, 빌드 설정만 수정한 채 기존 DerivedData를 재사용해서는 안 됩니다. 일부 사용자 정의 스크립트는 프로젝트 설정을 우회해 컴파일러를 직접 호출하므로, 실제 컴파일 명령에 해당 인수가 포함됐는지도 확인해야 합니다.
오탐을 전부 허용하지 말고 등급별로 분류하기
스캔에서는 리소스에 포함된 예제 경로, 테스트 픽스처, 서드파티 디버그 텍스트가 자주 발견됩니다. 처리 방식은 계속 늘어나는 전역 무시 목록이 아니라, 해당 항목의 위치와 도달 가능성을 기준으로 결정해야 합니다.
결과는 다음 세 단계로 나누는 것이 좋습니다.
- 배포 App 또는 포함된 구성 요소에서 현재 빌드 머신의 실제 접두사가 발견되면 즉시 실패 처리합니다.
- dSYM에서 매핑되지 않은 소스 접두사가 발견되면 실패로 표시하되, 진단을 위해 파일은 보존합니다.
- 내부 로그나 테스트 결과 패키지에서 경로가 발견되면 경고를 생성하고 접근 범위를 점검합니다.
허용 목록은 “파일 + 정규식 + 사유” 단위로 구체화해야 합니다. 예를 들어 특정 테스트 리소스에서 실제로 /Users/example/을 표시해야 한다면 해당 리소스만 예외로 처리할 수 있습니다. /Users/ 전체를 무시 목록에 추가해서는 안 됩니다. 또한 파이프라인은 현재 작업 공간 경로를 동적인 금지 항목으로 지정해야 합니다. 이 방식이 가능한 모든 사용자 이름을 추측하는 것보다 더 안정적입니다.
스캔 스크립트가 더 많은 정보를 노출하지 않도록 하기
보고서에서는 실제 접두사를 $WORKSPACE로 바꾸고, 상대 경로와 일치 유형만 남길 수 있습니다. 명령이 실패하더라도 전체 환경을 출력해서는 안 됩니다. 원본 보고서를 보관해야 한다면 모든 구성원이 읽을 수 있는 콘솔 출력에 직접 펼치지 말고, 접근이 제한된 빌드 첨부 파일로 저장해야 합니다.
릴리스 전 심볼리케이션 기능 재검증하기
경로 매핑이 스캔을 통과했다고 해서 디버깅 체인이 온전히 유지된다는 뜻은 아닙니다. 릴리스 전에는 최소한 App, dSYM, UUID 목록, 빌드 커밋 식별자를 보관하고, 실제 명령어 주소 하나를 선택해 심볼리케이션 테스트를 수행해야 합니다. 결과에는 16진수 주소만 표시되는 것이 아니라 함수 이름과 /src/... 형식의 논리적 소스 파일 경로가 반환되어야 합니다.
최종 게이트는 네 가지 항목으로 정리할 수 있습니다. App에 실제 작업 공간 접두사가 없어야 하고, dSYM UUID가 바이너리와 일치해야 하며, 매핑된 소스 경로를 식별할 수 있어야 하고, 로그에 원본 스캔 내용이 그대로 출력되지 않아야 합니다. 이렇게 하면 디렉터리 정보의 노출 범위를 줄이면서도 운영 환경의 장애를 분석하는 데 필요한 증거를 보존할 수 있습니다.
경로 감사는 VMOrbit 클라우드 Mac의 아카이브 작업 직후 실행하는 것이 적합합니다. 고정된 사용자 이름에 의존하지 않고 소스 디렉터리 구조를 바꿀 필요도 없습니다. 파이프라인이 작업 공간 루트 경로를 일관되게 제공하기만 하면 동일한 규칙으로 임시 작업과 장기 빌드 노드를 모두 검사할 수 있습니다.
자주 묻는 질문
App에서 /Users/ 경로가 발견되면 항상 보안 취약점인가요?
항상 취약점인 것은 아니지만 빌드 계정과 디렉터리 구조를 노출할 수 있습니다. 배포 App, dSYM, 내부 로그 중 어디에서 발견됐는지 먼저 구분해야 합니다.
debug-prefix-map을 적용하면 dSYM을 삭제해도 되나요?
안 됩니다. 접두사 매핑은 경로 표현만 바꾸며 dSYM을 대체하지 않습니다. dSYM을 보관하고 실제 주소로 심볼리케이션을 재검증해야 합니다.
경로 검사 결과는 모두 빌드를 차단해야 하나요?
배포 App에 남은 실제 로컬 경로는 차단하고, dSYM과 내부 로그의 결과는 경고와 검토 대상으로 분리하는 방식이 안전합니다.
빌드 작업을 전용 클라우드 Mac에서 실행하세요
VMOrbit M4 또는 VMOrbit M4 Pro를 선택하고 팀의 위치에 따라 노드를 지정하세요. 실제 사용 가능 여부와 제공 정보는 콘솔에서 실시간으로 확인되는 내용을 기준으로 합니다.