For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
기본 탐색 메뉴
Theme

GitLab CI/CD에서 Codex Security 실행하기

GitLab 병합 요청과 브랜치를 스캔하고 보안 이슈를 SARIF 형식으로 게시하세요. 검증된 수정 사항으로 병합 요청 초안을 열 수도 있습니다.

GitLab CI/CD에서 Codex Security를 실행하면 커밋된 변경 사항과 보호 브랜치를 스캔하고 보안 이슈를 GitLab Security에 게시할 수 있습니다. 필요하면 병합 요청 초안으로 검증된 수정 사항을 제안할 수도 있습니다.

이 워크플로우는 스캔용 자격 증명과 리포지터리 쓰기 권한을 분리합니다. 생성된 변경 사항을 병합하기 전에는 반드시 사람이 검토해야 합니다.

먼저 스캔 결과만 보고하도록 설정하세요. 프로젝트의 러너, 보고된 보안 이슈, 각 작업에서 접근할 수 있는 자격 증명의 범위를 확인한 뒤에만 자동 수정을 활성화하세요.

시작하기 전에

다음 항목이 필요합니다.

  • Codex 샌드박스의 사용자 네임스페이스를 지원하는 신뢰할 수 있는 러너가 있는 GitLab 프로젝트
  • 프로젝트 CI/CD 변수와 보호 리소스를 설정할 수 있는 GitLab 프로젝트의 Maintainer 또는 Owner 역할
  • Codex Security 접근 권한이 있는 OpenAI API 키. Platform API 키를 사용하는 조직은 Trusted Access for Cyber를 신청할 수 있습니다. ChatGPT 인증을 사용하는 개인은 개인용 Trusted Access 신청 절차를 이용할 수 있습니다. 일부 계정이나 리포지터리에서는 리포지터리 전체를 스캔하려면 이 권한이 필요합니다.
  • SARIF 2.1.0 보고서 수집을 지원하는 GitLab Ultimate 19.2 이상
  • 병합 요청 작업에서 병합 기준 커밋을 계산하는 데 필요한 전체 Git 이력

파이프라인 이미지는 Node.js 26, Python 3, Git, rg, 지정된 버전의 Codex Security CLI를 설치합니다. 자동 수정에는 기존 회귀 테스트와 보호된 자격 증명 없이 리포지터리에서 정의한 명령어를 실행할 수 있는 러너도 필요합니다.

스캔 전용 파이프라인으로 시작하기

마스킹, 숨김, 보호를 모두 적용한 GitLab CI/CD 변수 CODEX_SECURITY_API_KEY를 만드세요. 값으로는 Codex Security 접근 권한이 있는 OpenAI Platform API 키를 사용하고 환경 범위를 codex-security/openai로 설정하세요. CI/CD 변수의 환경 범위 설정을 참고하세요.

먼저 테스트 프로젝트에 다음 파이프라인을 추가하세요. 이 파이프라인은 조건을 충족하는 보호 브랜치 간 병합 요청에서 커밋된 변경 사항을 스캔합니다. 보고 작업이 성공하면 SARIF 보고서를 게시하고 별도의 게이트에서 스캐너의 종료 상태를 복원합니다.

stages:
  - security_scan
  - security_gate

.codex-security-merge-request:
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_SOURCE_PROJECT_ID == $CI_PROJECT_ID && $CI_MERGE_REQUEST_SOURCE_BRANCH_PROTECTED == "true" && $CI_MERGE_REQUEST_TARGET_BRANCH_PROTECTED == "true"'

codex-security:
  extends: .codex-security-merge-request
  stage: security_scan
  image: node:26-bookworm-slim
  environment:
    name: codex-security/openai
    action: access
  variables:
    GIT_DEPTH: "0"
  before_script:
    - apt-get update -qq
    - apt-get install -y -qq --no-install-recommends ca-certificates git python3 ripgrep
    - npm install --prefix /tmp/codex-security-cli --ignore-scripts --no-audit --no-fund @openai/codex-security@0.8.1
  script:
    - |
      set -eu
      test -n "${CODEX_SECURITY_API_KEY:-}"

      CODEX_SECURITY_BIN="/tmp/codex-security-cli/node_modules/.bin/codex-security"
      RESULTS_DIR="/tmp/codex-security-results-$CI_JOB_ID"
      ARTIFACT_DIR="codex-security-artifacts"
      BASE_REVISION="$(git merge-base \
        "$CI_MERGE_REQUEST_DIFF_BASE_SHA" "$CI_COMMIT_SHA")"
      install -d -m 700 "$RESULTS_DIR" "$ARTIFACT_DIR/results"

      codex_security_api_key="$CODEX_SECURITY_API_KEY"
      unset CODEX_SECURITY_API_KEY
      set +e
      OPENAI_API_KEY="$codex_security_api_key" \
        "$CODEX_SECURITY_BIN" scan . \
          --diff "$BASE_REVISION" \
          --head "$CI_COMMIT_SHA" \
          --auth api-key \
          --output-dir "$RESULTS_DIR" \
          --fail-on-severity high \
          --json
      scan_exit="$?"
      set -e
      unset codex_security_api_key

      case "$scan_exit" in
        0|1) ;;
        *) exit "$scan_exit" ;;
      esac

      "$CODEX_SECURITY_BIN" export "$RESULTS_DIR" \
        --export-format sarif \
        --source-root "$CI_PROJECT_DIR" \
        --output "$ARTIFACT_DIR/results.sarif"
      test -s "$ARTIFACT_DIR/results.sarif"
      cp -R "$RESULTS_DIR"/. "$ARTIFACT_DIR/results/"
      printf '%s\n' "$scan_exit" > "$ARTIFACT_DIR/scan-exit-code.txt"
      exit 0
  artifacts:
    when: always
    access: maintainer
    expire_in: 7 days
    paths:
      - codex-security-artifacts/
    reports:
      sarif: codex-security-artifacts/results.sarif

codex-security-gate:
  extends: .codex-security-merge-request
  stage: security_gate
  image: alpine:3.20
  needs:
    - job: codex-security
      artifacts: true
  script:
    - exit "$(cat codex-security-artifacts/scan-exit-code.txt)"

비밀 정보에 접근할 수 있는 작업을 실행하기 전에 .gitlab-ci.yml의 변경 사항을 모두 검토하세요. 이 예제에는 전체 스캔과 자동 수정이 포함되어 있지 않습니다.

운영 환경에 파이프라인 적용하기

  1. 전체 GitLab 파이프라인을 다운로드한 뒤 리포지터리 루트에 .gitlab-ci.yml로 저장하세요. 이미 파이프라인이 있다면 예제의 단계, 숨겨진 템플릿, 작업을 기존 파일에 통합하세요.
  2. 기존 빌드, 테스트, 배포 단계는 유지하세요. 프로젝트에서 workflow: rules를 사용한다면 스캔하려는 파이프라인 이벤트가 허용되는지 확인하세요.

이 예제는 security_scan, security_remediation, security_publish, security_gate 단계를 추가합니다. 스캔 결과만 보고하려면 CODEX_SECURITY_API_KEY만 있으면 됩니다.

기본 설정에서는 같은 프로젝트의 보호 브랜치 간 병합 요청에서만 스캔 작업이 실행됩니다. 보호된 기본 브랜치에 푸시하거나 해당 브랜치에서 파이프라인을 수동으로 실행할 때 스캔하려면 CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH=true로 설정하세요. 보호된 기본 브랜치에서 심층 스캔을 예약하려면 CODEX_SECURITY_SCHEDULED_DEEP_SCAN=true로 설정하고 시간과 비용 예산을 명시하세요.

병합 요청 파이프라인이 보호된 변수와 러너에 접근하려면 다음 조건을 모두 충족해야 합니다.

포크 파이프라인과 보호되지 않은 병합 요청에는 스캔용 자격 증명이 전달되지 않습니다. 비밀 정보에 접근할 수 있는 작업을 실행하기 전에 .gitlab-ci.yml의 변경 사항을 모두 검토하세요. 변수를 마스킹하고 숨겨도 신뢰할 수 없는 CI 코드가 안전해지지는 않습니다.

스캔 실행 및 보안 이슈 검토하기

조건을 충족하는 보호 브랜치 간 병합 요청을 만들거나 보호된 기본 브랜치에서 파이프라인을 실행하세요. 비용이 발생하는 리포지터리 전체 스캔을 실행하기 전에 작은 변경 사항부터 스캔하세요.

codex-security 작업을 열고 아티팩트에 다음 파일이 포함되어 있는지 확인하세요.

  • results/scan-manifest.json
  • results/findings.json
  • results/report.md
  • results.sarif
  • scan-exit-code.txt

그런 다음 파이프라인의 Security 탭을 열어 보고서 수집 시 발생한 경고를 검토하고 보안 이슈의 식별자, 심각도, 소스 코드 위치를 확인하세요. 기본 브랜치 스캔은 프로젝트 취약점 레코드도 생성합니다. 병합 요청에서 발견된 보안 이슈는 파이프라인의 Security 탭이나 병합 요청의 보안 위젯에 표시되지만 프로젝트 전체의 취약점 레코드로 등록되지는 않습니다.

스캔 결과에는 취약한 소스 코드 일부와 판단 근거, 수정 방법이 포함될 수 있으므로 아티팩트 접근을 제한하세요.

스캔 프로필 선택하기

파이프라인은 실행을 트리거한 이벤트에 따라 프로필을 선택합니다.

트리거 대상 모드 추론 수준
같은 프로젝트의 보호 브랜치 간 병합 요청 커밋된 변경 사항 standard low
보호된 기본 브랜치에 푸시하거나 수동 실행할 때(별도 활성화 필요) 리포지터리 전체 standard high
보호된 기본 브랜치에서 예약 실행할 때(별도 활성화 필요) 리포지터리 전체 deep xhigh

병합 요청 스캔은 커밋된 변경 사항에 대한 피드백을 제공합니다. 기본 브랜치 스캔은 변경 사항이 통합된 리포지터리를 검토합니다. 예약 심층 스캔은 주기적으로 더 넓은 범위를 점검합니다. 변경분 스캔 결과는 해당 변경 사항에만 적용되므로, 스캔을 완료했다고 해서 리포지터리 전체에 문제가 없다는 뜻은 아닙니다.

워크플로우는 CLI를 리포지터리 외부에 설치하고 절대 경로로 실행합니다. 모의 실행을 통한 사전 점검에서는 해당 프로세스에만 제공되는 API 키를 사용합니다. 이 점검에서는 유료 스캔을 시작하지 않으며 API 인증, Codex Security 접근 권한, 할당량, 모델 사용 가능 여부도 확인하지 않습니다.

워크플로우는 작업 트리 외부에 스캔 상태와 결과를 기록하고 OPENAI_API_KEY의 범위를 스캔 프로세스로 제한합니다. CLI에는 GitLab 변수 전체가 상속되지 않고 명시적으로 지정한 소수의 환경 변수만 전달됩니다. 변경분 스캔에서는 워크플로우가 병합 기준 커밋을 계산하고 검토 대상인 베이스 리비전과 헤드 리비전을 지정해 스캔합니다.

이 예제는 @openai/codex-security 버전을 0.8.1로 고정합니다. 버전을 변경하기 전에 인증, 아티팩트, SARIF 보고서 수집, 정책 게이트 동작을 다시 테스트하세요.

보고와 정책 적용 분리하기

GitLab은 성공한 보고 작업에서 SARIF 보고서를 수집합니다. 파이프라인은 먼저 보고서를 게시하고 별도의 codex-security-gate 작업에서 스캐너의 종료 상태를 복원합니다.

보고 작업은 스캐너의 종료 코드가 0 또는 1일 때만 보안 이슈를 내보냅니다. 다른 종료 코드가 반환되면 SARIF 내보내기를 건너뛰고 파이프라인을 차단합니다. 내보내기에 실패해도 파이프라인이 차단됩니다.

보고 작업은 실행 오류나 중단 상태를 그대로 전달합니다. 보고 작업이 성공하면 최종 게이트에서 스캐너의 정책 평가 결과를 다음과 같이 복원합니다.

종료 코드 의미
0 스캔이 완료되었으며 정책을 통과했습니다.
1 스캔이 완료되었으며 설정한 심각도 기준 이상의 보안 이슈가 발견되었습니다.
2 스캔 중 입력, 런타임, 대상 무결성 또는 필수 출력 오류가 발생했습니다.
130 / 143 스캔이 중단되거나 종료되었습니다.

이 예제는 --fail-on-severity high를 전달하므로 심각도가 높음 또는 치명적 수준인 보안 이슈가 발견되면 게이트를 통과하지 못합니다. 심각도 기준이 없으면 완료된 스캔은 기본적으로 종료 코드 0을 반환합니다. results/scan-manifest.json에서 설정된 스캔 범위는 scan.scope를, 보안 이슈 비교에서 제외된 경로는 scan.review.excludedPaths를 확인하세요. 후속 작업은 results/report.md를 참고하세요.

수정 및 게시 작업은 최종 정책 게이트 전에 실행됩니다. 따라서 나중에 게이트에서 파이프라인이 실패하더라도 조건을 충족하는 보안 이슈에 대해서는 검증된 수정 사항을 담은 병합 요청 초안이 생성될 수 있습니다.

검증을 거치는 자동 수정 활성화하기

자동 수정은 선택 사항이며 보호된 기본 브랜치의 파이프라인에서만 실행됩니다. Codex 수정 프로세스와 리포지터리에서 정의한 검증 명령어에는 GitLab 프로젝트 액세스 토큰이나 러너가 주입하는 자격 증명이 전달되지 않습니다.

워크플로우는 다음 순서로 진행됩니다.

  1. 현재 리비전의 스캔 완료를 나타내는 매니페스트와 심각도가 high 또는 critical인 보안 이슈가 있는지 확인합니다. 두 조건을 모두 충족해야 다음 단계로 진행합니다.
  2. 패치를 적용하기 전에 지정한 회귀 테스트가 실패하는지 확인합니다.
  3. 패치를 생성하고 CI 파일, 자격 증명 파일, 바이너리 파일 또는 기타 보호 파일을 변경하는 패치는 거부합니다.
  4. OpenAI, GitLab, 레지스트리, 배포용 자격 증명이나 작업 토큰 없이 회귀 테스트를 실행합니다.
  5. verify-fix를 실행해 fixed, still_vulnerable, inconclusive 중 하나를 반환합니다. verify-fix가 fixed를 반환하고 검증 과정에서 패치가 변경되지 않은 경우에만 패치를 게시합니다.

자동 수정을 활성화하려면 다음 보호 변수를 설정하세요.

  • CODEX_SECURITY_ENABLE_REMEDIATION을 true로 설정하세요.
  • CODEX_SECURITY_VERIFICATION_COMMAND에 수정 전에는 종료 코드 1을, 수정 후에는 0을 반환하는 기존 회귀 테스트 명령어를 지정하세요.
  • 필요하면 CODEX_SECURITY_SETUP_COMMAND에 사용자 입력 없이 종속성을 설정하는 명령어를 지정하세요.

특정 구현 방식에 의존하지 않고 코드가 항상 충족해야 하는 보안 조건을 검증하는 회귀 테스트를 선택하세요. 생성된 테스트 변경 사항도 소스 코드 변경 사항만큼 면밀히 검토하세요.

고급 설정: 리포지터리 명령어 격리

validate, patch, verify-fix 명령어에는 해당 프로세스에서만 사용할 수 있는 OPENAI_API_KEY가 전달되며, 인증에는 --auth api-key를 사용합니다. 리포지터리에서 정의한 설정 및 테스트 명령어는 별도의 비특권 사용자로 실행되며, 추적 중인 소스 파일의 쓰기 가능한 복사본을 사용합니다. 복사본에는 Git 메타데이터, 서브모듈 콘텐츠, 다운로드한 아티팩트가 포함되지 않습니다. .git 또는 서브모듈이 필요한 설정 및 테스트 명령어는 자격 증명이 없는 별도 작업을 설계해 실행해야 합니다.

root 소유의 Codex 단계만 원본 체크아웃과 그 옆에 있는 GitLab의 파일형 변수 디렉터리에 접근할 수 있습니다. 복사본에서 사용하는 격리된 환경에는 PATH, HOME, LANG, CI, CI_PROJECT_DIR만 포함됩니다. 명령어에 비밀 정보가 아닌 다른 값이 필요하면 해당 명령어를 검토한 뒤 허용 목록에 값을 추가하세요. 러너에서 사용자를 전환할 수 없다면 자동 수정을 활성화하기 전에 검증 단계를 자격 증명이 없는 별도 작업으로 옮기세요.

병합 요청 초안 게시하기

GitLab 프로젝트 액세스 토큰을 만들고 Developer 역할과 api, write_repository 범위를 지정하세요. 토큰을 보호, 마스킹, 숨김이 적용된 GITLAB_REMEDIATION_TOKEN 변수에 저장하고 환경 범위를 codex-security/publish로만 제한하세요.

게시를 활성화하려면 CODEX_SECURITY_CREATE_MR=true로 설정하세요. 비밀 정보가 아닌 CODEX_SECURITY_MR_TEST_COMMAND에는 생성된 모든 수정 브랜치가 통과해야 하는 프로젝트별 보안 회귀 테스트 명령어를 지정하세요. 보호되지 않은 브랜치에서 생성된 병합 요청이 명령어를 읽을 수 있도록 이 변수에는 보호 설정을 적용하지 마세요. 게시 워크플로우는 다음과 같이 동작합니다.

  • 리포지터리 쓰기 토큰을 받으며 OpenAI 자격 증명은 받지 않습니다.
  • codex-security/fix-<finding-hash> 브랜치를 만듭니다.
  • 병합 요청 초안을 엽니다. 이미 열려 있는 초안이 있으면 중복 생성하지 않고 재사용합니다.
  • 보호되지 않은 수정 브랜치의 회귀 테스트를 비특권 사용자로 실행합니다. 이때 추적 중인 파일만 담긴 복사본을 사용하며 보호된 자격 증명은 제공하지 않습니다.
  • 생성된 변경 사항을 자동으로 병합하지 않습니다.

프로젝트 액세스 토큰을 CI_JOB_TOKEN으로 대체하지 마세요. 이 작업 토큰으로는 병합 요청을 생성할 수 없습니다. 병합하기 전에 제안된 패치, 검증 근거, 보안 이슈를 검토하세요.

선택적 변수 설정하기

활성화할 기능에 필요한 변수만 설정하세요.

변수 필요한 경우 기본값 또는 용도
CODEX_SECURITY_API_KEY 모든 스캔 보호, 마스킹, 숨김 적용. 환경 범위는 codex-security/openai
CODEX_SECURITY_VERSION CLI 업그레이드 0.8.1로 고정. 변경 전 재테스트 필요
CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH 기본 브랜치 전체 스캔 명시적으로 활성화해야 하며 기본값은 꺼짐
CODEX_SECURITY_SCHEDULED_DEEP_SCAN 예약 심층 스캔 명시적으로 활성화해야 하며 기본값은 꺼짐
CODEX_SECURITY_DEEP_MAX_TIME_MINUTES 예약 심층 스캔 필수 시간 예산(분). 0 초과 480 미만
CODEX_SECURITY_DEEP_MAX_COST 예약 심층 스캔 필수 예상 비용 한도(미국 달러). 0 초과
CODEX_SECURITY_ENABLE_REMEDIATION 패치 생성 보호 변수로 활성화하며 기본값은 꺼짐
CODEX_SECURITY_VERIFICATION_COMMAND 패치 생성 보호 변수에 지정하는 회귀 테스트
CODEX_SECURITY_SETUP_COMMAND 선택적 자동 수정 환경 설정 보호 변수에 지정하는 종속성 설치 명령어
CODEX_SECURITY_REMEDIATION_EFFORT 선택적 자동 수정 수준 조정 high
CODEX_SECURITY_MAX_CHANGED_FILES 선택적 패치 크기 제한 기본값은 8, 허용 범위는 1~20
CODEX_SECURITY_CREATE_MR 병합 요청 초안 생성 보호 변수로 활성화하며 기본값은 꺼짐
GITLAB_REMEDIATION_TOKEN 병합 요청 초안 생성 환경 범위를 codex-security/publish로 제한한 Developer 역할의 프로젝트 토큰
CODEX_SECURITY_GITLAB_INTERNAL_URL 자체 호스팅 환경에서 선택적으로 게시 러너에서 접근할 수 있는 GitLab 오리진
CODEX_SECURITY_MR_TEST_COMMAND 병합 요청 초안 게시 비밀 정보를 포함하지 않는 필수 프로젝트별 회귀 테스트
CODEX_SECURITY_MR_SETUP_COMMAND 선택적 수정 브랜치 환경 설정 비밀 정보를 포함하지 않는 종속성 설정 명령어

CI_* 변수는 GitLab이 제공합니다. CODEX_SECURITY_BIN, CODEX_SECURITY_EFFORT, CODEX_SECURITY_MODE, CODEX_SECURITY_STATE_DIR, CODEX_SECURITY_TARGET은 파이프라인이 관리하므로 프로젝트 변수로 설정하지 마세요. 변경분 스캔에서는 CLI가 정규화된 베이스 리비전과 헤드 리비전으로 스캔 대상의 정규 식별자를 결정합니다.

정책 적용 및 비용 조정하기

병합 요청에 대한 피드백에는 변경분 스캔을, 기본 브랜치에는 표준 리포지터리 스캔을, 더 넓은 범위의 점검에는 예약 심층 스캔을 사용하세요. 리포지터리 전체를 스캔하는 두 프로필은 기본적으로 비활성화되어 있습니다. 예약 심층 스캔에는 CODEX_SECURITY_DEEP_MAX_TIME_MINUTES와 CODEX_SECURITY_DEEP_MAX_COST도 필요합니다. CLI 시간 예산은 작업 제한 시간인 8시간보다 짧게 설정하세요. 새 YAML을 적용할 때는 기존 시간 단위 설정을 분 단위로 변환하세요. 예산을 설정하기 전에 대표적인 스캔을 실행해 시간과 비용을 측정하세요. --max-cost는 예상 비용을 제한하는 기준이며 실제 청구 금액의 상한을 보장하지 않습니다.

이 예제에서는 심각도가 높음 또는 치명적 수준인 보안 이슈가 발견되면 게이트를 통과하지 못합니다. 결과만 보고하려면 --fail-on-severity high를 제거하세요. 대표적인 보안 이슈, 스캔 범위, 비용, 실행 시간을 검토한 뒤 심각도 기준을 선택하세요. 심각도 정책은 CI/CD 개요를, 종료 코드에 관한 자세한 내용은 CLI 레퍼런스를 참고하세요.

작업이 실패하면 다음 사항을 확인하세요.

  • 스캔 아티팩트가 누락되었다면 설정이나 러너에 문제가 있을 수 있습니다.
  • 예상하지 못한 경로가 제외되었다면 results/scan-manifest.json에서 스캔 범위와 검토 세부 정보를 확인하세요.
  • GitLab에 보안 이슈가 표시되지 않으면 SARIF 보고 작업이 성공했는지, GitLab이 보고서를 수락했는지 확인하세요.
  • 자동 수정을 건너뛰었다면 보호 브랜치, 스캔 매니페스트, 보안 이슈 심각도, 검증 명령어, 기능 활성화 변수를 확인하세요.
  • 게시 오류가 발생하면 프로젝트 토큰의 역할, 권한 범위, 환경 제한을 확인하세요.

전체 명령어, 플래그, 아티팩트는 Codex Security CLI 레퍼런스를 참고하세요.