외부 기여자의 코드를 테스트하는 일과 저장소에 라벨을 쓰는 일은 필요한 신뢰가 다르다. 두 일을 한 워크플로에 묶었다면 새 정책을 허용으로 바꾸기 전에 실행할 코드와 사용할 권한을 분리해야 한다. 다가오는 임시 차단은 이 구분이 실제 운영에 반영됐는지 확인할 계기다.
첫 임시 차단은 한국시간 11월 10일 새벽이다
GitHub는 11월 2일 공지에서 pull_request_target 기본 차단 적용일을 기존 11월 2일에서 2026년 12월 2일로 연기했다. 대상은 GitHub Free·Team·Enterprise Cloud의 공개 저장소다. 비공개·internal 저장소와 GitHub Enterprise Server에는 이 공지의 변경이 적용되지 않는다. 공식 발표
이벤트 정책에서 명시적으로 허용한 경우까지 모두 막는다는 뜻은 아니다. 현재 기본 정책은 평가 모드로 동작하며, 적용 가능한 기존 이벤트 정책을 대체하지 않는다. 따라서 먼저 자기 저장소에 실제로 적용되는 정책을 확인해야 한다. 기본 정책의 범위
| 공지된 단계 | UTC | 한국시간(KST) |
|---|---|---|
| 첫 임시 차단 | 11월 9일 16:00부터 18:00까지 | 11월 10일 01:00부터 03:00까지 |
| 두 번째 임시 차단 | 11월 16일 16:00부터 18:00까지 | 11월 17일 01:00부터 03:00까지 |
| 상시 적용 예정 | 12월 2일, 정확한 시각 미명시 | 정확한 전환 시각 미확인 |
한국시간은 공지의 UTC에 9시간을 더한 값이다. 임시 차단 중 대상 실행은 오류 주석을 가진 실패 실행으로 남고 워크플로는 실행되지 않는다. 구간이 끝나면 기본 정책은 경고와 함께 실행을 허용하는 평가 모드로 돌아온다. 재시도가 업무를 자동 복구한다고 가정하지 말고 누락된 라벨이나 검사 결과를 따로 확인해야 한다. 일정과 동작은 11월 2일 공지 기준이며, 이 글은 11월 4일 확인한 문헌 분석이다. 실제 차단이나 계정 화면을 관측한 보고가 아니다.
위험을 만드는 것은 이벤트 이름 다음의 실행 경로다
외부 fork의 pull_request 테스트는 기여자의 변경을 검증하는 경로다. GitHub는 이 경우 토큰을 읽기 전용으로 제한하고 일반 비밀 값의 전달을 막는다. 반면 pull_request_target은 base 저장소 쪽의 신뢰된 워크플로로 PR에 반응하며, 권한이 필요한 라벨 처리 같은 용도를 지원한다. 두 이벤트의 신뢰 차이
문제는 후자의 작업에서 외부 PR 코드를 가져온 뒤 실행할 때 생긴다. YAML 자체가 신뢰된 브랜치에 있어도, 다음 단계의 빌드 스크립트·설정·의존성이 PR에서 온다면 실행 주체는 외부 기여자가 정한 코드다. 테스트 명령은 검사 대상인 동시에 프로그램 실행이다. 액션을 고정된 커밋으로 잠가도 테스트가 읽는 PR의 코드를 신뢰된 것으로 바꾸지는 못한다.
이를 공개 SDK 저장소의 하루 업무로 바꿔 보자. 외부 기여자가 버그 수정 PR을 열면 팀은 세 가지 결과를 원한다. 변경 코드의 테스트 결과, 담당 분야 라벨, 검토자가 읽을 요약 댓글이다. 편리하다는 이유로 세 작업을 같은 권한으로 실행할 필요는 없다.
그림은 제안하는 역할 분리다. 제품의 화면이나 실행 캡처가 아니다. 화살표가 연결돼 있다는 사실만으로 앞 단계의 산출물이 신뢰된다는 의미도 아니다.
공개 SDK 팀의 세 작업을 나누면 무엇이 달라질까
다음 표는 자체 설계한 전환안이다. 모든 저장소에 적용할 완성 YAML이 아니라, 팀이 자신의 워크플로를 분류할 기준이다.
| 업무 | 실행할 코드·읽을 입력 | 필요한 효과와 설계 |
|---|---|---|
| 버그 수정 테스트 | 외부 PR 코드와 그 코드의 의존성 | pull_request에서 비밀 값 없이 실행. 테스트 결과를 남김 |
| 담당 분야 라벨 | 신뢰된 분류 코드와 PR 메타데이터 | 필요한 쓰기 권한만 가진 별도 경로. PR 빌드·설정 코드를 실행하지 않음 |
| 결과 요약 게시 | 검증한 실행 식별자와 제한된 결과 데이터 | 필요하다면 별도 권한 경로. 산출물의 프로그램·스크립트를 실행하지 않음 |
이 설계의 이득은 “권한을 줄였다”는 선언보다 실패의 범위가 좁아진다는 데 있다. 라벨 처리가 정책에 막혀도 코드 테스트 결과와 구분할 수 있다. 테스트가 실패했다고 라벨용 토큰 권한을 늘릴 이유도 사라진다.
다만 단순히 job 두 개로 나누는 것으로 충분하지 않을 수 있다. 공유 작업 디렉터리, 지속되는 자체 호스팅 러너, 다음 단계가 읽는 파일처럼 실행 상태가 이어지는 경로를 확인해야 한다. 공식 보안 문서는 작업 간 간섭 가능성과 격리의 중요성을 설명한다. 이 사례에서는 비신뢰 코드를 실행하는 경로와 권한이 있는 경로가 실행 환경을 공유하지 않는 것을 설계 조건으로 둔다. Secure use reference
비공개 패키지가 필요한 테스트는 어디에 둘까
이 경우에는 이벤트 이름만 pull_request로 바꾸면 테스트가 깨질 수 있다. 기존 테스트가 비공개 레지스트리 자격증명에 의존했기 때문이다. 그렇다고 외부 PR 테스트에 자격증명을 다시 넣는 것을 복구라고 보기는 어렵다.
우리 SDK 팀이라면 외부 PR에서 수행 가능한 공개 의존성 테스트와, 신뢰 검토를 마친 특정 커밋에 대해 내부에서 수행하는 통합 테스트를 구분할 수 있다. 검토 뒤 PR에 커밋이 추가되면 이전 승인 대상과 달라졌다는 것도 확인한다. 이것은 추가 절차와 대기 시간을 수반하는 편집 제안이다. 모든 테스트를 즉시 자동 실행해야 하는 팀에는 그 비용이 클 수 있으며, 내부 테스트 환경과 데이터 대체 방안을 함께 설계해야 한다. 이 글에서 비공개 레지스트리나 실제 실행 환경을 구성하지는 않았다.
후속 게시 단계가 다시 신뢰 경계를 무너뜨리지 않게 한다
workflow_run으로 게시 단계를 옮겼다고 안전성이 자동으로 생기지는 않는다. 공식 문서도 다른 워크플로의 산출물을 조심해서 다루도록 요구한다. 산출물 처리 주의
가상의 PR 42번을 예로 들자. 테스트가 끝난 뒤 PR에 새 커밋이 올라왔는데, 이전 실행의 “통과” 요약을 현재 코드의 결과처럼 댓글에 붙이면 비밀 유출이 없어도 독자를 오도한다. 결과 파일 이름이 report.json이라는 사실만으로 그 출처나 의미는 검증되지 않는다.
이 팀의 게시 단계에는 다음 조건을 제안한다. 이는 구현·실행된 제품 기능 설명이 아니라 인수 기준이다.
- GitHub 실행 메타데이터에서 저장소, 대상 워크플로, 실행 ID, PR과 검사 대상 커밋의 연결을 확인한다. 산출물 안에 스스로 적힌 PR 번호만 믿지 않는다.
- 결과 데이터는 허용한 필드·자료형·크기로 제한한다. 경로나 명령 문자열을 실행 입력으로 사용하지 않는다.
- 게시 시점의 커밋과 검사 대상이 다르면 현재 코드가 통과했다고 표시하지 않는다. 이전 커밋의 결과로 명시하거나 새 실행을 기다린다.
- 같은 실행의 재처리가 댓글을 무한히 늘리지 않도록 게시 대상을 식별하고 갱신 규칙을 둔다.
라벨 처리에도 입력 검증은 남는다. PR 제목을 셸 코드에 직접 끼워 넣는 대신 데이터로 전달하는 방법은 GitHub의 스크립트 주입 방지 지침에 나온다. “체크아웃하지 않으므로 안전하다”는 결론보다, 어떤 외부 입력이 어느 실행 도구로 들어가는지 추적하는 편이 정확하다.
정책 화면에서는 허용 대상과 관측 결과를 함께 읽는다
공식 문서의 경로는 저장소·조직의 Settings → Actions → Policies다. 기업 수준에서는 Policies → Actions → Policies로 들어간다. 대상 저장소와 워크플로 경로를 좁혀 설정할 수 있으며, 사이드바의 Policy insights는 차단됐거나 평가 모드에서 차단될 실행을 확인하는 자리다. 정책 설정과 관측 문서
이 화면에서 먼저 찾을 것은 “허용 버튼”보다 영향을 받는 파일 목록이다. 예를 들어 label.yml만 이 이벤트를 필요로 한다면 전체 워크플로에 넓은 예외를 만들 이유가 없다. 파일별 허용은 코드 검토와 함께 결정하고, 조직·기업 수준 정책도 겹쳐 적용된다는 점을 확인한다. 하위 저장소에서 한 항목을 바꿨다고 모든 상위 제한이 풀렸다고 가정하지 않는다.
기본 정책이 현재 평가 모드라는 공지와, 사용자가 새 정책에서 Evaluate를 선택하는 기능도 구분해야 한다. 후자는 공식 문서에서 Enterprise Cloud 전용으로 표시한다. 모든 요금제에 동일한 사용자 설정이 있다고 안내할 수 없다. 위 설명은 문서 기반 위치 안내이며 실제 계정 화면·모바일 UI를 확인한 결과는 아니다.
멈춘 자동화를 어떤 순서로 복구할까
| 보이는 결과 | 먼저 확인할 근거 | 다음 행동 |
|---|---|---|
| 시작 전 정책 오류, 단계 로그 없음 | 실패 실행의 오류 주석과 Policy insights | 대상 파일·이벤트·정책 일치 여부 확인. 불필요한 이벤트는 변경, 필요한 경로만 검토 후 허용 |
| 실행은 시작했으나 API 쓰기 실패 | 해당 단계의 응답과 job 권한 | 정말 필요한 쓰기 효과와 권한을 대조. 테스트 작업 전체의 권한을 넓히지 않음 |
| 테스트 명령 실패 | 검사한 커밋·의존성·실패 로그 | 정책 문제가 아닌 코드·환경 실패로 조사 |
| 통과 댓글이 최신 PR과 불일치 | 실행 ID·검사 커밋·현재 커밋 | 오래된 결과임을 표시하고 현재 커밋의 결과를 별도로 확인 |
첫 임시 차단 전에 목록 조사와 업무 분리를 끝내고, 승인된 시험 저장소에서 외부 fork PR·추가 커밋·실패 테스트·반복 게시를 확인하는 것이 이 사례의 완료 조건이다. 아직 실행하지 않은 항목은 unknown으로 남긴다. 차단 구간이 끝나 일시적으로 다시 실행된다는 것만으로 전환 완료로 처리하지 않는다.
PR 자동화 전환 기록지에 파일별 역할, 코드 출처, 권한, 적용 정책, 검사 커밋과 복구 결과를 적을 수 있다. 자체 제작한 빈 양식이며 보안 인증서나 자동 검사 도구는 아니다. 이 글에서 GitHub 실행·정책 변경·공격 재현은 하지 않았다.
의존 액션의 버전을 고정하는 문제는 Actions 잠금 파일 도입과 복구로 이어진다. 이 글의 권한·입력 분리와 함께 적용할 수 있지만 해결하는 질문은 다르다. 실제 배포 파일의 출처를 판단하려면 SBOM·provenance·VEX의 역할을 읽을 수 있다. 전환 담당자는 기록지를 저장해 첫 임시 차단 뒤 실제 누락 업무와 대조하고, 이후 일정 변경은 공식 공지에서 다시 확인하면 된다.
- 기본 차단은 공개 저장소가 대상이다. 이미 적용 중인 이벤트 정책과 파일별 예외를 확인하고, 공지를 모든 저장소의 일괄 중단으로 읽지 않는다.
- 외부 코드를 실행하는 테스트와 권한이 필요한 라벨·결과 게시를 분리한다. 후속 워크플로로 옮긴 산출물도 신뢰가 자동으로 높아지지 않는다.
- 정책 차단, 토큰 권한 부족, 테스트 실패를 다른 결과로 기록한다. 정상 테스트 통과만으로 정책 전환이 끝났다고 판단하지 않는다.
근거와 원자료
자료의 발행 시점과 이번 글에서 참고한 범위를 함께 기록합니다.
- pull_request_target blocked by default December 2 ↗GitHub · 2026
November2 announcement; December2 enforcement; November9/16 UTC brownouts; public Free/Team/EnterpriseCloud only, not GHES.
- Securely using pull_request_target ↗GitHub · 2026
Current default policy and untrusted execution boundary; default vs explicit event policy, fork code and artifacts.
- Governing execution of GitHub Actions workflows ↗GitHub · 2026
Settings/Actions/Policies, workflow path scoping and Policy insights; custom Evaluate ECloud only.
- Secure use reference ↗GitHub · 2026
Least privilege, shell input handling and workflow_run artifact caution.
갱신 기록
공식 발표·정책·보안 문서를 대조하고 가상 공개 SDK 저장소의 업무 분리표와 전환 기록지를 작성했다. GitHub 계정·워크플로 실행은 수행하지 않았다.
오류를 발견했다면 댓글로 알려 주세요 →
이 글에 댓글 남기기
댓글 공개 방식을 확인하고 있습니다. 개인정보나 비밀 값은 적지 마세요.
댓글을 불러오는 중입니다.
내 댓글 확인·수정·삭제
등록 후 안내된 댓글 번호와 비밀번호를 입력하세요. 승인 대기 중인 댓글도 확인할 수 있습니다.