איור מופשט שנוצר על שדה צפחה כהה: רצועה אופקית ארוכה של קווי אור דקים בצבעי ציאן חיוור וענבר נמתחת מקצה לקצה, נקטעת בנקודה מדויקת אחת סמוך למרכז, ורסיס ענבר בהיר יחיד נמלט כלפי מעלה אל תוך ערוץ כהה וריק שמעל; מעגלים קונצנטריים קלושים וקווי רשת משורטים מרמזים על צינור. לא מופיעים טקסט, אנשים או לוגואים של ארגונים. הלוגו של OrcaRouter משולב בפינה הימנית התחתונה.
AI Safety Incidents

הטוקן של Jira של Snowflake: ליקוי ש-Copilot חתם עליו יחד, והאדם ש-GitHub אומר שכתב אותו

מחבר

Gideon Frost

תאריך פרסום

מודלים אחרונים · 20צפו בכל המודלים →
בנצ'מרקים: Artificial Analysis · מתעדכן יומית
חזרה לכל הפוסטים

ב-23 ביוני 2026 פתח Red Agent, סוכן אבטחה אוטונומי שנבנה על ידי Wiz, issue במאגר GitHub ציבורי בבעלות Snowflake וחזר עם אישור גישה. המאגר היה snowflakedb/snowflake-connector-net, וה-workflow האחראי, .github/workflows/jira_issue.yml, נועד לפתוח כרטיס Jira בכל פעם שמישהו פותח issue — הוא שילב את כותרת הכרטיס בתוך פקודת shell במקום להעביר אותה דרך משתנה סביבה, כך שכותרת זדונית הורצה כקוד על ה-runner של GitHub Actions. הטוקן ש-Red Agent שחזר הזדהה כ-qa@snowflake.net מול snowflakecomputing.atlassian.net והעניק הרשאת קריאה לפרויקטי Jira של Snowflake בתחומי ההנדסה, ציות אבטחתי ו-bug bounty. הפגם היה פעיל במשך חמישה ימים. Wiz פרסמה את הניתוח המלא ב-17 באוגוסט 2026. אירוע זה מתועד כרשומה 2026-08-17-snowflake-jira-zhao-dao-can בOrca AI Incident Archive, שמכיל את מערך הרשומות המלא עם דירוגי האמינות שלו והמקורות המצוטטים בו.

האינטרפולציה, והשומר שמעולם לא רץ

זרימת העבודה הופעלה באירוע GitHub "issues: opened". כל מי שיש לו חשבון GitHub יכול היה להפעיל אותה על ידי פתיחת issue במאגר ציבורי — ללא הזמנה, ללא תפקיד maintainer וללא fork. השלב הפגיע קרא את כותרת ה-issue אל תוך משתנה shell: TITLE=$(echo '${{ github.event.issue.title }}' | sed ...), עם שני מסננים שהיו אמורים לבצע escaping של מרכאות כפולות ומרכאות בודדות לפני הרכבת המחרוזת.

הכשל הוא בסדר הפעולות, ולא במילוט. GitHub מכניס את תוכן הביטוי לטקסט הסקריפט לפני ש-bash בכלל מפרש אותו, כך שגרש בודד בתוך כותרת ה-issue סוגר את המחרוזת המצוטטת ש-echo מחזיק פתוחה. שני מסנני ה-sed פועלים בתוך אותו סקריפט, לאחר ההחלפה, ואינם יכולים לתקן ציטוט שכבר שינה את אופן פירוש השורה. התיעוד של Wiz מפורש שהמילוט מגיע מאוחר מדי כדי למנוע את הפריצה, ושכותרת שנבנתה עם גרש סוגר ונקודה-פסיק מוסיפה פקודות לבחירת התוקף לשלב ההרצה.

אמצעי בקרה שני היה אמור לצמצם את קהל היעד, אך הוא לא עשה זאת. ה-job הכיל תנאי if שהשווה את github.event.pull_request.user.login לשם הכניסה של הבוט whitesource-for-github-com, ככל הנראה כדי למנוע מבקשות pull request אוטומטיות של תלות לפתוח כרטיסים. באירוע issues אין אובייקט pull request כלל, ולכן ההשוואה נעשית מול מאפיין null. התיעוד של GitHub עצמו, כפי שצוטט ב-The Hacker News, קובע כי הפניה למאפיין שאינו קיים מחזירה מחרוזת ריקה; הניתוח של Wiz מגיע לאותה תוצאה באמצעות ערך ה-null. כך או כך, התנאי הוערך כ-true עבור כל משתמש, והחריג עבור הבוט הפך למעבר פתוח לאינטרנט.

מה שהפך את ההזרקה לראויה לדיווח ולא לשגרתית הוא ההקשר שבו הופיעה. אותו שלב הכיל את JIRA_BASE_URL, JIRA_USER_EMAIL ו-JIRA_API_TOKEN כמשתני סביבה, כך שלהרצת פקודה שרירותית על ה-runner היה פרט גישה בהישג יד ולא מצע ריק. לא זוהתה אף גרסה של Snowflake Connector for .NET כמושפעת: החולשה שכנה באוטומציית ה-CI/CD של המאגר, ולא בקוד הקונקטור המסופק.

מה Red Agent לקח, ומה שהוא אומר שהשליך

התיאור של Wiz את הניצול הוא מה שמבדיל את המקרה הזה מממצא של סורק. ה-payload הראשון השתמש בתו hash, שהפך להערה את סוגר הסוגריים הסוגר של ההשמה TITLE=$(...) ויצר שגיאת תחביר ב-bash במקום callback. הסוכן קרא את השגיאה ושכתב את ה-payload כך שיסגור את בלוק ה-shell באמצעות נקודה-פסיק ומרכאה חדשה של echo, ואז קיבל קריאה מחוץ לערוץ. ה-payload השתמש ב-curl כדי להגיע לתת-דומיין של oast.me עם ערכים מקודדים ב-base64 של שלושת משתני האישורים, וה-callback הגיע מ-IP של Azure 20.106.182.197, כתובת ש-Wiz מייחסת ל-GitHub Actions runner.

האסימון שהוא החזיר היה אסימון API של Jira עבור qa@snowflake.net, ו-Wiz מתארת את היקף הגישה שלו כגישת קריאה המקיפה פרויקטים של הנדסה, ציות אבטחתי ומעקב באגי באג-באונטי במופע הענן של Atlassian של Snowflake. זהו הנזק שהארכיון מתעד: לא הרצת קוד על מכונת build במשך חמישה ימים, אלא אישור גישה שיכול היה לקרוא את תורי הטיקטים שבהם מדווחים באגים הנדסיים ואבטחתיים שלא תוקנו — כולל, לפי תיאורה של Wiz, את מעקב הבאג-באונטי.

A self-built HTML card titled 'What the run step could reach', badged 'snowflakedb/snowflake-connector-net · .github/workflows/jira_issue.yml · 18-23 June 2026'. A left panel lists the environment variables held by the step: JIRA_BASE_URL, JIRA_USER_EMAIL, JIRA_API_TOKEN. A right panel reads: identity qa@snowflake.net; Jira host snowflakecomputing.atlassian.net; access, read across engineering, security-compliance and bug-bounty Jira projects. Three tiles read: trigger 'issues: opened'; account required 'any GitHub user'; token rotated '24 June 2026'. A footer cites Wiz Research, published 17 August 2026, and notes no CVE identifier accompanies the flaw.

Wiz אומרת שהיא מחקה באופן מאובטח את כל מה שאליו ניגשה במהלך הוכחת ההיתכנות. Snowflake, בהצהרה ל-CSO Online, אמרה שהדוח "נחקר ותוקן באופן מיידי" ושאילו "החקירה שלנו לא מצאה עדות לגישה בלתי מורשית"; הבלוג של Wiz מוסיף ש-Snowflake בחנה יומני ביקורת עבור חלון חמשת הימים ולא מצאה שימוש של צד שלישי מעבר לכתובות הבדיקה של Wiz עצמה. Snowflake לא פרסמה את היומנים הללו, ולכן הממצא לפיו אין שחקן אחר נשען על גרסתה ועל סיכום של Wiz ממנה, ולא על מסמכים שמישהו מחוץ לשתי הארגונים יכול לקרוא.

מי כתב את השורה הפגיעה

השאלה הזו הולידה את הסיפור השני והגדול יותר. PR #1218, שכותרתו "SNOW-2069227: Update jira workflows", מוזג בשיטת squash ב-18 ביוני 2026 כקומיט 4a1b8ce, וקומיט ה-squash מפרט את Copilot Autofix powered by AI בין שותפיו לכתיבה. הכותרת המקורית של Wiz נשענה בדיוק על כך, ותיארה את הפגם כנמצא בבקשת משיכה (pull request) שנעזרה ב-GitHub Copilot, והסיקור המקצועי המוקדם הלך באותו קו — הכותרת של SC Media הייתה "סוכן של Wiz מאתר פגם במאגר של Snowflake בקוד שנכתב בשיתוף עם GitHub Copilot Autofix".

עמדת GitHub, כפי שדווח על ידי The Next Web וסוכמה בפתק מחקר של Cloud Security Alliance, היא שהבדיקה הפנימית שלה מצאה ש"אדם כתב את התרומות שהובילו לפגיעות" וש-Copilot Autofix "לא סקר אותן ולא תרם להן". הבסיס הטכני להפרכה הזו נמצא בהיסטוריית ה-git. מיזוג Squash מקפל בקשת משיכה לקומיט יחיד ומעביר הלאה כל תגית co-author, ללא קשר לאילו שורות אותו מחבר נגע בהן, ולכן שורת co-author מתעדת השתתפות בבקשת המשיכה, ולא מחברות של hunk מסוים. הקומיט שבו Copilot רשום כמחבר שותף באותה בקשת משיכה, 6d0e2fa, שינה את jira_close.yml — זרימת עבודה שונה מזו של jira_issue.yml הפגיע. האינטרפולציה הלא בטוחה מיוחסת לקומיט 094038e, שתאריכו 25 באוגוסט 2025, ומיוחסת על ידי GitHub למהנדס של Snowflake, sfc-gh-hpathak; בקשת המשיכה #1218 הכניסה את התבנית הזו לענף ברירת המחדל ביוני 2026.

Wiz לא משכה את הממצא, ושינתה את המסגור ביום הפרסום. הבלוג שלה כולל עדכון שפורסם ב-19:57 UTC ב-17 באוגוסט, המתאר את Copilot כ"מחבר שותף שבדק את ה-PR המוזג ואת שינוי הקוד" ואשר "זיהה אותו כנקי מכל חשד" בלי להבחין בפגיעויות, ומודה ש"לא ברור אם שינוי הקוד היה בסיוע AI". לפי תיאור זה, הכישלון של ה-AI הוא כישלון בבדיקה, לא במחברות: ה-pull request המוזג נשא חתימה שותפת של Copilot, וההזרקה שרדה אותו. CSO Online מצטט את אמי לוטוואק, ה-CTO של Wiz, באומרו שייחוס ברור בין בני אדם ל-AI "הופך קצת יותר קשה לקביעה", ושאין די ב"להסתכל רק על מחברים שותפים של ה-PR".

A self-built HTML card titled 'Two accounts of one commit', badged 'PR #1218 · SNOW-2069227 · squash-merged 18 June 2026 as commit 4a1b8ce'. A cyan-headed left panel, 'GitHub, internal review', reads: a human wrote the contributions that led to the vulnerability; Copilot Autofix neither reviewed nor contributed to them; Copilot's co-authored commit 6d0e2fa changed jira_close.yml, not the vulnerable file; the unsafe pattern traces to commit 094038e of 25 August 2025; squash-merging carries each co-author trailer forward regardless of which lines that author touched. An amber-headed right panel, 'Wiz, blog update, 17 August 2026, 19:57 UTC', reads: Copilot was a co-author that checked the merged PR and code change; it identified it as all-clear without noticing the vulnerabilities; it is unclear whether the code-change was AI-assisted; Copilot Autofix is listed among the squash commit's co-authors; the post was revised on the evening of publication without retracting the finding. Below, an open-question strip asks whether Copilot reviewed jira_issue.yml inside PR #1218, and a dashed band lists what is not in dispute.

מה ששתי הגרסאות חולקות ראוי להפרדה ממה שנוי ביניהן במחלוקת. שתיהן מסכימות שה-commit מסוג squash נושא את חתימת השותף-מחבר של Copilot Autofix, ושזרימת העבודה הייתה ניתנת לניצול. אף אחת מהן אינה חולקת על כך ש-GitHub Advanced Security סרקה את הגרסה הסופית של בקשת המשיכה, חילצה את jira_issue.yml, ולא סימנה את ההזרקה — Wiz מדווחת על כך כהחמצה, וההפרכה של GitHub עוסקת בייחוס הכותב ולא בסריקה. מה שנותר בלתי פתור הוא אם Copilot בכלל סקר את השורות הפגיעות: Wiz אומרת שסקירה התקיימה ואישרה אותן, GitHub אומרת שלכלי לא היה כל תפקיד בהן, והלוגים שיכריעו בדבר נמצאים בידי אחת משתי החברות. התיעוד כולל את שתי הגרסאות במקום להכריע ביניהן.

חמישה ימים, ומה השתנה אחר כך

התיקון היה מהיר מרגע שהדיווח התקבל. Wiz הגישה דיווח דרך תוכנית HackerOne של Snowflake כדיווח #3819931 ב-23 ביוני, ויידעה את צוות האבטחה של Snowflake ב-Slack באותו יום; Snowflake מיזגה PR #1402, קומיט 1dc7766, שהחליף הרחבת ביטוי ישירה במשתני סביבה שהועברו ל-jq כארגומנטים. ציר הזמן של Wiz ממקם את החלפת אסימון Jira ב-24 ביוני, ו-The Hacker News מדווח על אותו פער. ההקדמה של Wiz עצמה, לעומת זאת, אומרת ש-Snowflake תיקנה את הפגיעות והחליפה את אישור הגישה "באותו יום" — סתירה בתוך המקור הראשוני שאסור לתיעוד לטשטש. התיקון הוטמע ב-23 ביוני; ההחלפה מתוארכת ל-24 ביוני בטבלה של Wiz.

החשיפה התנהלה לפי לוח הזמנים של Snowflake: Wiz מציינת מועד יעד לחשיפה ציבורית של 25 ביולי 2026, שלושים יום לאחר החלטה מ-25 ביוני לפי מדיניות התוכנית, ופרסמה את הניתוח ב-17 באוגוסט. בהודעתה ל-CSO Online אמרה Snowflake כי החברה "מעריכה את הדיווח האחראי של Wiz" ושהיא פועלת עם Wiz כדי לשתף את הלקחים עם התעשייה. לא הניתוח של Wiz ולא הדיווח של The Hacker News כוללים מזהה CVE, ציון CVSS או רשומה בקטלוג הפגיעויות הידועות כמנוצלות של CISA; הפגם היה תצורת תהליך עבודה במאגר ציבורי, לא ספרייה שמופצת, ולכן הוא מעולם לא נכנס למסד נתוני פגיעויות בדרך הרגילה.

A self-built HTML card titled 'Five days live, five weeks to publication', subtitled 'Every date below is day-precision, as reported by Wiz Research and The Hacker News'. A vertical timeline lists six entries: 25 August 2025, commit 094038e introduces the unsafe jira_issue.yml refactor, attributed by GitHub to a Snowflake engineer; 18 June 2026, PR #1218 squash-merged as 4a1b8ce and the flaw goes live on the default branch; 23 June 2026, Wiz reports via HackerOne #3819931 and Snowflake merges fix PR #1402 as 1dc7766; 24 June 2026, Jira API token rotated, the fix having landed a day earlier; 25 July 2026, public disclosure deadline under Snowflake's HackerOne policy; 17 August 2026, Wiz publishes the full analysis, blog updated at 19:57 UTC. An amber band reads 'Exposure window: five days, 18 to 23 June 2026'. A footer notes no CVE identifier, CVSS score or known-exploited entry accompanies the record.

מה שהתיעוד מבסס, ומה שהוא אינו מבסס

הארכיון מסווג זאת כממצא מחקרי ולא כאירוע פריסה, עם חומרה גבוהה, דירוג ודאות A, מעורבות AI מאומתת ונזק ממשי מתועד; תאריכו, 17 באוגוסט 2026, הוא היום שבו Wiz פרסמה, והאירוע עצמו משתרע בין 18 ל-23 ביוני. הליבה המבוססת צרה וניתנת לבדיקה: תהליך עבודה ציבורי השתיל טקסט שנשלט בידי התוקף לתוך פקודת shell, תנאי ההגנה שלו הושווה למאפיין שהוא null באותו אירוע, אסימון Jira נשמר באותו שלב, סוכן אוטונומי ניצל אותו, ו-Snowflake מיזגה תיקון והחליפה את פרטי הכניסה בתוך יום.

החלקים שהם הסקה ולא תיעוד הם אלה ששחזורים לא־פורמליים נוטים להשטיח. Copilot Autofix מתועד כמחבר־שותף של בקשת המשיכה (pull request) ואינו מתועד כמחבר השורות הפגיעות; המסגור של AI מול AI שנשא את מחזור החדשות הראשון הוסר חלקית בידי ארגון הדיווח בתוך שעות ונדחה בידי GitHub. האם הסקירה של ה־AI של בקשת המשיכה המוזגה בחנה את jira_issue.yml היא עדיין שאלה עובדתית פתוחה, ולא שאלה מוכרעת. והיקף הגישה, אף שתואר בפירוט בידי Wiz, לא נבדק באופן בלתי תלוי: לא פורסמו הרשאות Jira, ריצת תהליך עבודה או רשומת ביקורת.

דפוס התיקון הוא זה שההנחיות של GitHub עצמה המליצו עליו מאז יולי 2025 — להעביר נתוני issue לא מהימנים אל משתנה סביבה ולמסור אותם ל-jq כארגומנט, במקום להרחיב אותם בתוך בלוק run. ה-commit הממוזג של Snowflake עושה בדיוק את זה, והטיפול המתוקן נותר בענף ברירת המחדל. לכל מי שקורא את התיעוד כתקדים, הממצא העמיד נוגע לייחוס ולא להזרקה: כאשר pull request כולל כמה בני אדם וכמה סוכנים, ה-trailer של co-author לא יכול לומר לך מי כתב שורה, וגם Wiz וגם GitHub אמרו זאת בסופו של דבר במילים שונות.