GitHub Actions에서 Codex Security 실행

Codex Security Action으로 풀 리퀘스트와 저장소를 스캔하고, 보고서를 저장하고, SARIF를 업로드하고, 정책 적용을 구성합니다.

GitHub Actions에서 Codex Security를 실행하여 풀 리퀘스트의 변경 사항을 검토하거나 일정에 따라 저장소를 스캔합니다. Action은 CLI를 설치하고, 구조화된 보고서를 저장하며, 작업 요약과 소스 주석을 추가합니다. 먼저 결과를 참고용으로 활용한 다음, 스캔 범위와 품질을 검토한 후 정책 적용을 구성하세요.

워크플로 준비

스캔을 실행하려면 Codex Security 액세스 권한이 필요합니다. OpenAI API key를 추가하려면 다음을 수행하세요.

  1. GitHub 저장소에서 Settings → Secrets and variables → Actions 를 엽니다.
  2. New repository secret 을 선택합니다.
  3. 이름으로 CODEX_SECURITY_API_KEY를 입력하고 OpenAI API key를 값으로 붙여 넣습니다. 비밀을 저장합니다.

아래 워크플로 예시는 이 비밀을 Codex Security Action에 자동으로 전달합니다. 워크플로 파일에 API key를 넣을 필요가 없습니다.

신뢰하는 저장소와 풀 리퀘스트에 대해서만 워크플로를 실행하세요. 스캔은 러너의 로컬 권한을 사용하며 승인을 기다리지 않습니다. 관련 없는 자격 증명과 배포 단계는 별도의 작업에 두세요.

GitHub Actions 워크플로 추가

일정에 따라 저장소 스캔

아래 워크플로는 매주 월요일 07:23 UTC에 기본 브랜치를 스캔합니다. GitHub의 Actions 탭에서 수동으로 실행할 수도 있습니다. x64 GitHub 호스팅 Ubuntu 24.04 러너를 사용하며 필요한 샌드박스를 자동으로 설정합니다.

  1. 저장소에서 Add file → Create new file 을 선택합니다.
  2. 파일 이름을 .github/workflows/codex-security-repository.yml으로 지정합니다.
  3. 아래 워크플로를 붙여 넣고 기본 브랜치에 커밋합니다.
name: Codex Security repository

on:
  workflow_dispatch:
  schedule:
    - cron: "23 7 * * 1" # Mondays at 07:23 UTC

permissions:
  contents: read

jobs:
  security:
    runs-on: ubuntu-24.04
    timeout-minutes: 120
    steps:
      - name: Set up the Ubuntu sandbox
        run: |
          sudo apt-get update
          sudo apt-get install --yes bubblewrap apparmor-profiles
          sudo apparmor_parser -r /usr/share/apparmor/extra-profiles/bwrap-userns-restrict

      - name: Check out the repository
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false

      - name: Scan the repository
        id: security
        uses: openai/codex-security@3f61e5150981a5087c32e4395bbaa8ce5ce0c3e3 # action-v0.3.0
        with:
          scope: repository
          model: gpt-6-sol
          # For approved Daybreak Blue access, uncomment the next input.
          # cyber-access-program: daybreak_blue
          effort: high
          fail-on-severity: none
          upload-artifacts: "true"
        env:
          OPENAI_API_KEY: ${{ secrets.CODEX_SECURITY_API_KEY }}

러너 조정: Action에는 Node.js 24와 Python 3.11 이상이 필요하며, 이 러너는 이를 제공합니다. 샌드박스 설정은 bubblewrap 패키지를 설치하고 스캔 전에 제공된 AppArmor 프로필을 로드합니다. 이 러너에서는 패키지를 설치하는 것만으로는 충분하지 않습니다.

워크플로를 수동으로 실행하려면 Actions → Codex Security repository → Run workflow 를 엽니다. 완료된 실행을 열어 요약, 주석, 다운로드 가능한 보고서를 검토합니다.

fail-on-severity가 none이므로 탐지 결과는 보고만 됩니다. 스캐너 오류와 필수 보고 오류가 발생하면 작업은 여전히 실패합니다.

선택한 폴더를 스캔하려면 스캔 단계의 with 블록에 리터럴 경로를 줄바꿈으로 구분하여 추가합니다.

paths: |
  src/api
  src/auth

경로를 사용하려면 scope: repository가 필요하며 glob은 확장되지 않습니다. diff 스캔에서는 paths를 생략합니다. persist-credentials: false를 유지하고 체크아웃 직후에 스캔을 실행하세요.

풀 리퀘스트 변경 사항 스캔

동일한 비밀을 사용하여 .github/workflows/codex-security-pr.yml을 생성합니다.

name: Codex Security PR

on:
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]

permissions:
  contents: read

concurrency:
  group: codex-security-pr-${{ github.event.pull_request.number }}
  cancel-in-progress: true

jobs:
  security:
    if: github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'dependabot[bot]'
    name: Codex Security
    runs-on: ubuntu-24.04
    timeout-minutes: 60
    steps:
      - name: Set up the Ubuntu sandbox
        run: |
          sudo apt-get update
          sudo apt-get install --yes bubblewrap apparmor-profiles
          sudo apparmor_parser -r /usr/share/apparmor/extra-profiles/bwrap-userns-restrict

      - name: Check out the pull request
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          ref: ${{ github.event.pull_request.head.sha }}
          fetch-depth: 0
          persist-credentials: false

      - name: Scan PR changes
        id: security
        uses: openai/codex-security@3f61e5150981a5087c32e4395bbaa8ce5ce0c3e3 # action-v0.3.0
        with:
          scope: diff
          model: gpt-6-sol
          # For approved Daybreak Blue access, uncomment the next input.
          # cyber-access-program: daybreak_blue
          effort: high
          fail-on-severity: none
          upload-artifacts: "true"
        env:
          OPENAI_API_KEY: ${{ secrets.CODEX_SECURITY_API_KEY }}

동일한 저장소의 브랜치에서 PR을 열거나 업데이트합니다. Action은 전체 기록을 사용하여 정확한 병합 기준점을 찾고, 체크아웃된 PR 헤드까지의 변경 사항을 스캔합니다. PR의 Checks 에서 Codex Security 검사를 확인하세요. 먼저 탐지 결과를 참고용으로 활용한 다음, 변경 사항에 병합 조건을 적용할 준비가 되면 심각도 정책을 선택하세요.

이 예시는 포크 PR과 dependabot[bot]이 연 PR을 건너뜁니다. 작업을 건너뛰었다고 해서 보안 검토가 수행된 것은 아닙니다. 이러한 봇 PR을 포함하려면 작성자 제외 조건을 제거하고 CODEX_SECURITY_API_KEY도 dependabot[bot]용 비밀로 구성하세요. Action은 pull_request_target 또는 workflow_run을 지원하지 않습니다.

스캐너는 PR의 정책 변경 사항을 포함하여 체크아웃에서 적용 가능한 SECURITY.md 지침을 읽습니다. 해당 변경 사항을 코드와 함께 검토하세요.

선택적 Daybreak 액세스 구성

Daybreak는 선택 사항입니다. 두 워크플로 예시 모두 gpt-6-sol을 사용합니다. 조직이 Trusted Access for Cyber 승인을 받았다면 스캔 단계의 with 블록에서 cyber-access-program 앞의 #를 제거합니다.

model: gpt-6-sol
cyber-access-program: daybreak_blue

Daybreak Blue가 활성화되어 있고 gpt-6-sol에 액세스할 수 있는 프로젝트의 API key를 사용하세요.

프로그램 입력에는 standard도 사용할 수 있습니다. Daybreak 액세스 권한이 없다면 표준 보호 조치하에서 API key로 액세스할 수 있는 모델을 사용하고 cyber-access-program 입력을 생략하거나 standard로 설정하세요. 모델이나 프로그램을 선택해도 액세스 권한이 부여되지는 않습니다. Action의 Daybreak 액세스 지침을 참조하세요.

거부 또는 안전 차단으로 스캔이 중단되면 fail-on-severity가 none인 경우에도 Action이 실패합니다. 이 입력은 스캐너 오류가 아니라 탐지 결과에 대한 정책을 제어합니다.

선택적 스캔 예산 설정

두 워크플로 예시 모두 max-cost를 생략하므로 예상 비용에 따른 중지 임계값이 없습니다. 임계값을 설정하려면 max-cost 입력에 양수인 USD 금액을 추가합니다. CLI에서 직접 스캔하려면 --max-cost를 사용합니다.

비용 한도를 사용하려면 CLI가 선택한 모델의 가격 정보를 지원해야 합니다. 예상 비용 임계값은 엄격한 지출 한도가 아닙니다. 이미 진행 중인 요청의 비용으로 인해 이를 초과할 수 있습니다. 임계값에 도달하여 스캔이 중지되면 탐지 결과와 coverage.json을 검토하세요. 비용 한도 동작은 출력 및 정책 옵션을 참조하세요.

보고서 저장 및 SARIF 업로드

예시에서는 upload-artifacts: "true"를 설정하여 다운로드 가능한 보고서를 7일 동안 보관합니다. 보고서에는 소스 코드 조각, 취약점 증거, 수정 세부 정보가 포함될 수 있습니다. 코드에 적합한 보관 기간과 저장소 액세스 권한을 선택하세요. Action은 허용 목록에 있는 검증된 보고서만 업로드합니다. results-directory 출력을 재귀적으로 업로드하지 마세요.

SARIF 업로드는 선택 사항입니다. 비공개 또는 내부 저장소의 경우 업로드 전에 GitHub Code Security를 활성화하세요. 워크플로의 permissions 블록을 다음으로 바꿉니다.

permissions:
  contents: read
  security-events: write
  actions: read # Required for private repositories

그런 다음 두 워크플로 중 사용하는 워크플로에서 스캔 뒤에 다음 단계를 추가합니다.

- name: Upload security findings
  if: ${{ always() && steps.security.outputs.sarif-upload-ready == 'true' }}
  uses: github/codeql-action/upload-sarif@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0
  with:
    sarif_file: ${{ steps.security.outputs.sarif-path }}
    sha: ${{ steps.security.outputs.scanned-sha }}
    ref: ${{ steps.security.outputs.analysis-ref }}
    category: codex-security-repository

PR 워크플로에서는 category: codex-security-pr를 사용하여 각 범위에 고유한 범주를 지정합니다. 스캔 단계의 id: security를 유지하세요. 탐지 결과가 심각도 정책을 충족하지 못해도 완전하고 검증된 보고서는 계속 업로드할 수 있습니다. 실패하거나 중단된 스캔, 빈 diff 또는 모의 실행의 경우 SARIF는 업로드되지 않습니다.

모든 설정, 상태 필드, 보고서 경로는 Action의 입력 및 출력 레퍼런스를 참조하세요.

심각도 정책 선택

GitHub 워크플로는 fail-on-severity: none으로 시작합니다. 완료된 스캔에서 심각도가 높거나 치명적인 탐지 결과가 나오면 실패하도록 하려면 스캔 단계의 입력을 변경합니다.

fail-on-severity: high

PR 작업이 실패할 때 병합을 차단하려면 저장소 규칙에서 Codex Security 를 필수 상태 검사로 지정합니다. GitHub는 필수 검사에서도 조건에 따라 건너뛴 작업을 성공으로 처리합니다. 포크 PR과 dependabot[bot]의 PR은 스캔 없이 이 검사를 통과합니다. 이렇게 건너뛴 경우를 차단하려면 성공적으로 완료된 스캔을 요구하세요.

Action은 CLI 결과를 따릅니다.

  • 종료 코드 0은 scan-status: completed와 policy-status: passed를 설정합니다.
  • 종료 코드 1은 scan-status: completed와 policy-status: failed를 설정합니다. 설정된 심각도 이상의 탐지 결과가 있으면 단계가 실패합니다.
  • 종료 코드 2 또는 프로세스 중단은 scan-status: failed와 policy-status: not-evaluated를 설정하며, 단계가 실패합니다.
  • 유효하지 않거나 누락된 필수 보고서, 변경된 체크아웃, 요청된 아티팩트 업로드 실패, 런타임 정리 실패도 단계를 실패하게 만듭니다.

스캔 완료는 구성된 분석이 유효한 결과를 생성했음을 의미합니다. coverage.json에 있는 범위 제외, 보류된 조사, 기타 참고 사항은 별도의 스캔 결과를 만들거나 심각도 정책을 우회하지 않습니다. 스캔 완료가 모든 취약점을 발견했음을 보증하지는 않습니다. 결과를 평가할 때 coverage.json을 검토하세요.

성공적으로 완료된 스캔 요구

더 엄격한 정책을 적용하려면 스캔 작업이 실패하거나 GitHub가 건너뛰더라도 실행되는 별도의 게이트를 추가합니다. 건너뛴 작업에서는 단계가 전혀 실행되지 않으므로 스캔 작업 내부의 단계로는 건너뛴 작업을 확인할 수 없습니다.

PR 워크플로의 기존 security 작업에 다음 outputs 매핑을 runs-on 및 steps와 동일한 들여쓰기 수준으로 추가합니다.

outputs:
  scan-status: ${{ steps.security.outputs.scan-status }}

그런 다음 jobs 아래에 기존 security 작업과 나란히 다음 작업을 추가합니다.

security-gate:
  name: Codex Security gate
  needs: security
  if: ${{ always() }}
  runs-on: ubuntu-24.04
  steps:
    - name: Require a successful, completed scan
      env:
        SCAN_RESULT: ${{ needs.security.result }}
        SCAN_STATUS: ${{ needs.security.outputs.scan-status }}
      run: test "$SCAN_RESULT" = success && test "$SCAN_STATUS" = completed

이 정책에서는 Codex Security gate 를 필수 상태 검사로 지정합니다. 스캔 작업의 성공과 scan-status: completed를 모두 요구합니다. 두 조건을 모두 검사하면 스캔 자체가 완료되었더라도 심각도 정책, 보고, 정리로 인한 실패가 유지됩니다.

예시의 제외 조건을 사용하면 이 게이트는 포크 PR과 dependabot[bot]의 PR을 차단합니다. 또한 Action이 skipped로 표시하는 빈 diff와 모의 실행도 차단합니다. 게이트는 제외된 PR을 스캔하지 않습니다. 이러한 경우에 병합을 방지해야 할 때만 이 정책을 선택하세요.

스캔 문제 해결

  • 알 수 없는 Git ref 또는 예상치 못한 diff: PR 헤드를 체크아웃할 때 fetch-depth: 0을 사용하세요.
  • 샌드박스 시작 오류: Ubuntu 24.04에서는 Action 실행 전에 bubblewrap 패키지를 설치하고 AppArmor 프로필을 로드하세요. 패키지를 설치하는 것만으로는 필요한 프로필이 로드되지 않습니다.
  • 자격 증명 누락: 신뢰할 수 있는 워크플로에서 CODEX_SECURITY_API_KEY를 사용할 수 있고 스캔 단계의 OPENAI_API_KEY 환경 변수에 매핑되어 있는지 확인하세요.
  • Python 설정 오류: Action에는 Python 3.11 이상이 필요합니다.
  • 스캔 범위 관련 참고 사항: 범위 제외와 보류된 조사를 coverage.json에서 검토하세요. 이러한 참고 사항은 실행 실패를 일으키거나 심각도 정책을 우회하지 않습니다.
  • SARIF 누락: scan-status, report-status, sarif-upload-ready를 확인하세요. 선택 사항인 SARIF가 누락되면 Action은 스캔 결과를 변경하지 않고 경고를 표시합니다. 요청된 아티팩트 업로드가 실패하면 여전히 작업이 실패합니다.
  • SARIF 업로드 오류: 조직에서 저장소에 GitHub Code Security를 활성화했는지, 워크플로가 actions: read, contents: read, security-events: write를 부여하는지 확인하세요.

모든 명령, 플래그, 아티팩트, 출력 필드는 CLI 레퍼런스를 참조하세요. 다른 제공업체는 CI/CD 개요를 참조하세요.