Skip to content

Commit 5418c29

Browse files
Update secure_quality_gitlab.md
1 parent 538c2f1 commit 5418c29

File tree

1 file changed

+134
-136
lines changed

1 file changed

+134
-136
lines changed

examples/codex/secure_quality_gitlab.md

Lines changed: 134 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -370,155 +370,153 @@ Parsed `gl-sast-report.json` and merged overlapping issues.
370370

371371
**Requirement**: This job depends on the previous stage output of the `security_priority.md` file to use as input to generate the patch file for creating an MR
372372
```yaml
373-
# --- Resolution prompt (produces unified git diffs only) ---
374-
CODEX_DIFF_PROMPT: |
375-
You are a secure code remediation assistant.
376-
You will receive:
377-
- The repository working tree (read-only)
378-
- One vulnerability (JSON from a GitLab SAST report)
379-
- Allowed files list
373+
stages:
374+
- remediation
380375
376+
default:
377+
image: node:24
381378
382-
GOAL:
383-
- Create the minimal, safe fix for the vulnerability.
384-
- Output a unified git diff that applies cleanly with `git apply -p0` (or -p1 for a/ b/ paths).
385-
- Prefer surgical changes: input validation, safe APIs, parameterized queries, permission checks.
386-
- Do NOT refactor broadly or change unrelated code.
387-
388-
389-
RULES (must follow exactly):
390-
- PRINT ONLY the diff between the markers below.
391-
- Use repo-relative paths; `diff --git a/path b/path` headers are accepted.
392-
- No binary file changes. No prose/explanations outside the markers.
393-
394-
395-
MARKERS:
396-
=== BEGIN_UNIFIED_DIFF ===
397-
<unified diff here>
398-
=== END_UNIFIED_DIFF ===
399-
400-
401-
If no safe fix is possible without deeper changes, output an empty diff between the markers.
402-
379+
variables:
380+
# Inputs/outputs
381+
SAST_REPORT_PATH: "gl-sast-report.json"
382+
PATCH_DIR: "codex_patches"
383+
CODEX_DIFF_RAW: "artifacts/codex-diff-raw.log"
384+
385+
# --- Resolution prompt (produces unified git diffs only) ---
386+
CODEX_DIFF_PROMPT: |
387+
You are a secure code remediation assistant.
388+
You will receive:
389+
- The repository working tree (read-only)
390+
- One vulnerability (JSON from a GitLab SAST report)
391+
- Allowed files list
392+
393+
GOAL:
394+
- Create the minimal, safe fix for the vulnerability.
395+
- Output a unified git diff that applies cleanly with `git apply -p0` (or -p1 for a/ b/ paths).
396+
- Prefer surgical changes: input validation, safe APIs, parameterized queries, permission checks.
397+
- Do NOT refactor broadly or change unrelated code.
398+
399+
RULES (must follow exactly):
400+
- PRINT ONLY the diff between the markers below.
401+
- Use repo-relative paths; `diff --git a/path b/path` headers are accepted.
402+
- No binary file changes. No prose/explanations outside the markers.
403+
404+
MARKERS:
405+
=== BEGIN_UNIFIED_DIFF ===
406+
<unified diff here>
407+
=== END_UNIFIED_DIFF ===
408+
409+
If no safe fix is possible without deeper changes, output an empty diff between the markers.
403410

404411
# ---------------------------
405-
# Stage: remediation → Job 2 (Resolution / git diffs)
412+
# Stage: remediation → Generate unified diffs/patches
406413
# ---------------------------
407414
codex_resolution:
408-
stage: remediation
409-
needs:
410-
- job: codex_recommendations
411-
artifacts: true
412-
rules:
413-
- if: '$OPENAI_API_KEY'
414-
when: on_success
415-
- when: never
416-
variables:
417-
SAST_REPORT_PATH: "gl-sast-report.json"
418-
PATCH_DIR: "codex_patches"
419-
CODEX_DIFF_RAW: "artifacts/codex-diff-raw.log"
420-
script:
421-
- set -euo pipefail
422-
- mkdir -p "$PATCH_DIR" artifacts
423-
424-
- apt-get update && apt-get install -y --no-install-recommends bash git jq curl ca-certificates
425-
- npm -g i @openai/codex@latest
426-
- git --version && codex --version || true
427-
415+
stage: remediation
416+
rules:
417+
- if: '$OPENAI_API_KEY'
418+
when: on_success
419+
- when: never
420+
script:
421+
- set -euo pipefail
422+
- mkdir -p "$PATCH_DIR" artifacts
428423

429-
# If SAST missing, no-op (job still visible/success)
430-
- |
431-
if [ ! -s "${SAST_REPORT_PATH}" ]; then
432-
echo "No SAST report found; resolution will no-op."
433-
printf "CODEX_CREATED_PATCHES=false\n" > codex.env
434-
exit 0
435-
fi
424+
# Deps
425+
- apt-get update && apt-get install -y --no-install-recommends bash git jq curl ca-certificates
426+
- npm -g i @openai/codex@latest
427+
- git --version && codex --version || true
436428

437-
# Filter High/Critical
438-
- |
439-
jq -c '.vulnerabilities[]? | select((.severity|ascii_downcase)=="high" or (.severity|ascii_downcase)=="critical")' "$SAST_REPORT_PATH" \
440-
| nl -ba > /tmp/hicrit.txt || true
429+
# Require SAST report; no-op if missing
430+
- |
431+
if [ ! -s "${SAST_REPORT_PATH}" ]; then
432+
echo "No SAST report found; remediation will no-op."
433+
printf "CODEX_CREATED_PATCHES=false\n" > codex.env
434+
exit 0
435+
fi
441436
437+
# Pull High/Critical items
438+
- jq -c '.vulnerabilities[]? | select((.severity|ascii_downcase)=="high" or (.severity|ascii_downcase)=="critical")' "$SAST_REPORT_PATH" \
439+
| nl -ba > /tmp/hicrit.txt || true
440+
- |
441+
if [ ! -s /tmp/hicrit.txt ]; then
442+
echo "No High/Critical vulnerabilities found. Nothing to fix."
443+
printf "CODEX_CREATED_PATCHES=false\n" > codex.env
444+
exit 0
445+
fi
442446
443-
if [ ! -s /tmp/hicrit.txt ]; then
444-
echo "No High/Critical vulnerabilities found. Nothing to fix."
445-
printf "CODEX_CREATED_PATCHES=false\n" > codex.env
446-
exit 0
447-
fi
447+
# Ground Codex to actual repo files
448+
- FILE_LIST="$(git ls-files | sed 's/^/- /')"
448449

449-
- FILE_LIST="$(git ls-files | sed 's/^/- /')"
450-
- git config user.name "CI Codex Bot"
451-
- git config user.email "[email protected]"
450+
# Identity for any local patch ops
451+
- git config user.name "CI Codex Bot"
452+
- git config user.email "[email protected]"
452453

453-
- created=0
454+
- created=0
454455

455-
# Loop per finding → compose prompt via a temp file (robust) → run Codex → extract diff
456-
- |
457-
while IFS=$'\t' read -r idx vuln_json; do
458-
echo "Processing vulnerability #$idx"
459-
echo "$vuln_json" > "/tmp/vuln-$idx.json"
460-
461-
# --- Compose prompt into a temp file (no heredocs/quoting traps) ---
462-
PROMPT_FILE="$(mktemp)"
463-
{
464-
printf "%s\n\n" "$CODEX_DIFF_PROMPT"
465-
printf "VULNERABILITY_JSON:\n<<JSON\n"
466-
cat "/tmp/vuln-$idx.json"
467-
printf "\nJSON\n\n"
468-
printf "EXISTING_REPOSITORY_FILES (exact list):\n"
469-
printf "%s\n" "$FILE_LIST"
470-
} > "$PROMPT_FILE"
471-
472-
PER_FINDING_PROMPT="$(tr -d '\r' < "$PROMPT_FILE")"
473-
rm -f "$PROMPT_FILE"
474-
475-
: > "$CODEX_DIFF_RAW"
476-
set +o pipefail
477-
codex exec --full-auto "$PER_FINDING_PROMPT" | tee -a "$CODEX_DIFF_RAW" >/dev/null
478-
RC=${PIPESTATUS[0]}
479-
set -o pipefail
480-
echo "Codex (diff) exit code: ${RC}"
481-
482-
OUT_PATCH="$PATCH_DIR/fix-$idx.patch"
483-
sed -E 's/\x1B\[[0-9;]*[A-Za-z]//g' "$CODEX_DIFF_RAW" \
484-
| tr -d '\r' \
485-
| awk '
486-
/^\s*=== BEGIN_UNIFIED_DIFF ===\s*$/ {grab=1; next}
487-
/^\s*=== END_UNIFIED_DIFF ===\s*$/ {grab=0}
488-
grab
489-
' > "$OUT_PATCH"
490-
491-
# must contain at least one diff hunk
492-
if ! [ -s "$OUT_PATCH" ] || ! grep -qE '^\s*diff --git ' "$OUT_PATCH"; then
493-
echo " No usable diff produced for #$idx; skipping."
494-
rm -f "$OUT_PATCH"
495-
continue
496-
fi
497-
498-
# Validate apply; accept -p0 (repo-relative) or -p1 (a/ b/ prefixes)
499-
if git apply --check -p0 "$OUT_PATCH" || git apply --check -p1 "$OUT_PATCH"; then
500-
echo " Patch validated for #$idx → $OUT_PATCH"
501-
created=$((created+1))
502-
else
503-
echo " Patch failed to apply cleanly; removing."
504-
rm -f "$OUT_PATCH"
505-
fi
506-
done < /tmp/hicrit.txt
507-
508-
echo "Total patches created: $created"
509-
if [ "$created" -gt 0 ]; then
510-
printf "CODEX_CREATED_PATCHES=true\nPATCH_DIR=%s\n" "$PATCH_DIR" > codex.env
511-
else
512-
printf "CODEX_CREATED_PATCHES=false\n" > codex.env
513-
fi
514-
artifacts:
515-
when: always
516-
paths:
517-
- codex_patches/
518-
- artifacts/codex-diff-raw.log
519-
reports:
520-
dotenv: codex.env
521-
expire_in: 14 days
456+
# Loop: build prompt (robust temp-file), run Codex, extract diff, validate
457+
- |
458+
while IFS=$'\t' read -r idx vuln_json; do
459+
echo "Processing vulnerability #$idx"
460+
echo "$vuln_json" > "/tmp/vuln-$idx.json"
461+
462+
PROMPT_FILE="$(mktemp)"
463+
{
464+
printf "%s\n\n" "$CODEX_DIFF_PROMPT"
465+
printf "VULNERABILITY_JSON:\n<<JSON\n"
466+
cat "/tmp/vuln-$idx.json"
467+
printf "\nJSON\n\n"
468+
printf "EXISTING_REPOSITORY_FILES (exact list):\n"
469+
printf "%s\n" "$FILE_LIST"
470+
} > "$PROMPT_FILE"
471+
472+
PER_FINDING_PROMPT="$(tr -d '\r' < "$PROMPT_FILE")"
473+
rm -f "$PROMPT_FILE"
474+
475+
: > "$CODEX_DIFF_RAW"
476+
set +o pipefail
477+
codex exec --full-auto "$PER_FINDING_PROMPT" | tee -a "$CODEX_DIFF_RAW" >/dev/null
478+
RC=${PIPESTATUS[0]}
479+
set -o pipefail
480+
echo "Codex (diff) exit code: ${RC}"
481+
482+
OUT_PATCH="$PATCH_DIR/fix-$idx.patch"
483+
sed -E 's/\x1B\[[0-9;]*[A-Za-z]//g' "$CODEX_DIFF_RAW" \
484+
| tr -d '\r' \
485+
| awk '
486+
/^\s*=== BEGIN_UNIFIED_DIFF ===\s*$/ {grab=1; next}
487+
/^\s*=== END_UNIFIED_DIFF ===\s*$/ {grab=0}
488+
grab
489+
' > "$OUT_PATCH"
490+
491+
if ! [ -s "$OUT_PATCH" ] || ! grep -qE '^\s*diff --git ' "$OUT_PATCH"; then
492+
echo " No usable diff produced for #$idx; skipping."
493+
rm -f "$OUT_PATCH"
494+
continue
495+
fi
496+
497+
# Validate: accept -p0 (repo-relative) or -p1 (a/ b/ prefixes)
498+
if git apply --check -p0 "$OUT_PATCH" || git apply --check -p1 "$OUT_PATCH"; then
499+
echo " Patch validated → $OUT_PATCH"
500+
created=$((created+1))
501+
else
502+
echo " Patch failed to apply cleanly; removing."
503+
rm -f "$OUT_PATCH"
504+
fi
505+
done < /tmp/hicrit.txt
506+
507+
if [ "$created" -gt 0 ]; then
508+
printf "CODEX_CREATED_PATCHES=true\nPATCH_DIR=%s\n" "$PATCH_DIR" > codex.env
509+
else
510+
printf "CODEX_CREATED_PATCHES=false\n" > codex.env
511+
fi
512+
artifacts:
513+
when: always
514+
paths:
515+
- codex_patches/
516+
- artifacts/codex-diff-raw.log
517+
reports:
518+
dotenv: codex.env
519+
expire_in: 14 days
522520
```
523521
524522
Example generated patch:

0 commit comments

Comments
 (0)