Self-hosted runner를 fork PR에 그대로 열어뒀다가 생긴 보안 문제
문제 발생
빌드 속도를 높이려고 사내 서버에 self-hosted runner를 설치해 오픈소스 저장소에 연결했는데, 외부 기여자가 만든 Pull Request의 워크플로우가 그 러너에서 실행되면서 내부 네트워크에 접근 가능한 임의 명령을 실행할 수 있는 상황이 만들어졌습니다.
원인 분석
GitHub이 제공하는 호스팅 러너(ubuntu-latest 등)는 매 워크플로우 실행마다 완전히 새로 프로비저닝된 격리 환경입니다 — 실행이 끝나면 그 가상 머신은 통째로 폐기됩니다. Self-hosted runner는 반대로 여러분이 직접 관리하는 지속적인 머신입니다. 매 실행 후 자동으로 초기화되지 않으며(별도로 그렇게 구성하지 않는 한), 그 머신이 접근할 수 있는 네트워크, 파일, 자격 증명에 워크플로우가 그대로 접근할 수 있습니다.
퍼블릭 저장소에서 pull_request 트리거로 self-hosted runner를 쓰면, 누구나 PR을 열어서 그 워크플로우 파일에 원하는 명령을 추가한 뒤 실행시킬 수 있습니다 — GitHub 공식 문서가 이를 명시적으로 강하게 경고하는 이유입니다. fork에서 온 PR은 신뢰할 수 없는 코드로 취급해야 합니다.
해결 방안
- 퍼블릭 저장소에서는 fork PR에 self-hosted runner를 노출하지 않습니다. GitHub 공식 문서도 "Public repositories에서 self-hosted runner를 쓰지 말 것"을 강하게 권고합니다 — 꼭 필요하다면
pull_request_target처럼 신중한 검토가 필요한 이벤트로 제한하고, 실행 전 코드 내용을 사람이 직접 확인하는 절차를 둡니다. - Self-hosted runner는 가능하면 프라이빗 저장소나, 신뢰할 수 있는 내부 기여자만 코드를 push할 수 있는 저장소에서만 씁니다.
- 러너를 매 job마다 초기화되는 임시 환경(컨테이너, 매번 새로 만들고 버리는 VM 등)으로 구성해, 이전 실행의 상태(자격 증명 캐시, 남은 파일)가 다음 실행에 영향을 주지 않도록 합니다.
- 러너가 접근 가능한 네트워크 범위를 최소한으로 제한합니다(방화벽, 별도 네트워크 분리) — 워크플로우가 예상 밖의 명령을 실행하더라도 피해 범위를 줄일 수 있습니다.
- 러너에 필요한 최소한의 권한만 있는 자격 증명을 두고, 프로덕션 인프라에 직접 접근 가능한 강한 권한은 별도의 더 엄격하게 통제되는 배포 경로로 분리합니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.