CodeQL에서 GitHub 공식 Actions도 SHA 고정 검사하기

워크플로는 그대로인데 actions/checkout@v4가 가리키는 코드는 언제든 바뀐다. CodeQL이 이 줄에 경고를 띄우지 않는다면 고정된 참조라는 뜻일까?

CodeQL에서 GitHub 공식 Actions도 SHA 고정 검사하기
세 줄 요약
  • CodeQL은 GitHub 공식 액션에 버전 태그를 써도 기본 설정에서는 미고정 태그 경고를 내지 않는다.
  • 모델 팩에서 공식 소유자의 검사 예외를 해제하면 이 액션들도 커밋 고정 여부를 검사한다.
  • 검사를 실행할 때 모델 팩과 해당 쿼리를 함께 불러온다. Actions 잠금 파일로 이미 고정된 참조는 경고에서 제외된다.

공식 액션의 버전 태그에 경고가 없는 이유

actions/checkout@v4의 v4는 특정 커밋을 영구히 가리키는 값이 아니다. 게시자가 태그를 옮기면 워크플로 파일을 수정하지 않아도 다음 실행에서 다른 코드가 사용될 수 있다. 그런데 CodeQL의 actions/unpinned-tag 검사는 actions, github, advanced-security 소유자의 액션을 기본 예외로 처리한다. 공식 액션에 경고가 없는 이유다.

CodeQL 2.27.2부터는 이 예외에서 소유자를 뺄 수 있다. 공식 액션까지 같은 쿼리로 검사해 미고정 참조를 찾는 설정이다. 설정을 바꿔도 액션 실행을 차단하는 것은 아니며, 검사 결과에 경고가 추가된다.

모델 팩에 검사할 공식 소유자를 등록한다

모델 확장의 trustedActionsOwnerDataModel은 검사에서 예외로 둘 게시자를 지정한다. 소유자 이름만 넣으면 예외에 추가되고, 이름 앞에 !를 붙이면 예외에서 빠진다. 따라서 !actions는 actions가 배포한 액션도 검사하라는 설정이다.

세 공식 소유자를 모두 검사하려면 모델 팩의 models/trusted-owner.model.json을 다음과 같이 작성한다.

{
  "extensions": [{
    "addsTo": {
      "pack": "codeql/actions-all",
      "extensible": "trustedActionsOwnerDataModel"
    },
    "data": [["!actions"], ["!github"], ["!advanced-security"]]
  }]
}

actions/checkout의 소유자는 첫 슬래시 앞의 actions다. 이 액션을 검사 대상에 넣으려면 !actions를 쓴다. 같은 소유자가 배포한 다른 액션에도 적용된다. !github는 github 소유자의 액션에 적용된다. 같은 소유자에 일반 이름과 ! 이름을 모두 등록하면 예외 해제가 우선한다.

같은 팩의 codeql-pack.yml에서 확장할 라이브러리와 JSON 파일 경로를 지정한다. 아래 example-org/actions-owner-policy는 실제 게시할 팩 이름으로 바꾼다.

name: example-org/actions-owner-policy
version: 0.0.1
library: true
extensionTargets:
  codeql/actions-all: '*'
dataExtensions:
  - models/**/*.json

분석 명령에 모델 팩과 검사 쿼리를 함께 넣는다

모델 팩을 게시한 뒤 분석 명령의 --model-packs로 불러온다. 아래 명령은 이미 생성한 Actions 데이터베이스를 분석한다. ./actions-db는 실제 데이터베이스 경로로, 팩 이름은 앞서 게시한 이름으로 바꾼다. 분석 환경에서 해당 팩에 접근할 수 있어야 한다.

codeql database analyze ./actions-db \
  codeql/actions-queries:codeql-suites/actions-security-extended.qls \
  --download --model-packs example-org/actions-owner-policy \
  --format=sarif-latest --output=actions-results.sarif

이 명령은 모델 팩으로 공식 소유자의 예외를 해제하고, actions-security-extended.qls로 미고정 태그 쿼리를 실행한다. 해당 쿼리는 actions-security-and-quality.qls에도 들어 있다.

쿼리는 Actions 잠금 파일로 이미 고정된 참조와 불변 액션으로 판정한 참조를 경고에서 제외한다. 소유자 예외를 해제한 뒤에도 이 제외 조건은 적용된다. 모델 확장 형식은 현재 베타 API다.

경고가 난 태그를 전체 커밋 SHA로 바꾼다

미고정 태그를 직접 수정할 때는 원하는 릴리스의 전체 커밋 SHA를 uses:에 넣는다. GitHub는 액션 원본 저장소에 있는 커밋을 선택하도록 권고한다. 같은 이름의 포크에서 가져온 SHA를 쓰는 일을 막기 위해서다.

전체 SHA로 고정하면 새 릴리스가 나와도 기존 커밋을 계속 실행한다. 보안 수정도 새 SHA로 바꿔야 반영된다. CodeQL Action은 고정한 버전을 갱신하는 방법으로 Dependabot을 안내한다.