Exécuter Codex Security dans CI
Analysez les modifications des pull requests et des merge requests, conservez les résultats structurés, téléversez les fichiers SARIF et définissez une politique de sévérité.
Exécutez la CLI Codex Security dans CI pour examiner précisément les modifications d’une pull request ou d’une merge request, conserver les constats et la couverture, et éventuellement faire échouer la vérification à un niveau de sévérité choisi. Commencez par des résultats à titre informatif, examinez la qualité de l’analyse et sa durée d’exécution, puis ajoutez une politique de sévérité adaptée à votre dépôt.
Ce guide contient des exemples pour GitHub Actions et GitLab CI/CD. Les mêmes commandes d’analyse et d’exportation fonctionnent dans les autres systèmes CI.
Préparer le workflow
Stockez une API key OpenAI dans le magasin de secrets de votre fournisseur CI sous le nom
CODEX_SECURITY_API_KEY.
Associez directement ce secret à la variable d’environnement OPENAI_API_KEY de l’étape
d’analyse. Limitez la portée de l’identifiant au processus d’analyse et utilisez
--auth api-key pour le sélectionner explicitement.
Le runner nécessite :
- Node.js 22 ou version ultérieure.
- Python 3.10 ou version ultérieure.
- Le package
@openai/codex-securitypublié, installé en dehors du checkout du dépôt. - L’historique de la tête et de la base de la pull request ou de la merge request afin que Git puisse calculer la base de fusion.
Ajouter le workflow GitHub Actions
Pour les dépôts privés ou internes, activez GitHub Code Security avant de téléverser un fichier SARIF.
Créez .github/workflows/codex-security.yml. Avant d’effectuer le checkout de la pull
request, installez @openai/codex-security sous
$RUNNER_TEMP/codex-security afin que l’exécutable de confiance soit disponible à l’emplacement
$RUNNER_TEMP/codex-security/node_modules/.bin/codex-security :
name: Codex Security scan
on:
pull_request:
jobs:
codex-security:
if: github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'dependabot[bot]'
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
steps:
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: "26"
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
with:
python-version: "3.14"
- name: Install Codex Security
run: |
set -euo pipefail
npm install \
--prefix "$RUNNER_TEMP/codex-security" \
--ignore-scripts \
--no-audit \
--no-fund \
@openai/codex-security
- name: Verify Codex Security
env:
CODEX_SECURITY_BIN: ${{ runner.temp }}/codex-security/node_modules/.bin/codex-security
run: |
set -euo pipefail
test -x "$CODEX_SECURITY_BIN"
"$CODEX_SECURITY_BIN" --version
- name: Check out the pull request
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
persist-credentials: false
- name: Scan the pull request
env:
OPENAI_API_KEY: ${{ secrets.CODEX_SECURITY_API_KEY }}
CODEX_SECURITY_BIN: ${{ runner.temp }}/codex-security/node_modules/.bin/codex-security
CODEX_SECURITY_STATE_DIR: ${{ runner.temp }}/codex-security-state
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
SCAN_DIR: ${{ runner.temp }}/codex-security-results
run: |
set -euo pipefail
BASE_REVISION="$(git merge-base "$BASE_SHA" "$HEAD_SHA")"
"$CODEX_SECURITY_BIN" scan . \
--diff "$BASE_REVISION" \
--head "$HEAD_SHA" \
--auth api-key \
--output-dir "$SCAN_DIR" \
--json > "$RUNNER_TEMP/codex-security.json"
- name: Export SARIF
id: export-sarif
if: always()
env:
CODEX_SECURITY_BIN: ${{ runner.temp }}/codex-security/node_modules/.bin/codex-security
SCAN_DIR: ${{ runner.temp }}/codex-security-results
SARIF_FILE: ${{ runner.temp }}/codex-security.sarif
run: |
set -euo pipefail
if test -f "$SCAN_DIR/scan-manifest.json"; then
"$CODEX_SECURITY_BIN" export "$SCAN_DIR" \
--export-format sarif \
--source-root "$GITHUB_WORKSPACE" \
--output "$SARIF_FILE"
echo "available=true" >> "$GITHUB_OUTPUT"
fi
- name: Upload SARIF
if: always() && steps.export-sarif.outputs.available == 'true'
uses: github/codeql-action/upload-sarif@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4
with:
sarif_file: ${{ runner.temp }}/codex-security.sarif
ref: refs/pull/${{ github.event.pull_request.number }}/head
sha: ${{ github.event.pull_request.head.sha }}
category: codex-security
- name: Preserve scan results
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: codex-security-results
path: |
${{ runner.temp }}/codex-security-results
${{ runner.temp }}/codex-security.json
if-no-files-found: warn
retention-days: 7Le workflow effectue le checkout de la tête de la pull request, calcule sa base de fusion et
analyse les modifications validées entre ces révisions. L’historique complet garantit une
cible exacte. persist-credentials: false empêche le jeton du dépôt d’être enregistré dans
la configuration Git issue du checkout. L’installation de la CLI avant le checkout et
son exécution à l’aide de son chemin absolu empêchent les exécutables contrôlés par le dépôt d’accéder à
l’identifiant d’analyse. --auth api-key sélectionne explicitement l’API key à portée limitée.
L’analyse enregistre son historique dans un répertoire d’état accessible en écriture situé en dehors du
dépôt.
--json écrit un document JSON complet sur stdout, ce qui permet au workflow de l’enregistrer
directement. La progression, les résumés de fin et les erreurs restent sur stderr. Ce comportement
diffère de codex exec --json, qui émet un flux d’événements JSON Lines.
L’étape d’exportation lit une analyse terminée et scellée, puis écrit le fichier SARIF. Elle ne modifie ni le runtime Codex ni les identifiants. Les artefacts d’analyse peuvent contenir des extraits de code source vulnérable, des éléments de preuve et des détails de remédiation. Choisissez des contrôles d’accès et une courte durée de conservation adaptés à votre dépôt.
Ajouter le pipeline GitLab CI/CD
GitLab peut ingérer des
rapports SARIF 2.1.0
avec GitLab Ultimate 19.2 ou une version ultérieure. Ajoutez une variable CI/CD
CODEX_SECURITY_API_KEY masquée et cachée avant d’exécuter le pipeline.
Ajoutez l’étape security et le job Codex Security au fichier .gitlab-ci.yml racine.
Conservez les étapes et jobs existants dans le fichier. Par défaut, l’exemple analyse les modifications
de la merge request. Définissez CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH sur "true"
pour analyser également la branche par défaut complète :
variables:
CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH: "false"
stages:
- test
- security
codex-security:
stage: security
image: node:26-bookworm-slim
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_SOURCE_PROJECT_ID == $CI_PROJECT_ID'
variables:
CODEX_SECURITY_SCAN_SCOPE: "diff"
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH == "true"'
variables:
CODEX_SECURITY_SCAN_SCOPE: "full"
variables:
GIT_DEPTH: "0"
CODEX_SECURITY_CLI_DIR: "/tmp/codex-security-cli"
before_script:
- |
set -eu
apt-get update -qq
apt-get install -y -qq --no-install-recommends \
ca-certificates \
git \
python3 \
ripgrep
npm install \
--prefix "$CODEX_SECURITY_CLI_DIR" \
--ignore-scripts \
--no-audit \
--no-fund \
@openai/codex-security
export CODEX_SECURITY_BIN="$CODEX_SECURITY_CLI_DIR/node_modules/.bin/codex-security"
test -x "$CODEX_SECURITY_BIN"
"$CODEX_SECURITY_BIN" --version
script:
- |
set -eu
if test -z "${CODEX_SECURITY_API_KEY:-}"; then
echo "Set the CODEX_SECURITY_API_KEY CI/CD variable." >&2
exit 2
fi
codex_security_api_key="$CODEX_SECURITY_API_KEY"
unset CODEX_SECURITY_API_KEY
case "${CODEX_SECURITY_SCAN_SCOPE:-}" in
diff)
BASE_SHA="$CI_MERGE_REQUEST_DIFF_BASE_SHA"
HEAD_SHA="$CI_COMMIT_SHA"
BASE_REVISION="$(git merge-base "$BASE_SHA" "$HEAD_SHA")"
set -- --diff "$BASE_REVISION" --head "$HEAD_SHA"
echo "Scanning committed changes from $BASE_REVISION to $HEAD_SHA."
;;
full)
set -- --mode standard
echo "Scanning the complete default branch at $CI_COMMIT_SHA."
;;
*)
echo "Unsupported Codex Security scan scope: ${CODEX_SECURITY_SCAN_SCOPE:-unset}" >&2
exit 2
;;
esac
export CODEX_SECURITY_STATE_DIR="/tmp/codex-security-state-$CI_JOB_ID"
SCAN_DIR="/tmp/codex-security-results-$CI_JOB_ID"
JSON_FILE="/tmp/codex-security-$CI_JOB_ID.json"
SARIF_FILE="/tmp/codex-security-$CI_JOB_ID.sarif"
install -d -m 700 "$CODEX_SECURITY_STATE_DIR" "$SCAN_DIR"
set +e
OPENAI_API_KEY="$codex_security_api_key" \
"$CODEX_SECURITY_BIN" scan . \
"$@" \
--auth api-key \
--output-dir "$SCAN_DIR" \
--json > "$JSON_FILE"
scan_exit="$?"
set -e
unset codex_security_api_key
install -d -m 700 codex-security-artifacts/results
cp -R "$SCAN_DIR"/. codex-security-artifacts/results/
if test -s "$JSON_FILE"; then
cp "$JSON_FILE" codex-security-artifacts/codex-security.json
fi
printf '%s\n' "$scan_exit" > codex-security-artifacts/scan-exit-code.txt
export_exit=0
if test -f "$SCAN_DIR/scan-manifest.json"; then
set +e
"$CODEX_SECURITY_BIN" export "$SCAN_DIR" \
--export-format sarif \
--source-root "$CI_PROJECT_DIR" \
--output "$SARIF_FILE"
export_exit="$?"
set -e
if test -s "$SARIF_FILE"; then
cp "$SARIF_FILE" codex-security-artifacts/codex-security.sarif
fi
fi
if test "$scan_exit" -ne 0; then
exit "$scan_exit"
fi
exit "$export_exit"
artifacts:
when: always
access: maintainer
expire_in: 7 days
paths:
- codex-security-artifacts/
reports:
sarif: codex-security-artifacts/codex-security.sarifPar défaut, le job s’exécute uniquement pour les merge requests provenant de branches du même
projet, afin que les pipelines de forks ne reçoivent pas l’identifiant d’analyse. Définissez
CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH sur "true" au niveau du groupe, du projet ou
du pipeline pour exécuter également une analyse complète standard sur la branche par défaut. Les analyses
complètes sont plus longues et plus coûteuses que les analyses de différences.
GIT_DEPTH: "0" fournit l’historique nécessaire pour calculer la base de fusion à partir de
CI_MERGE_REQUEST_DIFF_BASE_SHA et CI_COMMIT_SHA lors des analyses de merge requests.
Le job installe la CLI sous /tmp, l’exécute à l’aide de son chemin absolu et expose l’
API key uniquement au processus d’analyse. artifacts: when: always conserve le rapport SARIF
lorsque l’analyse échoue, tandis que artifacts:access: maintainer limite l’accès
aux résultats détaillés de l’analyse.
Les modifications apportées à .gitlab-ci.yml peuvent exposer les variables CI/CD ; examinez donc les modifications du pipeline
avant d’exécuter le job. Si vous
protégez CODEX_SECURITY_API_KEY,
GitLab ne la rend disponible que pour les merge requests du même projet entre
des branches protégées, et uniquement lorsque l’utilisateur peut accéder à la branche cible.
Choisir une politique de sévérité
Les deux exemples génèrent uniquement des rapports, car ils omettent --fail-on-severity. Lorsque vous
êtes prêt à faire dépendre la vérification des constats, ajoutez un seuil à la commande
d’analyse :
"$CODEX_SECURITY_BIN" scan . \
--diff origin/main \
--output-dir /path/outside/repository/results \
--fail-on-severity highLes seuils pris en charge sont critical, high, medium et low. Un
seuil inclut les constats de ce niveau de sévérité et des niveaux supérieurs.
L’étape d’analyse utilise les codes de sortie suivants :
| Sortie | Signification |
|---|---|
0 |
L’analyse s’est terminée avec une couverture complète et toute politique configurée a été respectée. |
1 |
L’analyse terminée contient un constat dont la sévérité atteint ou dépasse le seuil. |
2 |
La CLI a rencontré une erreur d’entrée ou de runtime, ou l’analyse terminée présente une couverture incomplète. |
130 |
Ctrl-C a interrompu l’analyse. |
143 |
SIGTERM a mis fin à l’analyse. |
Une analyse avec une couverture partial ou unknown renvoie 2, même sans politique de
sévérité. La CLI écrit tout de même les constats et les informations de couverture disponibles. Examinez les
zones différées dans coverage.json avant de considérer la vérification comme concluante.
Réessayer avec un répertoire de résultats existant
Utilisez un répertoire de runner neuf pour chaque job CI. Pour un runner persistant ou auto-hébergé,
conservez un résultat antérieur avec --archive-existing :
"$CODEX_SECURITY_BIN" scan . \
--diff origin/main \
--output-dir /path/outside/repository/results \
--archive-existingLa commande archive les résultats antérieurs et démarre avec un répertoire d’analyse vide.
Résoudre les problèmes d’une analyse CI
- Référence Git inconnue ou différence inattendue : récupérez l’historique de la base et de la tête, calculez la base de fusion et transmettez explicitement les deux révisions.
- Répertoire de sortie protégé ou non vide : choisissez un répertoire privé
situé en dehors du worktree Git englobant. Utilisez
--archive-existinglorsque le répertoire contient déjà des résultats. - Identifiants manquants : vérifiez que
CODEX_SECURITY_API_KEYest disponible pour le workflow ou pipeline de confiance et directement associé à la variable d’environnementOPENAI_API_KEYdu processus d’analyse. - Erreur d’historique de l’analyse : définissez
CODEX_SECURITY_STATE_DIRsur un répertoire accessible en écriture situé en dehors du dépôt. - Erreur de configuration de Python : vérifiez que le runner utilise Python 3.10 ou une version ultérieure.
- Couverture incomplète : examinez
coverage.json, notamment les surfaces différées et les questions ouvertes, puis relancez l’analyse avec une cible ou un environnement adapté. - Erreur d’exportation SARIF : vérifiez que l’analyse est terminée et que le répertoire d’analyse complet est disponible. L’exportation valide les artefacts scellés avant d’écrire le fichier SARIF.
- Erreur de téléversement SARIF : pour GitHub Actions, vérifiez que votre organisation
a activé GitHub Code Security pour le dépôt et que le workflow accorde les autorisations
actions: read,contents: readetsecurity-events: write. Pour GitLab CI/CD, vérifiez que le projet utilise GitLab Ultimate 19.2 ou une version ultérieure et que le job téléverse un fichier SARIF 2.1.0 viaartifacts:reports:sarif.
Pour toutes les commandes, options, artefacts et champs de sortie, consultez la référence de la CLI. Pour un examen CI interactif fondé sur un plugin, consultez Examiner les modifications du code du point de vue de la sécurité.