אבטחת צינור עיבוד הנתונים של CI/CD באמצעות CodeMender

1. לפני שמתחילים

ברוכים הבאים ל-Codelab המעשי בנושא אבטחת פייפליין של CI/CD באמצעות CodeMender.

בהכנת תוכנה להפצה מודרנית, כלים לניתוח סטטי (כמו CodeQL) חיוניים לזיהוי דפוסים תחביריים מוכרים, אבל לעיתים קרובות הם מפספסים נקודות חולשה מורכבות שמוסתרות עמוק בתוך הלוגיקה העסקית, ויוצרים התראות רועשות ולא מאומתות.

‫CodeMender (קובץ הפעלה של CLI: ‏cm) משפר את צינור עיבוד הנתונים של CI/CD – ופועל לצד כלי SAST קיימים – על ידי פריסת סוכני הסקת מסקנות בנושא אבטחה שמבוססים על Gemini של Google כדי:

חשיפת פגמים מורכבים בלוגיקה העסקית: הסקת מסקנות לגבי ההקשר של האפליקציה וזרימת הנתונים בארכיטקטורה, מעבר לכללי דפוסים סטטיים נוקשים.

צמצום משמעותי של התראות שווא באמצעות אימות ניצול פרצות עצמי: הוכחה דינמית של יכולת הניצול בסביבות ארגז חול (sandbox) לפני שליחת התראות למפתחים.

תיקון אוטומטי של ממצאים מאומתים: סינתזה של תיקוני קוד, אימות מול חבילות מקרים לבדיקה כדי למנוע רגרסיות ושליחת בקשות Pull שמוכנות לבדיקה.

ב-Codelab הזה תשלבו את CodeMender במאגר OWASP Juice Shop באמצעות GitHub Actions ואיחוד שירותי אימות הזהות של עומסי עבודה (WIF) ללא מפתחות ב-Google Cloud.

דרישות מוקדמות

  • מומלץ: היכרות בסיסית עם המושגים של CodeMender (מפורטים במאמר אבטחת האפליקציה באמצעות CodeMender)
  • הבנה בסיסית של תהליכי עבודה, טריגרים ותחביר YAML של פעולות GitHub
  • היכרות בסיסית עם פקודות Git ותהליכי עבודה של בדיקת בקשות משיכה (pull request)
  • ידע בסיסי במושגים של Google Cloud IAM (חשבונות שירות, תפקידים וממשקי API)
  • היכרות עם נקודות חולשה נפוצות באפליקציות אינטרנט (כמו הזרקת SQL ו-XSS)

מה תלמדו

  • איך להגדיר אימות ללא מפתח בגישת אבטחה של אמון אפס בין GitHub Actions לבין Google Cloud באמצעות איחוד שירותי אימות הזהות של עומסי עבודה (WIF)
  • איך ליצור תהליך עבודה אוטומטי של בדיקת נקודות חולשה באמצעות CodeMender ו-gemini-3.8-flash
  • איך לפרסם דוחות אבטחה שניתן לפעול לפיהם באמצעות OASIS SARIF גרסה 2.1.0 וסיכומי משימות מקוריים של GitHub Actions
  • איך לבנות תהליך עבודה אוטונומי לתיקון שיוצר תיקוני קוד מאומתים בבדיקה ופותח בקשות משיכה לבדיקה אנושית
  • איך לאכוף שערי איכות אוטומטיים (--fail-on) ושמירת צינור עיבוד נתונים במטמון לאבטחה רציפה במהירות גבוהה

מה תצטרכו

  • פרויקט ב-Google Cloud עם חיוב מופעל והרשאות בעלים/עריכה של הפרויקט
  • חשבון GitHub עם הרשאות ליצור מאגרים, להגדיר סודות ולנהל פעולות (בשלב 3, אתם יוצרים פיצול של מאגר OWASP Juice Shop ב-GitHub באמצעות ה-CLI של GitHub).

2. הסבר על ארכיטקטורת ה-CI/CD של CodeMender

ב-DevSecOps מודרני בארגונים, אבטחה מבוססת-AI לא יכולה להיות רק כלי ידני למחשב. הוא צריך לפעול כשומר סף אוטומטי (לחסום בקשות משיכה לא מאובטחות) וכמפתח שותף אוטונומי (להציע תיקונים מאומתים ישירות ל-Git).

כדי לעשות את זה, תטמיעו ארכיטקטורה של תהליך עבודה כפול שמבוססת על איחוד שירותי אימות הזהות של עומסי העבודה (WIF) ב-Google Cloud ועל מודלים של חשיבה רציונלית ב-Gemini Enterprise.

ארכיטקטורה של תהליך עבודה כפול

ארכיטקטורת צינור עיבוד הנתונים האוטונומי של CI/CD ב-CodeMender

במקום לדחוס את הזיהוי והתיקון לסקריפט מונוליטי אחד, צינור עיבוד הנתונים מפריד את האבטחה לשני תהליכי עבודה נפרדים, שכל אחד מהם מיועד למטרה מסוימת:

תהליך עבודה

טריגר ראשי

תחומי האחריות העיקריים

שער איכות קשיח

1. סורק לבדיקת נקודות חולשה(codemender-scan.yml)

בקשות משיכה, דחיפות ראשיות, Cron שבועי, שליחה ידנית

• מריץ סריקות AST דיפרנציאליות מהירות בבקשות משיכה (כ-15 שניות), סריקות בסיסיות מהירות בדחיפות (–quick) וביקורות עומק בו-זמניות לפי לוחות זמנים • מאמת את המוכנות מראש באמצעות cm health –strict • יוצר סיכומי משימות מקוריים של Actions ומעלה את OASIS SARIF לכרטיסיית האבטחה של GitHub

חסימת מיזוג של בקשות משיכה אם זוהו נקודות חולשה חדשות ברמת חומרה גבוהה או קריטית (–fail-on)

2. Autonomous Remediator(codemender-remediate.yml)

טריגר ידני (workflow_dispatch), Cron לילי

‫• ממשיך את המצב מפריטי הסריקה (cm report import) וstate.db• מסנתז תיקונים באמצעות יכולות החשיבה של Gemini • שומר על גבולות נקיים של סביבת העבודה ושולח בקשות Pull שמוכנות לבדיקה

מוודא שההבדלים בסביבת הייצור נקיים לפני שפותחים בקשת משיכה (PR)

שלושה עקרונות ליבה לעיצוב ארגוני

כשאתם בונים את תהליכי העבודה האלה בקטעים הבאים, חשוב לזכור את שלושת עמודי התווך האלה של הארכיטקטורה:

‫🔑 אימות ללא מפתח במודל אבטחה של אפס אמון ואימות לפני ההפעלה:

מפתחות JSON של חשבון שירות ב-Google Cloud לטווח ארוך לא מאוחסנים ב-GitHub Secrets. ה-runner יוצר אסימון OIDC לטווח קצר שמוחלף באמצעות Google Cloud STS בפרטי כניסה זמניים לשעה, מגדיר את persist-credentials: false ב-Git checkouts ומריץ את cm health --strict כדי לאמת את פרטי הכניסה, הנגישות לרשת והרשאות ה-IAM לפני שהוא משתמש במכסת המודל.

⚡ ניתוב סריקה אדפטיבי ודיכוי רעשים מדור קודם:

במקום להריץ בדיקות איטיות של מאגרים מלאים בכל בקשת משיכה, CodeMender מנתב כל אירוע CI למצב הסריקה האופטימלי: בקשות משיכה מפעילות ניתוח AST דיפרנציאלי (--diff="origin/$BASE_REF") בקבצים שהשתנו ובמתקשרים עם דילוג אחד תוך פחות מ-15 שניות; דחיפות של הסתעפות ראשית מריצות סריקות בסיסיות מהירות של סשן יחיד (--quick); ולוחות זמנים שבועיים מריצים בדיקות מעמיקות בו-זמנית של קובץ אחר קובץ (ברירת המחדל cm find .). נקודות חולשה קיימות בבסיס הקוד שלא הושפעו מבקשת משיכה מסומנות בתווית [LEGACY / UNTOUCHED]; הן מופיעות בדוחות SARIF לצורך חשיפה, אבל לא חוסמות את שער המיזוג של בקשת המשיכה ולא מפעילות תיקון אוטומטי.

‫🛡️ תצפיתיות אבטחה עמידה ללא חסימה:

גם כש---fail-on יוצא עם קוד 1 כדי לחסום בקשת משיכה לא מאובטחת, הגנה על שלבי הייצוא של הדוח וההעלאה של SARIF באמצעות steps.scan.outputs.completed == 'true' ו-hashFiles('results.sarif') != '' מבטיחה שההתראות של OASIS SARIF וסיכומי המשימות עדיין יתפרסמו, תוך דילוג נקי על הייצוא וההעלאה אם ההרצה מבוטלת או מופסקת בגלל שגיאת הגדרה או קיבולת (10–60).

‫3. אימות והכנה של מאגר היעד ב-Cloud Shell

כדי להגדיר אימות ללא מפתחות ולהריץ צינורות עיבוד נתונים אוטומטיים של אבטחה, אתם צריכים מאגר GitHub נגיש שבבעלותכם. ב-Codelab הזה תשתמשו ב-OWASP Juice Shop – אפליקציית אינטרנט של Node.js עם נקודות חולשה מכוונות – כסביבת אבטחה מוכנה לשימוש.

כדי לבצע אימות מול GitHub, לתעד את פרטי המשתמש באופן אוטומטי ולהכין את המאגר בתהליך אחד יעיל, תשתמשו ב-GitHub CLI (gh) שמותקן מראש ב-Google Cloud Shell.

שלב 1: פותחים את Cloud Shell ומאמתים את GitHub CLI

פותחים את מסוף Google Cloud ומפעילים את Cloud Shell (הסמל >_ בסרגל הניווט העליון).

מאמתים את ה-CLI של GitHub‏ (gh) כדי להגדיר את ניהול פרטי הכניסה ל-Git:

gh auth login --hostname github.com --git-protocol https --web

פועלים לפי ההוראות במסך:

מעתיקים את הקוד החד-פעמי בן 8 התווים שמופיע ב-Cloud Shell (למשל, 1234-ABCD).

מקישים על Enter כדי לפתוח את https://github.com/login/device בדפדפן.

מדביקים את הקוד ולוחצים על Authorize github.

שלב 2: ייצוא משתנים באופן דינמי ופיצול של OWASP Juice Shop

מריצים את הפקודות הבאות ב-Cloud Shell כדי לתעד באופן אוטומטי את שם המשתמש ב-GitHub ולהכין את המאגר:

# 1. Automatically capture your GitHub username (customize GITHUB_REPO if desired)
export GITHUB_ORG=$(gh api user -q .login)
export GITHUB_REPO="${GITHUB_REPO:-juice-shop}"
export GITHUB_REPOSITORY="${GITHUB_ORG:+${GITHUB_ORG}/${GITHUB_REPO}}"
echo "Authenticated as: ${GITHUB_REPOSITORY}"

# 2. Fork on GitHub server using GITHUB_REPO as the fork name
gh repo fork juice-shop/juice-shop --fork-name "${GITHUB_REPO}" --default-branch-only --clone=false 2>/dev/null || true

# 3. Shallow clone your fork (downloads only ~15 MB in 3-5 seconds, skipping heavy upstream git history)
[ -d ~/"${GITHUB_REPO}" ] || git clone --depth=1 "https://github.com/${GITHUB_REPOSITORY}.git" ~/"${GITHUB_REPO}" || \
 (sleep 2 && git clone --depth=1 "https://github.com/${GITHUB_REPOSITORY}.git" ~/"${GITHUB_REPO}")
cd ~/"${GITHUB_REPO}"

# 4. Confirm you are in the repository directory
git status

4. הגדרת איחוד שירותי אימות הזהות של עומסי עבודה ב-Google Cloud באמצעות gcloud

בשלב הזה, תשתמשו ב-CLI של gcloud ב-Google Cloud Shell כדי להפעיל את ממשקי ה-API הנדרשים, ליצור חשבון שירות ייעודי ל-CI/CD, להגדיר את מאגר הזהויות של עומסי העבודה וליצור אמון ב-OIDC עם מאגר GitHub שלכם (${GITHUB_REPOSITORY}).

שלב 1: הגדרת משתני סביבה ב-Google Cloud

במסוף Cloud Shell (בתוך סביבת העבודה של המאגר המשוכפל), מתעדים את מזהה הפרויקט הפעיל ב-Google Cloud, מאמתים את המשתנה של מאגר GitHub ומגדירים את שמות המשאבים של WIF:

# Capture active Google Cloud Project ID and verify GitHub repository
export PROJECT_ID=$(gcloud config get-value project)
export GITHUB_USER=$(gh api user -q ".login")
export GITHUB_REPO="${GITHUB_REPO:-$(git remote get-url origin 2>/dev/null | sed -E 's#^.*/##; s#\.git$##')}"
export GITHUB_REPO="${GITHUB_REPO:-juice-shop}"
export GITHUB_REPOSITORY="${GITHUB_USER:+${GITHUB_USER}/${GITHUB_REPO}}"

# Define WIF and Service Account resource names
export WORKLOAD_IDENTITY_POOL="codemender-github-pool"
export WORKLOAD_IDENTITY_PROVIDER="codemender-github-provider"
export SERVICE_ACCOUNT_NAME="codemender-ci-runner"

if [ -z "${PROJECT_ID}" ] || [ -z "${GITHUB_REPOSITORY}" ]; then
 echo "ERROR: PROJECT_ID ('${PROJECT_ID}') or GITHUB_REPOSITORY ('${GITHUB_REPOSITORY}') is empty. Check 'gcloud config get-value project' and 'gh auth status'."
else
 echo "Project ID:        ${PROJECT_ID}"
 echo "GitHub Repository: ${GITHUB_REPOSITORY}"
fi

שלב 2: הפעלת ממשקי ה-API הנדרשים של Google Cloud

מפעילים את IAM API,‏ Security Token Service API,‏ IAM Credentials API,‏ Agent Platform API ו-Resource Manager API:

gcloud services enable \
 iam.googleapis.com \
 iamcredentials.googleapis.com \
 sts.googleapis.com \
 aiplatform.googleapis.com \
 cloudresourcemanager.googleapis.com \
 --project=${PROJECT_ID}

שלב 3: יוצרים חשבון שירות ייעודי ל-CI/CD

יוצרים חשבון שירות ב-Google Cloud עם הרשאות מינימליות, שמיועד להרצת צינור עיבוד הנתונים של CI/CD (אפשר להשתמש בו שוב בבטחה אם הוא כבר קיים):

export SERVICE_ACCOUNT_EMAIL="${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com"

gcloud iam service-accounts describe "${SERVICE_ACCOUNT_EMAIL}" \
 --project="${PROJECT_ID}" >/dev/null 2>&1 || \
gcloud iam service-accounts create "${SERVICE_ACCOUNT_NAME}" \
 --display-name="CodeMender CI/CD Pipeline Runner" \
 --project="${PROJECT_ID}"

echo "Service Account Email: ${SERVICE_ACCOUNT_EMAIL}"

שלב 4: נותנים הרשאות IAM ל-Agent Platform

מקצים לחשבון השירות את התפקיד roles/aiplatform.user (משתמש ב-Agent Platform) כדי שהוא יוכל לתקשר עם Gemini Enterprise Agent Platform:

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
 --member="serviceAccount:${SERVICE_ACCOUNT_EMAIL}" \
 --role="roles/aiplatform.user"

שלב 5: יצירת מאגר הזהויות של עומסי העבודה

יוצרים את מאגר הזהויות של עומסי העבודה כדי לנהל את טענות הנכוֹנוּת (assertions) של הזהויות בפעולות של GitHub (או משחזרים ומפעילים אותו באופן אוטומטי אם הוא כבר קיים בפרויקט):

POOL_STATE=$(gcloud iam workload-identity-pools list \
 --location="global" \
 --show-deleted \
 --project="${PROJECT_ID}" \
 --filter="name ~ /${WORKLOAD_IDENTITY_POOL}$" \
 --format="value(state)")

if [ -z "${POOL_STATE}" ]; then
 gcloud iam workload-identity-pools create "${WORKLOAD_IDENTITY_POOL}" \
   --location="global" \
   --display-name="CodeMender GitHub Pool" \
   --project="${PROJECT_ID}"
else
 [ "${POOL_STATE}" = "DELETED" ] && gcloud iam workload-identity-pools undelete "${WORKLOAD_IDENTITY_POOL}" \
   --location="global" \
   --project="${PROJECT_ID}"
 gcloud iam workload-identity-pools update "${WORKLOAD_IDENTITY_POOL}" \
   --location="global" \
   --no-disabled \
   --project="${PROJECT_ID}"
fi

שלב 6: יצירת ספק Workload Identity באמצעות GitHub OIDC

יוצרים (או מעדכנים) את ספק ה-OIDC במאגר, מקשרים את כתובת ה-URL של המנפיק https://token.actions.githubusercontent.com וממפים את טענות הנכוֹנוּת (assertions) של אסימון GitHub למאפייני STS של Google:

PROVIDER_STATE=$(gcloud iam workload-identity-pools providers list \
 --workload-identity-pool="${WORKLOAD_IDENTITY_POOL}" \
 --location="global" \
 --show-deleted \
 --project="${PROJECT_ID}" \
 --filter="name ~ /${WORKLOAD_IDENTITY_PROVIDER}$" \
 --format="value(state)")

if [ -z "${GITHUB_REPOSITORY}" ]; then
 echo "ERROR: GITHUB_REPOSITORY is empty. Re-run Step 1 before configuring the OIDC provider."
elif [ -z "${PROVIDER_STATE}" ]; then
 gcloud iam workload-identity-pools providers create-oidc "${WORKLOAD_IDENTITY_PROVIDER}" \
   --workload-identity-pool="${WORKLOAD_IDENTITY_POOL}" \
   --location="global" \
   --display-name="CodeMender GitHub Provider" \
   --issuer-uri="https://token.actions.githubusercontent.com" \
   --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository,attribute.repository_owner=assertion.repository_owner" \
   --attribute-condition="assertion.repository == '${GITHUB_REPOSITORY}'" \
   --project="${PROJECT_ID}"
else
 [ "${PROVIDER_STATE}" = "DELETED" ] && gcloud iam workload-identity-pools providers undelete "${WORKLOAD_IDENTITY_PROVIDER}" \
   --workload-identity-pool="${WORKLOAD_IDENTITY_POOL}" \
   --location="global" \
   --project="${PROJECT_ID}"
 gcloud iam workload-identity-pools providers update-oidc "${WORKLOAD_IDENTITY_PROVIDER}" \
   --workload-identity-pool="${WORKLOAD_IDENTITY_POOL}" \
   --location="global" \
   --issuer-uri="https://token.actions.githubusercontent.com" \
   --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository,attribute.repository_owner=assertion.repository_owner" \
   --attribute-condition="assertion.repository == '${GITHUB_REPOSITORY}'" \
   --no-disabled \
   --project="${PROJECT_ID}"
fi

שלב 7: מתן הרשאה למאגר ב-GitHub להתחזות לחשבון השירות

מקשרים את התפקיד roles/iam.workloadIdentityUser כדי לאפשר לאסימונים שמקורם במאגר להתחזות לחשבון השירות של ה-CI runner, ומאמתים את קישור המדיניות:

# Retrieve the canonical Workload Identity Pool resource ID
export POOL_ID=$(gcloud iam workload-identity-pools describe "${WORKLOAD_IDENTITY_POOL}" \
 --project="${PROJECT_ID}" \
 --location="global" \
 --format="value(name)")

if [ -z "${POOL_ID}" ] || [ -z "${GITHUB_REPOSITORY}" ]; then
 echo "ERROR: POOL_ID ('${POOL_ID}') or GITHUB_REPOSITORY ('${GITHUB_REPOSITORY}') is empty. Re-run Step 1 and Step 5."
else
 # Bind Workload Identity User role to the principalSet of your repository
 gcloud iam service-accounts add-iam-policy-binding "${SERVICE_ACCOUNT_EMAIL}" \
   --project="${PROJECT_ID}" \
   --role="roles/iam.workloadIdentityUser" \
   --member="principalSet://iam.googleapis.com/${POOL_ID}/attribute.repository/${GITHUB_REPOSITORY}"

 # Verify the principalSet binding on the Service Account
 gcloud iam service-accounts get-iam-policy "${SERVICE_ACCOUNT_EMAIL}" \
   --project="${PROJECT_ID}"
fi

שלב 8: אחזור ערכי הגדרה לסודות של GitHub

אחזור שם המשאב המלא של ספק מאגרי זהויות של עומסי עבודה ושמירה שלו במשתנה סביבה לרישום אוטומטי בשלב הבא:

# Retrieve full Workload Identity Provider name
export WORKLOAD_PROVIDER_NAME=$(gcloud iam workload-identity-pools providers describe ${WORKLOAD_IDENTITY_PROVIDER} \
 --workload-identity-pool=${WORKLOAD_IDENTITY_POOL} \
 --location="global" \
 --project=${PROJECT_ID} \
 --format="value(name)")

echo "=========================================================="
echo "WIF CONFIGURATION READY:"
echo "=========================================================="
echo "GCP_WORKLOAD_IDENTITY_PROVIDER: ${WORKLOAD_PROVIDER_NAME}"
echo "GCP_SERVICE_ACCOUNT:            ${SERVICE_ACCOUNT_EMAIL}"
echo "=========================================================="

5. הגדרת סודות והרשאות לתהליכי עבודה במאגר ב-GitHub

עכשיו, אחרי שהקציתם את Google Cloud WIF, אתם צריכים להגדיר את הסודות של מאגר GitHub ולתת את ההרשאות הנדרשות לתהליך העבודה כדי לבצע סריקות אבטחה אוטומטיות ולתקן באופן אוטומטי בקשות משיכה.

אתם יכולים לקבוע את ההגדרות האלה ישירות מ-Cloud Shell באמצעות ה-CLI של GitHub‏ (gh), וכך להימנע לחלוטין מהעתקה והדבקה ידנית של שמות ארוכים של משאבים.

שלב 1: הגדרת סודות המאגר באמצעות ה-CLI של GitHub

במסוף Cloud Shell, מריצים את הפקודות הבאות כדי להגדיר באופן מאובטח את שני הסודות הנדרשים של המאגר באמצעות משתני הסביבה הפעילים:

# 1. Set the Workload Identity Provider resource name
gh secret set GCP_WORKLOAD_IDENTITY_PROVIDER \
 --body "${WORKLOAD_PROVIDER_NAME}" \
 --repo "${GITHUB_REPOSITORY}"

# 2. Set the CI/CD Service Account email
gh secret set GCP_SERVICE_ACCOUNT \
 --body "${SERVICE_ACCOUNT_EMAIL}" \
 --repo "${GITHUB_REPOSITORY}"

# 3. Verify the secrets are registered
gh secret list --repo "${GITHUB_REPOSITORY}"

שלב 2: נותנים הרשאות לתהליך העבודה של בקשות משיכה אוטומטיות

כברירת מחדל, תהליכי עבודה של פעולות GitHub פועלים עם הרשאות לקריאה בלבד ולא יכולים ליצור בקשות משיכה. בשלב 9, CodeMender ייצור וישלח באופן אוטונומי בקשות משיכה מאומתות לתיקון.

נותנים הרשאות כתיבה ומפעילים יצירה של בקשות משיכה ישירות דרך GitHub API:

[ -d .git ] || cd ~/"${GITHUB_REPO:-juice-shop}"
export GITHUB_REPOSITORY="${GITHUB_REPOSITORY:-$(git remote get-url origin 2>/dev/null | sed -E 's#^.*github\.com[:/]##; s#\.git$##')}"

gh api \
 --method PUT \
 -H "Accept: application/vnd.github+json" \
 /repos/${GITHUB_REPOSITORY}/actions/permissions/workflow \
 -f default_workflow_permissions="write" \
 -F can_approve_pull_request_reviews=true

שלב 3: השבתת תהליכי עבודה קודמים של Juice Shop שעברו בירושה

פיצול של OWASP Juice Shop מעביר יותר מ-16 תהליכי עבודה של CI במעלה הזרם (כמו PR Compliance Check,‏ CI/CD Pipeline ו-CodeQL Scan) יחד עם תבנית של בקשת משיכה (PR) של תורם במעלה הזרם, שסוגרת באופן אוטומטי בקשות משיכה שמטרגטות את master. משביתים את כל תהליכי העבודה שלא קשורים ל-CodeMender דרך ה-CLI של GitHub, ומסירים את הקבצים במעלה הזרם באופן מקומי כדי שה-fork יריץ רק תהליכי עבודה של CodeMender:

[ -d .git ] || cd ~/"${GITHUB_REPO:-juice-shop}"
export GITHUB_REPOSITORY="${GITHUB_REPOSITORY:-$(git remote get-url origin 2>/dev/null | sed -E 's#^.*github\.com[:/]##; s#\.git$##')}"

# 1. Disable all inherited non-CodeMender workflows in GitHub Actions (and CodeQL default setup if active)
for WF_ID in $(gh workflow list --all --limit 100 --repo "${GITHUB_REPOSITORY}" --json id,path \
 -q '.[] | select((.path | startswith(".github/workflows/")) and (.path | test("codemender-") | not)) | .id'); do
 gh workflow disable "${WF_ID}" --repo "${GITHUB_REPOSITORY}" 2>/dev/null || true
done
gh api -X PATCH "/repos/${GITHUB_REPOSITORY}/code-scanning/default-setup" \
 -f state=not-configured >/dev/null 2>&1 || true

# 2. Remove upstream workflow files and PR template from the local workspace
for f in .github/workflows/*; do
 case "$f" in *codemender-*) ;; *) rm -f "$f" ;; esac
done
rm -f .github/PULL_REQUEST_TEMPLATE.md

6. יצירת תהליך עבודה אוטומטי לבדיקת נקודות חולשה באמצעות SARIF

בשלב הזה, תכתבו את תהליך העבודה הראשי של סריקת האבטחה הרציפה (.github/workflows/codemender-scan.yml) שמריץ סריקות בסיסיות על דחיפות של הסתעפויות, שערים דיפרנציאליים בבקשות משיכה וייצוא של SARIF לסריקת קוד ב-GitHub.

שלב 1: מורידים את תהליך העבודה של הסריקה ב-CodeMender

מורידים את codemender-scan.yml ממאגר ההתחלה אל .github/workflows/:

[ -d .git ] || cd ~/"${GITHUB_REPO:-juice-shop}"
mkdir -p .github/workflows
curl -fsSL https://raw.githubusercontent.com/edwardc-gcp/codemender-github-actions/main/.github/workflows/codemender-scan.yml \
 -o .github/workflows/codemender-scan.yml

שלב 2: ביצוע commit, דחיפה והפעלת סריקת CI

שומרים את השינויים בתהליך העבודה ודוחפים אותם ישירות להסתעפות הראשית של המאגר (master ב-Juice Shop או main):

# Stage workflow changes, commit, and push to primary branch
git add -A .github
git commit -m "ci: add CodeMender SARIF security scanning workflow"
git push origin $(git branch --show-current)

בדפדפן:

עוברים למאגר המחובר ב-GitHub: ‏https://github.com/YOUR_GITHUB_USER/juice-shop (למשל, https://github.com/octocat/juice-shop).

לוחצים על הכרטיסייה פעולות בסרגל הניווט העליון.

בסרגל הצד הימני, בקטע Workflows, בוחרים באפשרות CodeMender Security Scan & SARIF Export.

מפעילים או מציגים את ביצוע תהליך העבודה:

טריגר אוטומטי: אם מופיעה הרצה אוטומטית שהופעלה על ידי ה-push, לוחצים עליה ישירות כדי לעקוב אחרי הביצוע בזמן אמת.

טריגר ידני לפי דרישה (workflow_dispatch): אם עדיין לא התחילה הרצה, לוחצים על הכפתור Run workflow ▾ בצד ימין, מוודאים שהאפשרות Branch: master נבחרה (משאירים את תיבת הסימון deep_scan לא מסומנת כדי שהסריקה המהירה של --quick תרוץ) ולוחצים על הכפתור הירוק Run workflow.

לוחצים על ההרצה שמתבצעת ובוחרים באפשרות Autonomous Code Vulnerability Scan כדי לצפות בתהליך העבודה בזמן אמת.

בתוך codemender-scan.yml: ניתוב סריקה לפי אירועים

בזמן שסריקת הבסיס של --quick פועלת בענן (בערך 3-5 דקות), בודקים איך codemender-scan.yml (שורות 118-155) מנתב כל אירוע ב-GitHub למצב הסריקה הייעודי שלו בתוך ה-runner:

# Excerpt from .github/workflows/codemender-scan.yml
if [ "${{ github.event_name }}" = "pull_request" ]; then
 cm find . \
   --diff="origin/${{ github.base_ref }}" \
   --diff-workers=16 \
   --fail-on="CRITICAL,HIGH" \
   --sandbox=false --yes --bypass-warning || status=$?
elif [ "${{ github.event_name }}" = "schedule" ] || [ "${{ github.event.inputs.deep_scan }}" = "true" ]; then
 cm find . \
   --deep-workers=8 \
   --sandbox=false --yes --bypass-warning || status=$?
else
 cm find . \
   --quick \
   --sandbox=false --yes --bypass-warning || status=$?
fi

הגדרת Hardened Runner (שורות 27-117): דילוג על פיצולים חיצוניים לא מהימנים ובקשות משיכה (PR) של dependabot[bot], ביצוע checkout באמצעות persist-credentials: false, שמירה במטמון של ~/.local/bin/cm ו-~/.codemender/state.db והרצת cm health --strict לפני ניצול מכסת המודל.

גבולות של ארגז חול ללא ממשק משתמש (--sandbox=false --yes --bypass-warning): משבית את הבידוד של מרחב השמות של המשתמשים ב-Linux (מוגבל בתוך קונטיינרים של GitHub Actions ללא הרשאות) תוך שמירה על אכיפת הגבולות של נתיב סביבת העבודה (project_paths) ו-command_policy.yaml.

Exit-Code Guarded SARIF & Artifact Export ( שורות 147–194): מגדיר את steps.scan.outputs.completed=true רק כש-cm find יוצא עם 0 (נקי) או 1 (הסף של --fail-on הושג). כך מובטח שדוחות SARIF (cm report -f sarif עם ציוני חומרה של CVSS), טבלאות $GITHUB_STEP_SUMMARY (cm report -f md) ופריטי מידע שנוצרו בתהליך הפיתוח (Artifact) של codemender-findings.json עדיין יתפרסמו כש---fail-on חוסם בקשת Pull, תוך דילוג על ייצוא במקרה של שגיאות בהגדרה או בקיבולת (10–60), כדי שקובצי SARIF ריקים לא יסגרו אף פעם התראות קיימות.

7. בדיקת ההתראות של GitHub Code Scanning ומרכז הבקרה לאבטחה

אחרי שתהליך העבודה של דחיפת קו הבסיס מסתיים, GitHub מעבד את קובץ ה-SARIF שהועלה ומאכלס גם את סיכום ההרצה של הפעולות וגם את הכרטיסייה Security של המאגר.

שלב 1: בדיקת סיכום המשימה המקורי ב-GitHub Actions

כל הפעלה של תהליך עבודה מוסיפה טבלת סיכום בפורמט Markdown‏ (cm report -f md) ישירות לסקירה הכללית של ההפעלה של פעולות GitHub:

במאגר שלכם ב-GitHub, לוחצים על הכרטיסייה Actions.

בוחרים את ההרצה שהושלמה של CodeMender Security Scan & SARIF Export (ביקורות של דחיפת ענף בסיס מסתיימות בסימן וי ירוק ✅ אחרי פרסום הממצאים של SARIF).

גוללים למטה לקטע 🛡️ CodeMender Security Scan Summary כדי לבדוק את פירוט הממצאים:

🔒 דוח האבטחה של CodeMender

סיכום

סה"כ ממצאים: 28

רמת החומרה

מספר יחידות

🔴 קריטי

6

‫🟠 גבוהה

16

‫🟡 בינוני

6

סטטוס

מספר יחידות

🔴 פתוח

28

ממצאים

מזהה

רמת החומרה

ביטחון

סטטוס

תיקון

קובץ

Title

c1b96b9a

🔴 קריטי

100%

פתיחה

—

routes/userProfile.ts

הרצת קוד מרחוק באמצעות הזרקת קוד בצד השרת בפרופיל המשתמש

cd47b38a

🔴 קריטי

100%

פתיחה

—

routes/login.ts

הזרקת SQL בנתיב אימות המשתמשים

a47a9e45

🔴 קריטי

100%

פתיחה

—

routes/b2bOrder.ts

הרצת קוד מרחוק באמצעות בריחה מארגז חול (sandbox) בעיבוד הזמנות B2B

שלב 2: בודקים את לוח הבקרה המרכזי של סריקת הקוד

בסרגל הניווט העליון של המאגר ב-GitHub, לוחצים על הכרטיסייה Security and quality (או Security).

בסרגל הצד הימני, בקטע Findings, לוחצים על Code scanning.

אם כמה כלים פעילים, מסננים את הכלי ל-CodeMender (is:open branch:master tool:CodeMender) כדי לבדוק את ההתראות שממופות עם תגי חומרת CVSS מקוריים:

תג חומרה

כותרת של נקודת חולשה

המיקום שזוהה

Branch

🔴 קריטי

הרצת קוד מרחוק באמצעות הזרקת קוד בצד השרת בפרופיל המשתמש

routes/userProfile.ts:58

master

🔴 קריטי

הזרקת SQL בנתיב אימות המשתמשים

routes/login.ts:34

master

🔴 קריטי

הרצת קוד מרחוק באמצעות בריחה מארגז חול (sandbox) בעיבוד הזמנות B2B

routes/b2bOrder.ts:21

master

לוחצים על SQL Injection in User Authentication Route (routes/login.ts:34) כדי לבדוק את תהליך הנתונים הפגום ואת ניתוח שורש הבעיה שנוצר על ידי Gemini.

8. חסימת בקשת משיכה לא מאובטחת באמצעות סריקה דיפרנציאלית

בסריקה הבסיסית נמצאו 28 נקודות חולשה קיימות ב-OWASP Juice Shop. במנתחים סטטיים מסורתיים, 28 ממצאי המדור הקודם האלה היו גורמים לכל בקשת משיכה (pull request) עתידית להיכשל עד שכל הבעיות היו נפתרות, מה שהיה מאלץ את הצוותים להשבית את חסימת המיזוג.

‫עכשיו תבדקו את שער ה-AST הדיפרנציאלי של בקשת ה-Pull (--diff + --fail-on="CRITICAL,HIGH") של CodeMender בפעולה: פותחים בקשת Pull שמציגה נקודת חולשה חדשה וצופים ב-CodeMender מבודד את הדלתא, חוסם את המיזוג תוך כ-15-25 שניות ומוסיף הערות לשורות הפוגעות המדויקות.

שלב 1: פותחים בקשת משיכה (Pull Request) שמכילה פגם של הזרקת פקודות

ב-Cloud Shell (בתוך סביבת העבודה של המאגר המשוכפל), יוצרים הסתעפות של תכונה, מוסיפים נתיב Express חדש שמכיל נקודת חולשה של הזרקת פקודות למערכת ההפעלה ופותחים בקשת משיכה (Pull Request) מול הפיצול:

[ -d .git ] || cd ~/"${GITHUB_REPO:-juice-shop}"
export GITHUB_REPOSITORY="${GITHUB_REPOSITORY:-$(git remote get-url origin 2>/dev/null | sed -E 's#^.*github\.com[:/]##; s#\.git$##')}"
PRIMARY_BRANCH=$(git symbolic-ref --short refs/remotes/origin/HEAD | sed 's@^origin/@@')

# Reset any previous demo PR/branch so this step can be re-run cleanly
gh pr close feat/diagnostics --repo "${GITHUB_REPOSITORY}" --delete-branch 2>/dev/null || true
git checkout "${PRIMARY_BRANCH}"
git checkout -B feat/diagnostics

# Introduce an Express endpoint vulnerable to OS Command Injection (CWE-78)
cat << 'EOF' > routes/diagnostics.ts
import { execSync } from 'node:child_process'
import { type Request, type Response } from 'express'

export function systemDiagnostics () {
 return (req: Request, res: Response) => {
   const host = String(req.query.host ?? '127.0.0.1')
   const output = execSync(`ping -c 1 ${host}`).toString()
   res.status(200).json({ status: 'ok', output })
 }
}
EOF

git add routes/diagnostics.ts
git commit -m "feat: add network diagnostics endpoint"
git push -f -u origin feat/diagnostics

gh pr create \
 --repo "${GITHUB_REPOSITORY}" \
 --base "${PRIMARY_BRANCH}" \
 --head feat/diagnostics \
 --title "feat: add network diagnostics endpoint" \
 --body "Adds a ping diagnostics handler."

שלב 2: אימות של שער המיזוג הדיפרנציאלי וההערה המוטבעת בבקשת ה-Pull

פותחים את כתובת ה-URL של בקשת משיכה (pull request) שמופיעה בסוף הפלט של הטרמינל.

גוללים לתיבה Checks בתחתית דף השיחה של בקשת ה-Pull וצופים ב-Autonomous Code Vulnerability Scan:

מהירות דלתא: במקום לסרוק את כל יותר מ-680 הקבצים במאגר (בערך 3-5 דקות), cm find . --diff="origin/${PRIMARY_BRANCH}" מגביל את הניתוח רק ל-routes/diagnostics.ts (ולכל קריאה עם דילוג אחד), ומשלים את הסריקה תוך בערך 15-25 שניות.

בידוד חובות מדור קודם וחסימת מיזוג: אף אחת מ-28 נקודות החולשה הקיימות של Juice Shop לא נכשלת בבדיקה – רק CRITICALהזרקת הפקודה החדשה מפעילה את --fail-on="CRITICAL,HIGH", ויוצאת עם קוד הסטטוס 1 (❌ אדום) כדי לחסום את מיזוג ה-PR.

לוחצים על הכרטיסייה Files changed בחלק העליון של בקשת משיכה (pull request):

מכיוון שההגנה על קוד היציאה של תהליך העבודה (steps.scan.outputs.completed == 'true') עדיין מייצאת ומעלה את results.sarif כש---fail-on יוצא עם הקוד 1, סריקת הקוד של GitHub מציגה הערת אבטחה מוטמעת מסוג CodeMender — Critical ישירות מתחת ל-execSync ב-routes/diagnostics.ts.

שלב 3: מנקים את בקשת ה-Pull לבדיקה וחוזרים להסתעפות הראשית

לפני שממשיכים לתיקון האוטונומי, מחליפים את סביבת העבודה של Cloud Shell בחזרה ל-branch הראשי וסוגרים את בקשת ה-Pull הלא מאובטחת לבדיקה:

[ -d .git ] || cd ~/"${GITHUB_REPO:-juice-shop}"
export GITHUB_REPOSITORY="${GITHUB_REPOSITORY:-$(git remote get-url origin 2>/dev/null | sed -E 's#^.*github\.com[:/]##; s#\.git$##')}"
PRIMARY_BRANCH=$(git symbolic-ref --short refs/remotes/origin/HEAD | sed 's@^origin/@@')
git checkout "${PRIMARY_BRANCH}"
gh pr close feat/diagnostics --repo "${GITHUB_REPOSITORY}" --delete-branch
git branch -D feat/diagnostics 2>/dev/null || true

9. יצירת תהליך עבודה לתיקון אוטונומי וליצירת בקשות משיכה אוטומטיות

עכשיו, כששער ה-Pull Request מונע כניסה של נקודות חולשה חדשות לבסיס הקוד, אתם יכולים לפרוס את Autonomous Remediation (.github/workflows/codemender-remediate.yml) כדי לתקן באופן פעיל נקודות חולשה קיימות ולפתוח בקשות Pull Request שמוכנות לבדיקה.

שלב 1: מורידים את קובץ תהליך התיקון

‫CodeMender מספק שתי תבניות לתיקון, בהתאם להרשאות הגישה למאגר:

מאגרים ציבוריים או בקוד פתוח (codemender-remediate.yml): מצב חשיפה אחראית – קישורים להתראות SARIF של סריקת קוד ב-GitHub בלי לחשוף באופן ציבורי וקטורים גולמיים של ניצול לרעה.

מאגרים פרטיים / ארגוניים (codemender-remediate-private-repo.yml): מצב ראיות של ביקורת פנימית - מטמיע ארטיפקטים של אימות (PLAN.md, REPORT.md, exploit.sh) בתוך מקטעי PR הניתנים לקיפול, תוך אי הכללתם מ-Git commits.

מורידים את תהליך העבודה לתיקון שמוגדר כבטוח לציבור למאגר:

mkdir -p .github/workflows
curl -fsSL https://raw.githubusercontent.com/edwardc-gcp/codemender-github-actions/main/.github/workflows/codemender-remediate.yml \
 -o .github/workflows/codemender-remediate.yml

שלב 2: אישור והפעלה של תהליך התיקון האוטומטי

שומרים ודוחפים את תהליך התיקון לענף הראשי:

git add .github/workflows/codemender-remediate.yml
git commit -m "ci: add CodeMender autonomous remediation workflow"
git push origin $(git branch --show-current)

בדפדפן, עוברים לכרטיסייה Actions במאגר ב-GitHub.

בסרגל הצד הימני, בקטע Workflows, בוחרים באפשרות CodeMender Autonomous Security Remediation & Auto-PR.

לוחצים על התפריט הנפתח הירוק Run workflow (הפעלת תהליך עבודה) בצד שמאל:

Use workflow from: מוודאים שהענף שמוגדר כברירת מחדל (master) נבחר.

Specific Finding ID or prefix to fix: מזינים את הקידומת בת 8 התווים של routes/login.ts שצוינה בשלב 7 (לדוגמה, cd47b38a). אם משאירים את השדה הזה ריק, התיקון באצווה יתבצע בכל הממצאים הפתוחים ברמת חומרה קריטית וגבוהה (כ-10 עד 15 דקות). אם מטרגטים מזהה יחיד, התיקון מסתיים תוך כ-45 עד 60 שניות.

לוחצים על הכפתור הירוק Run workflow בחלון הקופץ ופותחים את ההרצה.

הפעלת תהליך העבודה של CodeMender Autonomous Security Remediation דרך התפריט הנפתח Run workflow (הפעלת תהליך עבודה)

בתוך codemender-remediate.yml: סינתזה אוטונומית של תיקונים

בזמן ש-CodeMender יוצר את התיקון בענן (בערך 30-45 שניות), בודקים איך codemender-remediate.yml (שורות 111-184) מתזמר את התיקון בתוך ה-runner:

המשך ללא סריקה (cm report import): הורדת פריט המידע שנוצר בתהליך העבודה של הסריקה (codemender-findings.json) וייבוא שלו לסביבת העבודה (cm report import -f codemender-findings.json). המערכת חוזרת ל-cm find . --quick רק אם אין פריט מידע קודם.

יצירת תיקונים ללא ממשק משתמש (cm fix): מצמיד את project_paths ל-$GITHUB_WORKSPACE, מעביר את < /dev/null כדי למנוע תקיעות אינטראקטיביות, ומעביר את --no-reset במהלך לולאות אצווה כדי שהתיקונים המצטברים יישמרו בין הממצאים:

# Executed inside the GitHub Actions runner (codemender-remediate.yml)
cm fix "${SPECIFIC_TARGET}" --sandbox=false --yes --bypass-warning < /dev/null

שמירות (Commit) של קוד ייצור נקי (שורות 155-252): מנקה את .cm_project, .exploit/ וקבצים זמניים באמצעות .git/info/exclude לפני ש-peter-evans/create-pull-request@v8 פותח את ההסתעפות (codemender/auto-remediation-${{ github.run_id }}), ושומר רק שינויים בקוד הייצור:

--- a/routes/login.ts
+++ b/routes/login.ts
@@ -28,8 +28,8 @@ module.exports = function login () {
-    models.sequelize.query(`SELECT * FROM Users WHERE email = '${req.body.email || ''}' AND password = '${security.hash(req.body.password || '')}' AND deletedAt IS NULL`, { model: models.User })
+    models.sequelize.query('SELECT * FROM Users WHERE email = :email AND password = :password AND deletedAt IS NULL', {
+      replacements: { email: req.body.email || '', password: security.hash(req.body.password || '') },
+      model: models.User
+    })

שלב 3: בודקים את בקשת המשיכה (pull request) החדשה שנפתחה ב-GitHub

עוברים לכרטיסייה Pull requests במאגר ופותחים את בקשת ה-Pull החדשה (למשל, 🛡️ [CodeMender] Fix: SQL Injection in User Authentication Route).

לוחצים על Files changed כדי לוודא שרק routes/login.ts השתנה, וכל המטא-נתונים הפנימיים של זמן הריצה לא נכללים.

בודקים את תיאור ה-PR שמקשר ישירות להתראה של GitHub Code Scanning (SARIF)‎ כדי לקבל אישור מהמנהל.

10. פתרון בעיות במקרי קצה ובמאגרים פרטיים

מאגרים פרטיים בלי GitHub Advanced Security‏ (GHAS)

מאגרי GitHub ציבוריים מקבלים הטמעה חינמית ובלתי מוגבלת של SARIF לסריקת קוד ב-GitHub. עם זאת, אם תפרסו את תהליך העבודה הזה במאגר פרטי של Enterprise שאין לו רישיון פעיל של GitHub Advanced Security‏ (GHAS), השלב upload-sarif ייכשל עם השגיאה:

HTTP 403: Advanced Security must be enabled for this repository to use code scanning.

פתרון: דוח HTML אינטראקטיבי עצמאי כחלופה

הכלי המובנה ליצירת דוחות HTML ב-CodeMender‏ (cm report -f html) יוצר מרכז בקרה עצמאי ואינטראקטיבי לאבטחה, שכולל כרטיסי מדדים של חומרת הבעיה, קטעי קוד עם הדגשת תחביר ומספרי שורות, ותצוגה מוטמעת של ההבדלים בין התיקונים, ללא תלות באינטרנט החיצוני.

כדי לתמוך במאגרים פרטיים בלי רישיון GHAS, צריך לעדכן את .github/workflows/codemender-scan.yml כך שיעביר לארכיון פריט מידע שנוצר בתהליך הפיתוח (artifact) של דוח HTML במקום להעלות קובץ SARIF:

יצירת דוח HTML עצמאי: בשלב Export Security Reports & Publish Job Summary, מייצאים לוח בקרה ב-HTML לצד סיכום Markdown באמצעות cm report -f html > codemender-audit-report.html.

העברת הדוח לארכיון כארטיפקט של תהליך עבודה: מחליפים את השלב Upload SARIF Report to GitHub Code Scanning (github/codeql-action/upload-sarif@v4) ב-actions/upload-artifact@v4 שמוגדר להעלות את codemender-audit-report.html (לדוגמה, בשם הארטיפקט codemender-security-report).

בדיקה מקומית בכל דפדפן: מורידים את codemender-security-report.zip ישירות מדף הסיכום של הרצת תהליך העבודה של GitHub Actions, מחלצים אותו ופותחים את codemender-audit-report.html בכל דפדפן אינטרנט כדי לבצע בדיקה ויזואלית.

תיקון אוטונומי של מאגר פרטי עם ראיות מוטמעות לביקורת

במאגרים פרטיים של חברות, צוותי ההנדסה והאבטחה צריכים גישה מלאה לניתוח של שורש הבעיה, להוכחת היתכנות של ניצול לרעה ולתוכנית התיקון, בלי להשתמש במרכזי בקרה של כלים חיצוניים. עם זאת, הוספת סקריפטים של ניצול פרצות (exploit.sh) או קובצי Markdown פנימיים (PLAN.md, LOG.md) להסתעפות של המאגר מזהמת את היסטוריית ה-Git ויכולה להפעיל התראות שווא מסורקי אבטחה אחרים.

כדי לטפל בבעיה, צריך לפרוס את תהליך העבודה הייעודי לתיקון מאגרים פרטיים (codemender-remediate-private-repo.yml):

curl -fsSL https://raw.githubusercontent.com/edwardc-gcp/codemender-github-actions/main/.github/workflows/codemender-remediate-private-repo.yml \
 -o .github/workflows/codemender-remediate.yml
git add .github/workflows/codemender-remediate.yml
git commit -m "ci: switch to private repository remediation workflow with embedded audit evidence"
git push origin $(git branch --show-current)

איך פועל תיקון של מאגר פרטי

אימות דינמי של הוכחת היתכנות (cm verify): מסנתז ובודק ניצול פרצה פעיל לפני יצירת התיקון כדי לאשר את יכולת הניצול – דילוג אוטומטי על cm fix אם האימות מסמן ממצא שלא ניתן לנצל כDISMISSED.

Embedded PR Audit Collapsibles: חילוץ של REPORT.md,‏ PLAN.md ו-exploit.sh ל-/tmp/codemender-evidence/ ועיצוב שלהם ישירות בתיאור של בקשת ה-Pull בתוך בלוקים ניתנים לכיווץ של <details open>, כדי שהבודק יוכל לבדוק אותם בלחיצה אחת.

העברת פריטים לארכיון: העברת תיקיית ההוכחות המלאה לארכיון באמצעות actions/upload-artifact@v4.

Pristine Git Commits: מנקה את כל המטא-נתונים של זמן הריצה ואת הספריות של .exploit, כך שה-git commit של בקשת משיכה (pull request) מכיל רק שינויים בקוד הייצור.

רשימת משימות לפתרון בעיות באיחוד שירותי אימות הזהות של עומסי עבודה (WIF)

כברירת מחדל, google-github-actions/auth@v2 כותב קובץ תצורה מקומי של פרטי כניסה מאוחדים במהלך ההגדרה, והחלפת אסימון OAuth 2.0 בפועל מתרחשת כש-cm health --strict או cm find מתחילים. כדי לאבחן שגיאות אימות של HTTP 400 או HTTP 403, אפשר להיעזר ברשימת המשימות הבאה:

תסמין השגיאה

שורש הבעיה הנפוץ

אימות ותיקון

‫HTTP 403 (הגישה אל iam.serviceAccounts.getAccessToken נדחתה)

חסר קישור של roles/iam.workloadIdentityUser בחשבון השירות, סוד GCP_SERVICE_ACCOUNT שגוי או ש-iamcredentials.googleapis.com לא מופעל.

מוודאים ש-GCP_SERVICE_ACCOUNT תואם ל-codemender-ci-runner@.iam.gserviceaccount.com ומריצים את בדיקת מדיניות ה-IAM שבהמשך כדי לאמת את הקישור של principalSet.

‫HTTP 400 (unauthorized_client או שתנאי המאפיין נדחה)

שם המאגר (או האותיות הרישיות) של OIDC –attribute-condition לא תואם למאגר GitHub שמפעיל את תהליך העבודה, או שספק ה-WIF מושבת.

מריצים מחדש את שלב 4 (שלבים 1 ו-6) ומוודאים ש-${GITHUB_REPOSITORY} תואם בדיוק לאותיות הרישיות של owner/repo ב-GitHub, ושהוחל –no-disabled.

‫HTTP 400 (invalid_grant בהחלפת טוקנים)

פורמט שגוי של –issuer-uri או מיפוי חסר של attribute.repository=assertion.repository בספק ה-OIDC.

מוודאים שהערך של –issuer-uri מוגדר בדיוק כ-https://token.actions.githubusercontent.com (בלי לוכסן בסוף).

שגיאת HTTP 403 זמנית מיד אחרי ההגדרה

ההפצה של IAM גלובלי ושל איחוד שירותי אימות הזהות של עומסי עבודה יכולה להימשך בין דקה ל-5 דקות בקישורים שנוצרו לאחרונה.

מחכים דקה או שתיים ולוחצים על Re-run failed jobs ב-GitHub Actions.

כדי לבדוק את הקישור של Workload Identity בחשבון השירות של CI/CD ב-Cloud Shell, מריצים את הפקודה הבאה:

gcloud iam service-accounts get-iam-policy "${SERVICE_ACCOUNT_EMAIL}" \
 --project="${PROJECT_ID}" \
 --flatten="bindings[].members" \
 --filter="bindings.role=roles/iam.workloadIdentityUser"

מוודאים שהפלט מקשר את roles/iam.workloadIdentityUser אל principalSet://iam.googleapis.com/<POOL_ID>/attribute.repository/<GITHUB_USER>/<GITHUB_REPO>:

---
bindings:
 members: principalSet://iam.googleapis.com/.../attribute.repository/<OWNER>/<REPO>
 role: roles/iam.workloadIdentityUser

פתרון בעיות שקשורות לבדיקות מקדימות של CI/CD ולקודי יציאה של CLI

הפקודות של CodeMender‏ (cm health --strict,‏ cm find,‏ cm verify ו-cm fix) מחזירות קודי יציאה דטרמיניסטיים, כדי שצינורות עיבוד הנתונים של CI/CD יוכלו להבחין מיד בין ממצאי אבטחה לבין שגיאות בהגדרה או בשירות:

קוד יציאה

קטגוריה

שורש הבעיה ופתרונות

0

הפעולה הצליחה

בדיקות התקינות עברו או שהסריקה הושלמה ללא ממצאים שחוסמים את ההעברה.

1

ממצאים / כללי

‫–fail-on זיהה CRITICAL או HIGH נקודות חולשה שחוסמות בבקשת משיכה (צפוי כשל בשער המיזוג).

10

credentials

החלפת הטוקן של WIF OAuth/ADC נכשלה (400/401). צריך לאמת את GCP_WORKLOAD_IDENTITY_PROVIDER, GCP_SERVICE_ACCOUNT ואת הקישור של roles/iam.workloadIdentityUser למעלה.

20

config

תחביר פגום של .codemender/config.yaml או ~/.codemender/config.yaml.

30

reachability

ה-Runner לא יכול להגיע אל aiplatform.googleapis.com (DNS, שרת proxy, הפסקת שירות או VPC Service Controls).

40

authorization

בחשבון השירות חסר roles/aiplatform.user בפרויקט היעד, או ש-cloudresourcemanager.googleapis.com / aiplatform.googleapis.com מושבת.

50

timeout

בדיקת קדם ההפעלה cm health חרגה מהמועד האחרון של 30 שניות.

60

capacity

הסוכן הגיע למגבלת המשימות הפעילות בו-זמנית. צריך להפעיל מחדש את תהליך העבודה אחרי עיכוב קצר.

לשגיאות נוספות בזמן הריצה, כמו פתרון הסתעפות בסיס של Git diff‏ (fetch-depth: 0), עיכובים בהפצת משאבים או הרשאות ליצירת בקשות משיכה של GitHub Actions, עיינו במדריך הרשמי לפתרון בעיות ב-CodeMender CI/CD.

11. מחיקת משאבים

כדי למנוע צריכת משאבים מתמשכת או לנקות את הגדרות הבדיקה בסביבות Google Cloud ו-GitHub, בצעו את שלבי הניקוי הבאים.

שלב 1: הסרת הסודות של המאגר ב-GitHub והשבתת תהליכי העבודה באמצעות gh CLI

משתמשים ב-CLI של GitHub (gh) כדי למחוק בצורה נקייה את הסודות של Actions במאגר ולהשבית את תהליכי העבודה של CodeMender:

# Delete the repository Actions secrets
gh secret delete GCP_WORKLOAD_IDENTITY_PROVIDER --repo "${GITHUB_REPOSITORY}" 2>/dev/null || true
gh secret delete GCP_SERVICE_ACCOUNT --repo "${GITHUB_REPOSITORY}" 2>/dev/null || true

# Disable the CodeMender workflows to prevent unwanted automatic triggers
gh workflow disable codemender-scan.yml --repo "${GITHUB_REPOSITORY}" 2>/dev/null || true
gh workflow disable codemender-remediate.yml --repo "${GITHUB_REPOSITORY}" 2>/dev/null || true

שלב 2: משביתים או מוחקים את המשאבים של איחוד שירותי אימות הזהות של עומסי עבודה ב-Google Cloud

מאגרי זהויות של עומסי עבודה, ספקים וחשבונות שירות לא צוברים עלות בזמן חוסר פעילות כשלא מתבצעת החלפת אסימונים. בוחרים את מצב הניקוי שמתאים לתהליך העבודה:

אפשרות א' – השהיית הגישה (מומלץ אם מתכננים להריץ מחדש בפרויקט הזה): משביתה את החלפת אסימון ה-OIDC באופן מיידי, בלי להפעיל את שמירת המחיקה הרכה למשך 30 יום של Google Cloud IAM או את עיכובי ההפצה של חשבון השירות uniqueId:

gcloud iam workload-identity-pools providers update-oidc "${WORKLOAD_IDENTITY_PROVIDER}" \
 --workload-identity-pool="${WORKLOAD_IDENTITY_POOL}" \
 --location="global" \
 --disabled \
 --project="${PROJECT_ID}"

אפשרות ב' – פירוק מלא: מחיקת ספק ה-WIF, המאגר (נשמר במצב DELETED למשך 30 יום) וחשבון השירות הייעודי:

# Delete Workload Identity Provider
gcloud iam workload-identity-pools providers delete "${WORKLOAD_IDENTITY_PROVIDER}" \
 --workload-identity-pool="${WORKLOAD_IDENTITY_POOL}" \
 --location="global" \
 --project="${PROJECT_ID}" \
 --quiet

# Delete Workload Identity Pool
gcloud iam workload-identity-pools delete "${WORKLOAD_IDENTITY_POOL}" \
 --location="global" \
 --project="${PROJECT_ID}" \
 --quiet

# Delete CI/CD Service Account
gcloud iam service-accounts delete "${SERVICE_ACCOUNT_EMAIL}" \
 --project="${PROJECT_ID}" \
 --quiet

12. מזל טוב

מעולה! סיימתם את ה-Codelab בנושא אבטחת צינור עיבוד הנתונים של CI/CD באמצעות CodeMender.

זהו! תכננתם, יצרתם והפעלתם באופן אוטומטי צינור עיבוד נתונים של DevSecOps ברמת ייצור, עם אבטחה בגישת "אפס אמון", באמצעות איחוד שירותי אימות הזהות של עומסי עבודה ב-Google Cloud,‏ CodeMender ו-GitHub Actions.

מה למדתם

אימות ללא מפתחות בגישת Zero-Trust: ביטלנו את המפתחות הפרטיים המסוכנים לטווח ארוך של חשבונות שירות בפורמט JSON, על ידי קישור של אסימוני OIDC זמניים של GitHub ל-Google Cloud IAM באמצעות איחוד שירותי אימות הזהות של עומסי עבודה (WIF).

סריקת AST דיפרנציאלית של בקשות משיכה (PR) וסינון רעשים מדור קודם: סריקה רציפה של קבצים שהשתנו וקבצים תלויים (--diff="origin/$BASE_REF"), תוך בידוד של חוב טכני מדור קודם ([LEGACY / UNTOUCHED]) כדי לשמור על לולאות משוב של מפתחים מתחת ל-15 שניות.

דוחות בפורמטים שונים וסיכומי משימות מותאמים: שילוב של OASIS SARIF v2.1.0 לסריקת קוד מרוכזת ב-GitHub עם Markdown מותאם (cm report -f md >> $GITHUB_STEP_SUMMARY) כדי לאפשר למנהלים לראות את הנתונים באופן מיידי ישירות בדפי ההרצה של תהליך העבודה ב-CI.

תיקון אוטונומי עם בדיקה של האדם שבתהליך: עברנו מהתראות פסיביות לצינורות עיבוד נתונים פעילים לתיקון, שיוצרים באופן אוטונומי תיקוני קוד מוצעים, מאמתים אותם מול חבילות מקרים לבדיקת רגרסיה ופותחים בקשות משיכה לבדיקה עם פריטי ביקורת לאישור של מהנדס.

שערי איכות אוטומטיים: אכיפה של הגנה קפדנית על ענפים ושערי מיזוג (--fail-on) כדי למנוע מפרצות אבטחה מסוכנות להגיע לסביבת הייצור.

העברת מצב מבוססת-ארטיפקטים ובידוד סביבת העבודה: העברת ממצאים בצורה חלקה בין משימות CI באמצעות cm report import, תוך שימוש ב-.git/info/exclude כדי לשמור על היסטוריית Git נקייה ולמנוע דליפת פרטי כניסה.

שינוי בדפוס החשיבה של המפתחים

שיטת DevSecOps מסורתית

צינור עיבוד נתונים אוטונומי של CI/CD ב-CodeMender

הצגת התראות פסיבית: סורקים מדפיסים יומני מסוף גולמיים או רשימות סטטיות של שגיאות, ומעבירים את נטל המיון כולו למפתחים.

Active Co-developer: מסנתז תיקוני קוד מאומתים ופותח בקשות משיכה (PR) שמוכנות למיזוג, כדי שהמהנדסים יוכלו לאשר אותן.

שיעור גבוה של תוצאות חיוביות מוטעות: היוריסטיקות של AST סטטי מסמנות אלפי נקודות חולשה תיאורטיות בלי הוכחה שאפשר לנצל אותן.

אימות ניצול פרצות בשני שלבים: יצירת בדיקות דינמיות בארגז חול (cm verify) מאשרת את נקודת החולשה בפועל, וכך מבטלת תוצאות חיוביות מוטעות.

אחסון סודות מסוכן: מפתחות JSON לטווח ארוך של חשבונות שירות שמאוחסנים בסודות CI עלולים לדלוף בטעות ולהוביל להתפשטות של פרטי כניסה.

‫Zero-Trust WIF: אימות ללא מפתחות באמצעות אסימוני OIDC זמניים שמוחלפים ב-Google Cloud STS לפי דרישה.

סריקות חוזרות מונוליתיות: כל קוד שמוגש מפעיל ביקורות מלאות במאגר, מה שמעכב את תהליכי העבודה של ה-CI ומבזבז טוקנים יקרים.

ניתוב AST מבוסס-אירועים: בקשות משיכה מפעילות סריקות AST דיפרנציאליות של 15 שניות (–diff), והפעלות cron מבצעות ביקורות מעמיקות.

היסטוריית מאגר מזוהמת: סקריפטים זמניים של ניצול פרצות ויומני התקפות שנוספו ישירות לענפי המאגר.

היגיינה של סביבת העבודה בארגון: הראיות למתקפה מוטמעות בצורה נקייה בתיאורים של בקשות ה-Pull ובפריטי המידע שנוצרו בתהליך העבודה, וכך נשמרת הטוהר של הגשות הקוד.

השלבים הבאים

🚀 ממשיכים בתהליך הלמידה של CodeMender:

חלק 1: אבטחת האפליקציה באמצעות CodeMender – לומדים איך לגלות באופן אוטונומי נקודות חולשה במאגר, לאמת ניצול לרעה של הוכחת היתכנות (PoC) וליצור תיקונים מקומיים.

<!--Shift Left Locally & Serverless Cloud Native CI/CD: Explore the official CI/CD guide's reference implementations for Google Cloud Build () and Local Git Pre-commit Hooks ().-->Shift Left Locally & Serverless Cloud Native CI/CD: במדריך הרשמי של CI/CD תוכלו למצוא הטמעות לדוגמה של Google Cloud Build (cloudbuild.yaml) ושל Local Git Pre-commit Hooks (cm find . --diff --staged).

📖 עיון במסמכי התיעוד ובמקורות המידע:

המדריך הרשמי לשילוב של Google Cloud CodeMender ב-CI/CD

המסמכים הרשמיים של Google Cloud CodeMender

מאגר תבניות התחלתיות של פעולות GitHub ב-CodeMender

מסמכי התיעוד של איחוד שירותי אימות הזהות של עומסי עבודה ב-Google Cloud

💡 החלת השינויים על המאגרים שלכם:

אתם יכולים ליצור עותק של תהליך העבודה הראשוני ולאבטח את המאגרים של הארגון ב-Python,‏ Go,‏ Java,‏ Rust ו-Node.js באמצעות CodeMender.