Skip to main content

pull_request_target 안전하게 사용

의 보안 위험에 대해 알아봅니다 pull_request_target event.

이 가이드는 워크플로가 이벤트를 사용해야 pull_request_target 하는지 여부를 평가하고 관련된 보안 위험을 이해하는 데 도움이 됩니다. 또한 기본적으로 이러한 위험을 줄이기 위해 actions/checkout v7 이상에 적용되는 보호 와 필요한 경우 해당 보호를 옵트아웃해야 하는 경우를 설명합니다.

이러한 워크플로 중 하나에서 pull request 코드를 체크아웃하기 전에, 또는 actions/checkout에서 allow-unsafe-pr-checkout 입력을 설정하기 전에 pull_request_target을 읽어보세요.

pull_request_target 이벤트의 위험

pull_request_target에 의해 트리거된 워크플로는 높은 수준의 신뢰로 실행되며, 작업은 기본 리포지토리의 GITHUB_TOKEN에 대한 액세스, 리포지토리 및 조직 시크릿에 대한 액세스, 그리고 기본 브랜치 캐시에 대한 쓰기 액세스 권한을 받습니다. 이는 공동 작업자만 트리거할 수 있는 push와 같은 이벤트에 부여되는 것과 동일한 수준의 신뢰이며, 이러한 신뢰 덕분에 pull_request_target는 레이블 지정, 분류 또는 인증된 상태 검사 게시와 같이 포크에서 온 pull request에 응답하는 자동화에 유용합니다.

이것이 기본적으로 안전한 이유와 그 안전성이 일반적으로 어떻게 깨지는지 이해하려면 pull_request_targetpull_request와 대조해 검토하십시오.

pull_request 이벤트(pull_request_reviewpull_request_review_comment와 함께)는 이례적입니다. 풀 리퀘스트의 병합 커밋에 있는 워크플로 파일을 사용해 실행됩니다. 포크에서 열린 끌어오기 요청의 경우 해당 커밋은 기본 리포지토리에 대한 쓰기 액세스 권한이 없는 사용자가 제어합니다. 신뢰할 수 없는 워크플로 코드를 안전하게 GitHub 실행하려면 이러한 이벤트를 읽기 전용 GITHUB_TOKEN으로 제한하고, 다른 비밀에 대한 액세스를 보류하며, 컴퓨팅 남용을 방지하기 위해 포크 승인 정책을 적용합니다. 자세한 내용은 워크플로를 트리거하는 이벤트을(를) 참조하세요. 기본적으로 actions/checkout 워크플로에서는 pull_request 끌어오기 요청의 병합 커밋도 체크 아웃하므로 코드가 체크 아웃되고 실행되는 워크플로가 일관됩니다.

pull_request_target는 한 가지 중요하면서도 미묘한 변경을 가합니다. 워크플로와 ref를 지정하지 않는 후속 actions/checkout 호출은 풀 리퀘스트가 아니라 기본 리포지토리의 기본 브랜치에서 가져오게 됩니다. 기본 분기의 신뢰할 수 있는 코드만 실행되므로 비밀 및 읽기/쓰기 토큰을 부여해도 안전합니다. 포크의 코드는 기본적으로 실행되지 않습니다.

워크플로 작성자가 포크의 코드를 실행하기 위해 이 기본값을 재정의할 때 위험이 발생합니다. 개발자pull_request_target 통해 포크의 끌어오기 요청을 실행하고 비밀에 액세스할 수 있기를 원하기 때문에(예: 프라이빗 레지스트리가 필요한 테스트를 실행하기 위해) 자주 선택합니다__. 이렇게 하기 위해, 기본 브랜치 대신 pull request 헤드를 actions/checkout 가리키도록 하는데, 이는 안전하지 않습니다:

# INSECURE. Provided as an example only.
on:
  pull_request_target:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          ref: ${{ github.event.pull_request.head.sha }}
      - name: Test
        run: make test

체크 아웃 단계만으로는 신뢰할 수 없는 코드가 실행되지 않습니다. 워크플로 파일 자체는 여전히 기본 분기에서 제공됩니다. 취약성은 현재 작업 디렉터리에 체크 아웃된 코드를 실행하는 다음 단계에 의해 완료됩니다. 여기서 make test는 pull request 헤드에서 가져온 Makefile를 실행합니다. 공격자는 악성 명령이 포함된 Makefile(또는 빌드 스크립트, 테스트 명령, 의존성 또는 구성 파일)이 있는 포크에서 풀 리퀘스트를 열기만 하면 됩니다. 그런 다음, 이러한 명령은 기본 리포지토리의 비밀 및 토큰으로 실행됩니다.

이 패턴은 "pwn 요청"으로 알려져 있으며 여러 공급망 손상의 근본 원인이었습니다. 자세한 내용은 GitHub Security Lab에서 pwn 요청 방지를 참조하세요. 일반적인 취약한 셰이프는 다음과 같습니다.

  • 끌어오기 요청의 헤드 또는 병합 커밋(actions/checkout``ref: ${{ github.event.pull_request.head.sha }}, ref: refs/pull/${{ github.event.pull_request.number }}/merge)을 확인한 다음 결과를 빌드, 테스트 또는 실행합니다.
  • repository:를 포크(repository: ${{ github.event.pull_request.head.repo.full_name }})로 설정하여 포크의 브랜치를 직접 끌어옵니다.
  • actions/checkout 외부에서 풀 리퀘스트 코드를 가져온 다음(예: git fetch, gh pr checkout를 사용하거나 포크의 pull_request 실행에서 아티팩트를 다운로드하여) 실행하는 것.

Pwn 요청도 pull_request_target에만 해당하는 것은 아닙니다. 비밀로 실행되는 모든 이벤트는 신뢰할 수 없는 코드를 체크 아웃하거나 다운로드하고 실행하는 경우 pwn 요청을 도입할 수 있습니다. 예를 들어 issue_comment 포크의 끌어오기 요청 코드를 가져오고 실행하는 워크플로는 workflow_run 같은 방식으로 취약합니다. 워크플로는 workflow_run 다른 워크플로에서 업로드한 아티팩트를 신뢰할 수 없는 데이터로 처리해야 합니다. 그 내용은 포크에서 나올 수 있기 때문에.

pull_request_target 사용할지 여부 결정

일부 워크플로는 높은 수준의 신뢰로 포크된 pull request 코드를 체크아웃해야 하며, pull_request_target가 바로 이런 이유로 처음 만들어졌습니다. 예를 들어 프라이빗 아티팩트 레지스트리가 필요한 검사 보고서를 생성하거나 끌어오기 요청에서 도입된 변경 내용에 대해 인증된 검사를 생성하고 실행합니다. actions/checkout에서 pull_request_target를 사용하거나 allow-unsafe-pr-checkout 플래그를 선택하기 전에 아래 질문을 고려하세요.

  • 대신 사용할 pull_request 수 있나요? pull_requestpull_request_target와 동일한 이벤트에서 트리거되며, pull_request 병합 브랜치의 워크플로 코드를 실행합니다. 위에 자세히 설명된 보호 기능을 바탕으로 포크에서 온 풀 리퀘스트에 대해서도 이 작업을 안전하게 수행합니다. 추가 시크릿 액세스가 필요하지 않은 경우 pull_request을 사용하십시오. 더 복잡한 워크플로는 잠재적으로 위험한 풀 리퀘스트 코드 처리와 비밀 정보 액세스를 분리하도록 재구성할 수 있습니다. 자세한 내용은 GitHub Security Lab의 pwn 요청 방지를 참조하세요.

  • 체크 아웃된 코드가 실행되었나요? 이것은 pwn 요청 취약성을 도입하는 결함입니다. 가장 일반적으로 actions/checkout를 사용해 작업 디렉터리에 풀 리퀘스트 헤드를 체크아웃한 다음 이를 실행하는 방식으로 도입됩니다. path 입력이 설정되지 않으면 actions/checkout은(는) 일반적으로 후속 명령이 실행되는 작업 디렉터리인 $GITHUB_WORKSPACE 디렉터리에 코드를 기록합니다. 실행은 사용자 고유의 단계로 제한되지 않습니다. 코드에서 제공하는 구성 파일 및 종속성뿐만 아니라 빌드 및 npm install테스트 명령 npm run build 도 모두 공격자 제어 코드를 실행할 수 있습니다. 실행에는 명백한 빌드 단계가 필요하지 않습니다. 체크 아웃된 코드는 데이터로만 검사되고 이벤트를 사용하기 pull_request_target 전에 실행되지 않았는지 확인해야 합니다.

pull_request_target 워크플로 보안 강화

pull_request_target이(가) 필요하다는 것이 확인되면 이러한 제어 조치를 적용하여 이 고위험 이벤트로 인한 영향을 제한하세요. 워크플로가 끌어오기 요청 코드를 체크 아웃하는지 여부에 따라 적용됩니다.

  • 비밀을 제한합니다. 설정된 GITHUB_TOKEN 사용 권한에 최소 권한이 있고 필요한 리포지토리 및 조직 비밀만 워크플로에 사용되는지 확인합니다. 자세한 내용은 워크플로에서 인증에 GITHUB_TOKEN 사용을(를) 참조하세요.

  • 캐싱에 미치는 영향을 이해합니다. GITHUB_TOKEN 및 구성된 시크릿 외에도, pull_request_target에서 실행되는 워크플로에는 기본 브랜치의 다른 워크플로와 공유되는 캐시에 대한 쓰기 권한도 있습니다. 이벤트에서 이 캐시 pull_request_target 를 악의적으로 변경하면 관련이 없는 다른 워크플로의 실행에 영향을 미칠 수 있습니다.

  • 기반 컴퓨팅 리소스가 격리되어 있고 일시적인지 확인합니다. 자체 호스팅 실행기를 사용하는 경우 실행기 환경이 내부 리소스에 접근하지 못하도록 적절히 제한되어 있고 GitHub Actions 실행 전반에 걸쳐 재사용되지 않는지 확인해야 합니다. 자세한 내용은 안전 사용 참조을(를) 참조하세요.

  • 게이트는 승인 뒤에 실행됩니다. pull_request_target 워크플로는 쓰기 액세스 권한이 있는 사용자만 추가할 수 있는 필수 label에 의해 제한될 수 있습니다. 이는 GitHub Security Lab되어 있습니다.

  • 보안 모범 사례를 적용 GitHub Actions 합니다. pwn 요청의 특정 위험 외에도 명령 주입과 같은 기타 일반적인 취약성이 존재할 수 있으며 이 권한 있는 이벤트에서 실행되는 코드에 영향을 미칠 수 있습니다. 자세한 내용은 GitHub Actions 및 워크플로 보안 유지: 신뢰할 수 없는 입력을 GitHub Security Lab참조하세요. 일반적인 GitHub Actions 취약성을 식별하고 이에 선제적으로 대응하려면 GitHub Actions에 대해 CodeQL을(를) 사용하도록 설정하세요. 자세한 내용은 코드 검사에 대한 기본 설정 구성을(를) 참조하세요.

기본 제공 보호 기능 사용 안 함

위 질문들을 검토한 후 워크플로에 pull_request_target가 필요하고 이를 안전하게 사용한다는 것을 확인했다면, actions/checkout 보호를 해제할 수 있습니다. 입력으로 allow-unsafe-pr-checkout: true 설정 actions/checkout 하면 포크에서 끌어오기 요청 헤드 참조를 체크 아웃할 수 있습니다. 체크 아웃된 코드가 실행되지 않는지 확인한 후에만 이 작업을 수행합니다. 입력은 의도적으로 코드 검토 및 정적 분석에서 쉽게 발견할 수 있도록 명명됩니다.

이 보호는 포크의 풀 요청 ref에만 적용됩니다. 관련 없는 타사 리포지토리처럼 신뢰할 수 없는 다른 코드를 체크아웃하거나, git fetch 또는 gh pr checkout로 코드를 가져오거나, 다운로드한 아티팩트를 실행하는 것은 actions/checkout 검사에서 다루지 않습니다.

pull_request_target 사용 제한

리포지토리, 조직 및 엔터프라이즈 관리자는 워크플로 실행 보호를 사용하여 워크플로를 트리거할 수 있는 이벤트 및 행위자를 제어할 수 있습니다. 리포지토리에 대해 합법적인 사용 pull_request_target이 없는 경우 제한하면 개별 워크플로 작성 방법에 관계없이 위험이 제거됩니다.