איתור באגים במערך האקולוגי של Python עם קלוד ובדיקות מבוססות מאפיינים
מוחמד מאאז (Muhammad Maaz)1,2, ליאם דה-ווי (Liam DeVoe)3, זאק הטפילד-דודס (Zac Hatfield-Dodds)2, ניקולס קרליני (Nicholas Carlini)2
1MATS, 2אנתרופיק (Anthropic), 3אוניברסיטת נורת'איסטרן (Northeastern University)
פיתחנו סוכן AI המסוגל לזהות ביעילות באגים בפרויקטים גדולים של תוכנה. לשם כך, הסוכן שלנו מסיק מאפיינים כלליים שאמורים להיות נכונים לגבי הקוד, ולאחר מכן, באמצעות יישום בדיקות מבוססות מאפיינים – טכניקה הדומה ל-fuzz testing – אנחנו מצליחים לגלות באגים בחבילות Python מובילות כמו NumPy, SciPy ו-Pandas. לאחר אימות ידני מקיף, אנו מדווחים על באגים אלו למפתחים, כשחלקם כבר תוקנו.
למידע נוסף, קראו את המאמר המלא, עיינו במאגר ה-GitHub, או דפדפו בבאגים שמצאנו באתר שלנו.
מבוא
הבטחת קוד נקי מבאגים היא אחד ההיבטים המאתגרים ביותר בהנדסת תוכנה. באגים נוטים להמשיך להסתתר בקוד למרות מאמציהם הרבים של המפתחים. הגישה הנפוצה ביותר לבדיקת קוד היא באמצעות בדיקות מבוססות דוגמאות: המפתח כותב מקרה שימוש ספציפי, ולאחר מכן מאמת שהפלט בפועל תואם את הפלט הצפוי. לדוגמה, מפתח עשוי לוודא שפונקציית מיון המופעלת על הרשימה [2, 10, 5, 4] תחזיר את הפלט [2, 4, 5, 10]. עם זאת, כיסוי ממצה של תוכנית באמצעות בדיקות כאלה הוא מאתגר: לעיתים קרובות נשארים באגים במקרי קצה שהמפתח לא בדק. אחרי הכל, אם מפתח לא חושב לבדוק מקרה קצה, סביר להניח שהמפתח גם לא התחשב במקרה זה ביישום!
לעומת זאת, בדיקות מבוססות מאפיינים הן פרדיגמת בדיקות תוכנה שמטרתה לבדוק אם מאפיין כללי של הקוד תקף עבור כל (או רוב) הקלטים. מפתח מציין מאפיין או אינווריאנט לגבי התוכנית – למשל, שביטול סריאליזציה של JSON הוא ההופכי של סריאליזציה – וכן תיאור של סוגי הקלטים שהמאפיין מקבל (לדוגמה, כל אובייטים הניתנים לסריאליזציה ל-JSON). מסגרת הבדיקות מבוססות המאפיינים מחפשת באופן אוטומטי דוגמה נגדית למאפיין זה על ידי יצירת קלטים תקפים כמקרי בדיקה, תוך שימוש בטכניקות הדומות ל-fuzzing. מכיוון שהמפתח מציין את תחום הקלט הכללי, ולא מקרי בדיקה בודדים, בדיקות מבוססות מאפיינים משחררות מפתחים מהצורך לחשוב על כל מקרה קצה ומאפשרות להם לפעול ברמת הפשטה גבוהה יותר.
במאמר שלנו שהוצג בסדנת 'למידה עמוקה לקוד' (Deep Learning for Code) בכנס NeurIPS 2025 – שהיה תוצר של פרויקט MATS – פיתחנו סוכן AI שכותב באופן אוטונומי בדיקות מבוססות מאפיינים עבור קוד קיים. כיוונו את הסוכן לגלות מאפיינים על ידי קריאת אנוטציות טיפוסים, מחרוזות תיעוד (docstrings), שמות פונקציות והערות. לאחר מכן, הסוכן כתב בדיקות מבוססות מאפיינים תואמות באמצעות Hypothesis.
בעבודה זו, התמקדנו בבעיית זיהוי באגים באופן כללי, ולא רק בחולשות אבטחה. סוגים רבים של באגים לוגיים הגורמים לחולשות אבטחה ניתנים לבדיקה באמצעות בדיקות מבוססות מאפיינים. לדוגמה, בפוסט בבלוג שפרסמנו לאחרונה, התמקדנו בזיהוי באגים בחוזים חכמים; כמעט כל החולשות הללו הן תוצאה של באגים לוגיים. אנו מדמיינים כי בעתיד ניתן יהיה ליישם טכניקות כמו זו שאנו מתארים כאן כדי לזהות באגים באופן יזום לפני הפריסה.
השתמשנו בסוכן שלנו וגילינו מאות באגים פוטנציאליים במאגרי קוד פתוח פופולריים ב-Python, כמו NumPy, SciPy ו-Pandas. כדי לדווח על באגים אלה באופן אחראי ולוודא שאיננו מכבידים על המתחזקים שלא לצורך, סקרנו בקפדנות כל באג.
תהליך הסקירה שבו השתמשנו היה מפרך יותר ממה שהיינו מיישמים בדרך כלל עבור סקירות קוד משלנו, אך העדפנו מאוד להפחית את מספר התראות השווא. התהליך שלנו היה כדלקמן: ראשית, בחרנו רק את הבאגים בעדיפות הגבוהה ביותר לסקירה. שלחנו את הבאגים הפוטנציאליים הללו לסקירה על ידי שלושה מומחים אנושיים (בממוצע שעת סקירה אחת לכל באג). לאחר מכן, השלכנו כל באג שאף אחד משלושת הסוקרים הידניים לא היה בטוח בתקפותו. לבסוף, אנו (מחברי הבלוג הזה) סקרנו ידנית כל אחד מהבאגים המועמדים. רק אם היינו בטוחים בנכונותו, רק אז הגשנו ידנית דיווח למתחזק המאגר. כבר הגשנו כמה מדווחי הבאגים הללו, ואנחנו בתהליך של הגשת רבים נוספים.
הנגשנו את כל הנתונים שלנו, כולל באגים שטרם אומתו, ואף באגים שקבענו כלא תקפים, כך שמתחזקים יוכלו לעיין בהם באתר זה. בשבועות הקרובים אנו מתכוונים לדווח על רבים מהבאגים הנותרים (לאחר אימות נוסף), וכן להרחיב את הפרויקט שלנו לפרויקטי PyPI נוספים.
# example-based test
def test_sort():
assert my_sort([1,3,2]) == [1,2,3]
assert my_sort([1,0,-5]) == [-5,0,1]
# property-based test in Hypothesis
from hypothesis import given, strategies as st
@given(st.lists(st.integers()))
def test_sort(lst):
result = my_sort(lst)
for i in range(len(result)-1):
assert result[i] <= result[i+1]
איור 1. שתי דרכים לבדיקת קוד. בדיקת יחידה מבוססת דוגמאות מאמתת קלטים ספציפיים שהוזנו ידנית. בדיקה מבוססת מאפיינים, לעומת זאת, מציינת מאפיין כללי (לדוגמה, הגדרת רשימה ממוינת) ונסמכת על המסגרת לבנות באופן אוטומטי קלטים שעלולים להכשיל מאפיין זה.
סוכן הבדיקות מבוססות המאפיינים שלנו
סוכן הבדיקות מבוססות המאפיינים שלנו בנוי כפקודה ייעודית ב-Claude Code. הסוכן מקבל ארגומנט יחיד, המפנה אותו ליעד מסוים: קובץ Python בודד (לדוגמה, normalizers.py), מודול (לדוגמה, numpy, scipy.signal), או פונקציה (לדוגמה, requests.get, json.loads). הסוכן פועל לפי התהליך הבא כדי לזהות באגים פוטנציאליים:
- קריאה והבנת היעד, על ידי קריאת קוד, שליפת תיעוד רלוונטי ובחינת הקשר שלו לשאר בסיס הקוד.
- הצעת מאפיינים המבוססים על ממצאים אלה.
- כתיבת בדיקות מבוססות מאפיינים תואמות ב-Hypothesis.
- הרצת הבדיקות ורפלקציה: אם הבדיקה נכשלה, האם היא אכן גילתה באג, או שיש צורך להתאים את הבדיקה? אם היא הצליחה, האם הבדיקה בודקת משהו בעל ערך, או שהיא פשוט טריוויאלית?
- אם הסוכן בטוח שמצא באג אמיתי, הוא כותב דו"ח באג בפורמט מוגדר.

כדי לסייע לסוכן לבצע חשיבה מרובת שלבים לטווח ארוך, אנחנו מכוונים אותו להשתמש ברשימת משימות כדי לעקוב אחר התקדמותו.
אחת העדיפויות בעיצוב הסוכן הייתה הפחתת מספר התראות השווא – מניסיוננו האישי, כלי פיתוח יעילים ממזערים את כמות הדיווחים השגויים המוצגים למפתח. לולאת הרפלקציה העצמית מסייעת להפחית את מספר התראות השווא, וכך גם ביסוס מאפיינים על שימוש ותיעוד מפורשים של היעד. לדוגמה, באחת מהרצות הסוכן, הסוכן כתב מאפיין שעבר תחילה בהצלחה. עם זאת, לאחר רפלקציה עצמית, הסוכן הבין שעטף את כל הבדיקה בבלוק try-catch. לאחר הסרתו, הבדיקה נכשלה, והסוכן מצא באג. כמו כן, הבחנו בשיפור ניכר ברפלקציה העצמית עם מודלי Opus 4.1 ו-Sonnet 4.5, בהשוואה ל-Sonnet 4.
דוגמת הפעלה
כדי להדגים כיצד הסוכן עובד על בדיקת יעד, אנו מציגים תמליל מתומצת שבו קלוד מזהה באג ביישום של numpy.random.wald. הסוכן מתחיל בחקירת הפונקציה, החתימה שלה, מחרוזת התיעוד שלה (docstring) ואף בדיקות קיימות:
יש לציין כי התיקון שהוצע על ידי הסוכן אינו נכון; כשתיקנו באג זה, איתרנו את מקור השגיאה לחישוב לא יציב מבחינה נומרית; ראו את התיקון שמוזג כאן.
חיפוש באגים בחבילות PyPI אמיתיות
כדי לבחון את יכולות הסוכן שלנו בעולם האמיתי, אצרנו סט מגוון של למעלה מ-100 חבילות Python פופולריות. ספריות אלו משתרעות על פני מגוון רחב של תחומים, מחישוב נומרי ועד ניתוח נתונים ומסדי נתונים. הפעלנו את הסוכן שלנו על כל אחת מהחבילות הללו, ואספנו את כל דיווחי הבאגים שנוצרו.
הערכת הסוכן
בשלב הראשון של הערכתנו, המכוסה במאמר שלנו, הרצנו את הסוכן עם Claude Opus 4.1 על כל חבילה ואספנו את כל דיווחי הבאגים שנוצרו. כדי להעריך את דיווחי הבאגים הללו, קבענו שני קריטריונים: ראשית, "האם זהו באג תקף?", ושנית, "האם זהו באג תקף וגם משהו שהיינו מדווחים עליו באופן סביר למתחזקי הספרייה?". הקריטריון השני מחמיר יותר מהראשון, שכן, למשל, באג יכול להיות תקף, אך קל ערך מכדי להגיש עליו דו"ח.
מתוך 984 דיווחי באגים, בחרנו ידנית 50 לסקירה. מצאנו כי 56% מהדיווחים הללו היו באגים תקפים, ו-32% היו באגים תקפים שגם היינו מדווחים עליהם.
בהתבסס על סקירה ידנית זו, פיתחנו קריטריוני דירוג המדרגים באגים בסולם של עד 15 נקודות, במטרה להעלות באגים שסביר להניח שהם תקפים וששווה לתקן אותם עבור המפתח. השתמשנו ב-Opus 4.1 כדי לדרג את כל דיווחי הבאגים בהתאם לקריטריונים אלו. מצאנו ששלב הדירוג הזה היה יעיל למדי: מתוך דיווחי הבאגים בעלי הניקוד הגבוה ביותר, 86% היו תקפים, ו-81% היו גם תקפים וגם ראויים לדיווח.
בשלב השני של הערכתנו, הרצנו את הסוכן עם Sonnet 4.5 על תת-קבוצה של 10 חבילות חשובות, והפעלנו אותו על כל חבילה מספר פעמים. כמו כן, פיתחנו סוכן הערכה שהשתמש ב-Sonnet 4.5 כדי לקרוא את הקוד ואת דיווח הבאג, כדי לבדוק את נכונותו וחומרתו של הבאג, והוא היה מתוחכם יותר מקריטריונים הדירוג מהשלב הראשון. לבסוף, שילמנו לשלושה מומחים אנושיים כדי שיעריכו באגים בעלי חומרה גבוהה מבחינת נכונותם.
כדי לקרוא את כל דיווחי הבאגים שסוכן ה-AI שלנו מצא, ראו: https://mmaaz-git.github.io/agentic-pbt-site/.
אימות על ידי מתחזקים
הערכת יעילותו של כל כלי המגלה באגים בקוד היא קשה. בעוד שאנו עושים כמיטב יכולתנו לאמת את נכונותם של דיווחי באגים, מתחזקי החבילות משמשים כבורר האמת האולטימטיבי. כדי לוודא שסוכן ה-AI שלנו מוצא באגים שמתחזקים רואים בהם תקפים וראויים לתיקון, בחרנו חמישה באגים מעניינים במיוחד ודיווחנו עליהם ידנית למאגרי ה-GitHub המתאימים, יחד עם תיקון מוצע. בשבועות הקרובים, אנו מתכוונים להמשיך לדווח על באגים נוספים ככל שנאמת אותם.
NumPy
numpy.random.wald מחזירה לפעמים מספרים שליליים, וזהו באג מכיוון שדגימות מהתפלגות וולד אמורות להחזיר רק מספרים חיוביים. זהו הבאג שהוצג בהדגמה שלנו למעלה. קלוד ידע זאת כמאפיין של התפלגות וולד וכתב בדיקת PBT פשוטה כדי לבדוק אם כל הדגימות שנוצרו הן חיוביות. איתרנו את השגיאה לביטול קטסטרופלי המתרחש בקוד, ופיתחנו נוסחה יציבה יותר מבחינה נומרית כאשר הגשנו את בקשת המשיכה. כפי שהוצג על ידי מתחזקי NumPy בבקשת המשיכה, לניסוח החדש שלנו יש שגיאה יחסית נמוכה בעשר סדרי גודל מהאלגוריתם הקודם.
תיקון שמוזג: https://github.com/numpy/numpy/pull/29609
aws-lambda-powertools
slice_dictionary() מחזירה את הבלוק הראשון שוב ושוב, עקב אי-קידום האיטרטור. זה נתפס על ידי הסוכן שלנו כאשר זיהה שחיתוך ולאחר מכן בנייה מחדש של המילון אמורים להחזיר את המילון המקורי.
תיקון שמוזג: https://github.com/aws-powertools/powertools-lambda-python/pull/7246
cloudformation-cli-java-plugin
item_hash() מפיקה את אותו ערך של hash(None) עבור כל הרשימות, עקב שימוש בשיטת המיון במקום (.sort()), שמחזירה None. הסוכן תפס זאת על ידי בדיקה שגיבובים של קלטים שונים אמורים להיות שונים.
תיקון שהוגש: https://github.com/aws-cloudformation/cloudformation-cli/pull/1106
tokenizers
EncodingVisualizer.calculate_label_colors() חסרה סוגר סוגר סוגר סוגר, ומחזירה CSS HSL לא תקף. הסוכן שלנו זיהה זאת על ידי בדיקה שהפלט אמור להתאים לביטוי רגולרי של קוד צבע HSL.
תיקון שמוזג: https://github.com/huggingface/tokenizers/pull/1853
python-dateutil
easter() מחזירה תאריך שאינו יום ראשון עבור שנים מסוימות בעת שימוש בלוח השנה היוליאני. המתחזקים זיהו את ההתנהגות כמתוכננת בשל מערכות לוח שנה שונות, והכירו בכך שהסמנטיקה עדינה.
הבעיה לא תקפה: https://github.com/dateutil/dateutil/issues/1437
הדיווח ל-python-dateutil מראה מגבלה חשובה של הסוכן: גזירת מאפיינים מקוד עם סמנטיקה עדינה או מורכבת נשארת קשה. אם הקוד מניח הנחה מרומזת, רק מתחזקי הספרייה יכולים להחליט מהו המאפיין הנכון לבדיקה.
מסקנה
ככל שמודלי שפה ממשיכים להשתפר, אנו חושבים שבדיקות מבוססות מאפיינים סוכניות יכולות להפוך למשלים בעל ערך הולך וגובר לבדיקות הנכתבות על ידי בני אדם. ההבטחות הסמנטיות ברמה הגבוהה של בדיקות מבוססות מאפיינים הופכות אותן להתאמה טבעית לשילוב במהלך הפיתוח. אנו מוצאים ש-LLM מצוינים במיוחד בזיהוי מאפיינים שאמורים להיות נכונים לגבי קטע קוד נתון מההקשר שלו (שם הפונקציה, מחרוזת התיעוד, איך היא נקראת על ידי פונקציות אחרות וכו'). זה מאפשר ל-LLM לכתוב בדיקות מבוססות מאפיינים באיכות גבוהה ביעילות.
בהמשך הדרך, אנו מאמינים שיישום LLM לבדיקות ואיתור באגים הוא כיוון מחקר חשוב. במיוחד ככל ש-LLM משתפרים בתהליך ניצול חולשות, יש צורך להקדים תוקפים המשתמשים ב-LLM לניצול חולשות.
בעבודה זו איננו מתמקדים ביצירה אוטומטית של תיקונים, אך זהו כיוון ברור לעבודה עתידית. אם ניתן (כמעט) לציין באופן מלא את מאפייני הנכונות של קטע קוד, אזי תיקון הבאג הופך קל משמעותית, ואנו מאמינים כי בעתיד הקרוב LLM יוכלו להציע באופן יעיל תיקונים באיכות גבוהה שראויים להתייחסות המתחזקים.



