הגדרת Semgrep: מדוע ניתוח קוד לא לוכד פגיעויות
תמונה טיפוסית: הגדרת Semgrep בוצעה פורמלית — הרצה בצינור הבנייה קיימת, הדוח מגיע, והתועלת כמעט אפסית. או שמופעל הכול ברצף, כולל פיקסצ'רים ודוגמאות מהתיעוד, או שיש כל כך מעט כללים שהם שותקים מול בעיות אמיתיות. הצוות מתחיל במהרה להתייחס לבדיקות כאלה כפורמליות.
השורש הראשון — סט הכללים עצמו. תצורות מוכנות לא מכירות את ההסכמות שלכם: איך אתם מתמודדים עם סודות, אילו עטיפות מעל שאילתות אתם משתמשים, ואיפה בכלל מותר קלט לא מהימן. כללי המנתח מייצרים רעש בדיוק במקום שבו ההקשר של הפרויקט לא נלקח בחשבון, והמפתח מתרגל לסגור ממצא בלי לקרוא אותו.
השורש השני — ספים וטריאז' ממצאים. אם כל הערה חוסמת את הבנייה, בתצורה מופיעים חריגים; אם שום דבר לא נחסם, מתעלמים מבדיקות הקוד. סכמה עובדת — להיכשל על ממצאים חדשים בשורות שהשתנו, ולהחזיק את החוב המצטבר בתור נפרד עם בעלים ברור.
השורש השלישי — מקום הבדיקה בתהליך. כאשר ניתוח האבטחה בצינור הבנייה מופעל רק על הענף הראשי או פעם ביום, המשוב מגיע שעות לאחר העריכה וכבר לא נקשר אליה בראשו של המחבר. ניתוח קוד סטטי לא עובד בגלל כלי חלש, אלא בגלל הרצה לשם סימון וי.
בהמשך נפרק איך זה נסגר שלב אחר שלב: הפרדת כללים לפי תחומי אחריות, ספים על שינויים, טריאז' קבוע של ממצאים ותחזוקת התצורה במצב מעודכן.
מהירות הבדיקות, רעש בדוחות, כיסוי כללים
הרצה מלאה של Semgrep על כל היסטוריית המאגר נמשכת עשרות דקות — והמפתח משלם את המחיר הזה בכל בדיקת שינויים. אנחנו מגדירים ניתוח רק על קוד שהשתנה: סורקים קבצים שנגעו בהם ותלויים, הכללים נלקחים מהמטמון, וההרצה הופכת לשלב חובה לפני מיזוג הענף. בדיקת השינויים נכנסת לכמה דקות ולא מוציאה את המהנדס מההקשר של המשימה.
רעש הוא הסיבה העיקרית לכך שצוותים מכבים את הסורק. שיעור התראות השווא יורד מתצורה, לא מ"קסם": תבניות מדויקות במקום ביטויים רחבים, ספי חומרה מפורשים לרמות חוסמות, חריגים לקוד מיוצר ולנתוני בדיקה.
בנפרד אנו מנהלים קו בסיס של ממצאים: הבנייה נכשלת רק על פגמים חדשים, והממצאים שהיו קיימים מראש עוברים לתור משימות עם אחראי.
סט כללים ציבורי מכסה תבניות טיפוסיות, אבל לא יודע על ספריות פנימיות ועטיפות גישה לנתונים שנכתבו בבית. לכן אנחנו כותבים כללים משלנו: בדיקות הרשאה חובה לפני שאילתה, פונקציות ניקוי קלט, ואיסור על בניית שאילתות מקלט משתמש. כיסוי כללי הניתוח גדל מפרופיל סטנדרטי למפה של "איזה סוג פגם ואיפה בדיוק אנחנו לוכדים".
את האפקט מודדים לפי זרם הממצאים: כמה אושרו, כמה נדחו כהתראות שווא, ואילו סוגי פגמים לא מגיעים למהדורה. הזרקות לשאילתות, דה-סריאליזציה לא בטוחה, מפתחות וטוקנים שמוטבעים בקוד מפסיקים לצוף בבדיקות חדירה — הם נחסמים בזמן המיזוג.
מצבי סריקה: צינור בנייה, הרצה מקומית, תזמון
המצבים נבדלים לא בסט הכללים, אלא בנקודת ההרצה ובנפח הקוד הנבדק. אותם כללים נותנים זמן תגובה שונה וכיסוי שונה בהתאם לשאלה אם אנחנו סורקים את כל המאגר או רק את הדלתא. להלן — במה מוגבלת כל אפשרות ובאיזה דרג היא מתאימה.
| מצב | מתי מתאים | במה מוגבל |
|---|---|---|
| סריקה מלאה של ענף בצינור הבנייה | ענפים מוגנים ובקשות מיזוג לענף הראשי | הזמן גדל עם נפח המאגר: במונורפו גדול מדובר בעשרות דקות, לכן מחזיקים אותו רק בענפים מרכזיים |
| בדיקה של קבצים שהשתנו בלבד | כל קומיט בענפי עבודה | לא רואה בעיות בקוד שלא השתנה, ודורש בסיס השוואה תקין בעת כתיבה מחדש של ההיסטוריה |
| בדיקה מקומית לפני שליחה | הוק לפני קומיט והרצה ידנית לפני שליחת שינויים | תלוי במשמעת ובגרסת הכללים במכונת המפתח: פער מול השרת ועקיפת הבדיקה |
| הרצה לפי תזמון | הרצה מלאה בלילה של הענף הראשי וענפים ארוכי־חיים | הדוח מגיע באיחור ואינו חוסם מיזוג; נדרש ערוץ מסירה וטריאז' קבוע של ממצאים |
המצבים האלה לא מתחרים זה בזה, אלא מצטברים לדרגים: תגובה מהירה מקומית, בדיקת שינויים חוסמת בצינור, והרצה מלאה קבועה לפי תזמון. המפתח מקבל משוב לפני שליחת הקוד, והתשתית מקבלת הבטחה שהכיסוי לא נסוג. מעבר בין מצבים הוא עריכת תצורה אחת, לא שכתוב כללים: הסט והספים של הממצאים נשארים משותפים.
הגדרת Semgrep: סדר העבודות מביקורת ועד מסירה
סדר העבודות נבנה כך שהניתוח יתחיל להביא תועלת לפני שהוא הופך לשלב חובה בבנייה. תחילה מיפוי והרצה במצב רך, ורק אחרי טריאז' ממצאים הכלל מועבר לחסום. אחרת הצוות מקבל מאות התראות כבר ביום הראשון ומפסיק להסתכל על הדוח בכלל.
- ביקורת כללים נוכחיים. מוציאים את מה שמחובר כעת: אילו סטים פעילים, מה באמת מופעל, מה משכפל לינטרים ומפרמטים, ואילו בדיקות מרעישות על קוד לגיטימי.
- סכמת הרצת הניתוח. מגדירים נקודות כניסה — בכל שינוי, לפי תזמון על הענף הראשי, לפני הוצאת גרסה — ומה נשמר במטמון בין הרצות, כדי שהטריאז' לא יאריך את הבנייה.
- התאמה לפרויקט. מכבים בדיקות רועשות, מעלים ספי חשיבות, וכותבים חלק מהכללים לפי ההסכמות הפנימיות: עבודה עם סודות, ניתוח נתונים נכנסים, פנייה לשירותים חיצוניים.
- בדיקה על היסטוריית השינויים. מריצים את התצורה על עריכות קודמות, לא רק על קוד טרי: כך רואים את הנפח האמיתי של הממצאים ואילו כללים מייצרים התראות שווא על בסיס הקוד שלכם.
- מצב אזהרות במקום חסימה. ההרצות הראשונות לא עוצרות דבר: הדוח נאסף, הממצאים עוברים טריאז', ומונה התראות השווא יורד. החסימה מופעלת כאשר שיעור הממצאים המהימנים מצדיק זאת.
- נוהל טריאז'. מסדירים מי ומתי בוחן את הדוח, איך מסומנת התראת שווא ואיך כלל נכנס לחריגים — עם נימוק, לא בשקט.
- מסירה. הכללים נמצאים במאגר לצד הקוד, סכמת ההרצה מתועדת, ולצוות יש סדר עריכה ונקודת כניסה ברורה.
ארטיפקטים: תצורות כללים, סכמות, נוהל טריאז' ממצאים
לאחר סיום העבודות נשארת במאגר לא הגדרה חד־פעמית, אלא מעגל ניתוח עובד, שצוות הלקוח מפתח בלעדינו. כל הארטיפקטים מנוהלים בגרסאות יחד עם הקוד ועוברים סקירה כמו שינויים רגילים — כך רואים מי ערך את הבדיקות ולמה.
- סטים של כללים עצמאיים עבור הסטאק שלנו, מחולקים לפי שפות ותחומי אחריות: חובה למיזוג ואינפורמטיביים. כל כלל מגיע עם דוגמה של "הופעל — מה לעשות" ובדיקה על סט בדיקות.
- מדיניות חריגים והשתקות: היכן שמים השתקה (בקוד או בתצורה), מי מאשר, חובה לציין סיבה, בעלים ותוחלת חיים. חריגים בלי בעלים נכנסים לדוח נפרד.
- נוהל טריאז' ממצאים: אילו רמות חומרה חוסמות מיזוג, אילו עוברות לתור, מי מקבל החלטה "לתקן / להשתק / לקבל סיכון" ואיך מתעדים את הנימוק.
- תיעוד להרצת בדיקות: הרצה מקומית לפני קומיט, דוח לפי ענף, שחזור של הפעלה, ומשך ההרצה המלאה.
- תצורת הטמעה בבנייה: שלבים, מטמון תלויות, משימות מקבילות, ומצב כשל על ממצאים חדשים.
- תצלום בסיס של הממצאים הנוכחיים — הפעלת הבדיקות לא חוסמת את עבודת הצוות כבר ביום הראשון.
- מדדי המעגל: שיעור הממצאים שנבדקו, מספר התראות השווא לכל כלל, ומגמה לפי חומרה.
את הסט מוסרים עם הדרכה קצרה: מהנדסי הלקוח מריצים אותו בעצמם, ואנחנו נשארים זמינים לפיתוח כללים.
מקרה בוחן: שיעור התראות השווא וזמן הבדיקה לפני ואחרי
נקודת התחלה
הפרויקט — מונורפו עם כעשרה שירותים וצינור משותף, ואת ניתוח הקוד הפעילו על כללי ברירת מחדל. אחרי כל שינוי הדוח הביא מאות הערות, שמהן אושרו בודדות: שיעור התראות השווא עמד על 71%.
טריאז' הדוח לפני מיזוג ארך בממוצע 45 דקות, מהנדסים התחילו לדלג על בדיקות ולהסתכל רק על סטטוס הבנייה — ההגנה עבדה פורמלית, אבל לא לכדה דבר.
מה שינינו
Semgrep הוגדר לפי מבנה המאגר, ולא להפך. את הכללים פיצלו לסטים: קריטיים (דליפות סודות, הזרקות, דה-סריאליזציה לא בטוחה) חוסמים מיזוג, והשאר עוברים לדוח בלי לעצור את הצינור. כללים מותאמים תיארו עטיפות פנימיות לגישה לנתונים, ואת ספריות הבדיקה והקוד המיוצר הוציאו לחריגים. הוסיפו השוואה לענף הבסיס — נבדקות רק השורות שהשתנו, לא הקובץ כולו.
תוצאה
שיעור התראות השווא ירד מ-71% ל-9%, ואת הדוח שוב התחילו לקרוא במלואו, לא באופן סלקטיבי. זמן בדיקת השינויים הצטמצם מ-45 דקות ל-7, ובכל זאת אף ממצא קריטי לא אבד: לוכדים אותם בשלב הבדיקה, לא בפרודקשן. לאחר כמה שבועות הצוות הפסיק להתווכח על רעש והתחיל לפתח כללים — סט חדש לשירות מתווסף במעבר אחד.
במה כללים מובנים נבדלים מכללים עצמאיים ומתי נדרשים שניהם
סט מוכן של Semgrep מכסה סוגי פגיעויות טיפוסיים: הזרקות, הצפנה חלשה, סודות במאגר, וקריאות מסוכנות לספריות פופולריות. ממצאים מופיעים כבר בהרצה הראשונה — הכללים נשענים על חתימות כלליות של השפה, לא על מבנה הקוד שלכם.
כללים עצמאיים לפרויקט מתארים את ייחוד הארכיטקטורה: קריאה חובה לעטיפה במקום שאילתה ישירה למסד, בדיקת הרשאה במטפל, ואיסור על מודול פנימי עם חולשה ידועה. הם קשורים לשמות הישויות שלכם, ולכן פרויקט זר לא יאמץ אותם.
| סט | מתי מתאים | מגבלות |
|---|---|---|
| מובנה | הרצה ראשונה, תלויות חיצוניות, שגיאות טיפוסיות | לא רואה הסכמות פנימיות, מרעיש על מבנים בטוחים עבורכם |
| עצמאי | שכבת גישה לנתונים משלכם, בדיקות הרשאה חובה | דורש תחזוקה: לאחר ריפקטורינג יש לבדוק מחדש את התבניות |
| שניהם יחד | מוצר עם ארכיטקטורה משלו ותלויות חיצוניות | נדרשת תעדוף, אחרת זרם הממצאים מתערבב והטריאז' מתארך |
שילוב הסטים נותן תמונה מלאה: המובנה מכסה את המעגל החיצוני, והעצמאי — את ההסכמות הפנימיות של הצוות. התעדוף נעשה לפי מקור הממצא: הפעלה של כלל משלכם כמעט תמיד מעידה על הפרה של הסכמת הקוד שלכם, בעוד שאזהרה של הכלל המובנה דורשת לרוב בדיקת הקשר.
הגבול עובר בשאלה פשוטה: האם הכלל היה מופעל בפרויקט זר באותה שפה? אם כן — זה סט מובנה; אם הוא נשען על המודולים שלכם — עצמאי. שניהם יחד מכסים גם את הרקע הכללי וגם את הייחוד של ארכיטקטורת הפרויקט.
מגבלות ושאלות נפוצות לפני הטמעה
ניתוח קוד בשלב הבנייה לא מחליף בדיקות דינמיות ובדיקה ידנית: הוא רואה את זרימת הנתונים בתוך קבצים ומודולים, אבל חסר אונים מול הרשאות גישה, תצורת סביבה ולוגיקה שמתגלה רק תחת עומס. לכן אנחנו מטמיעים את הבדיקות כאחד השכבות — לצד בקרת תלויות ואיתור סודות. להלן — הספקות שצוות הלקוח מעלה לרוב לפני תחילת העבודות.
נושא נפרד — תחזוקה. כללים משלכם ב-Semgrep חיים כמו קוד: יש להם בעלים, בדיקות על דוגמאות הפעלה, והרצה בעת עדכון המנוע. בלי זה, בעוד כמה חודשים הסט הופך למזבלה שמכבים אותה בשלמותה — יחד עם הבדיקות המועילות.
התראות שווא משתקות את עבודת הצוות?
מסלקים שלוש סיבות לרעש: בונים קו בסיס לפי מצב המאגר הנוכחי ולא חוסמים את מה שהיה קודם; מפעילים בדיקה רק על שורות שהשתנו; קובעים סף לפי רמת חומרה לחסימה, והשאר עובר לדוח. השתקה מנסחים כאנוטציה עם נימוק ומועד בחינה מחדש. את שיעור התראות השווא מחשבים במפגשי טריאז' שבועיים — זה גודל מדיד, לא תחושה.
מה יקרה בעדכון כללים או מנוע?
הסטים מנוהלים בגרסאות יחד עם הקוד, גרסה חדשה מורצת תחילה על ענף ייחוס ומושווית לתוצאה הקודמת לפי מספר הממצאים. אם ההבדל מוסבר — מפעילים, אם לא — הכלל משופר. ההרצה הראשונה אחרי העדכון נעשית במצב אזהרות, הבנייה לא נכשלת.
אפשר להטמיע בשלבים, בלי לעצור מהדורות?
כן, וזה הנתיב המועדף: שירות אחד או שניים במצב צפייה, אחר כך חסימה על שורות שהשתנו, ואז הרחבה לשאר המאגרים. את סדר השלבים קובעים מראש, כדי שהצוות יראה מתי הבדיקות יתחילו להשפיע על הבנייה, ויספיק לטפל במה שהצטבר.
ממה נתחיל בעבודה על המאגר שלכם
כדי שההתחלה של עבודה על המאגר תימשך ימים ולא שבועות, אנחנו צריכים מכם סט מינימלי של נתוני קלט ושיחה קצרה אחת לעניין. הרשימה שלהלן — מה שאנחנו מבקשים בדיון על המשימה; היא גם הופכת לשלד של תוכנית הטמעת הבדיקות.
- גישה לקוד: מאגר או מראה שלו עם היסטוריית קומיטים — בלעדיה אי אפשר לבנות חתך בסיס ולהפריד ממצאים חדשים מאלה שנמצאים בבסיס הקוד זמן רב. למונורפו — פילוח לפי ספריות ובעלי מודולים.
- גישות למערכות הבנייה: הרשאה ליצור משתמש שירות נפרד ולהוסיף שלב ניתוח, אבל בלי הרשאות לשנות את לוגיקת המהדורות.
- נקודות אינטגרציה: מה צריך להפעיל את הבדיקה — קומיט, בקשת מיזוג, הרצה לילית על ההיסטוריה המלאה. מזה תלוי היכן שמים ספים חוסמים והיכן רק דוח.
- כללים וחריגים פעילים: אילו לינטרים ומנתחים כבר עובדים, היכן נשמרות השתקות, מי מאשר אותן. אין טעם לשכפל בדיקות קיימות.
- סדרי עדיפויות לפי סוגי ממצאים: אילו קטגוריות קריטיות עבורכם, ומה נכנס להתעלמות (בדיקות, קוד מיוצר, ספריות ספק צד שלישי). זה משפיע ישירות על היקף הכללים המותאמים.
- אחראי טריאז' מצד הלקוח: מהנדס אחד שמנתח ממצאים ומחליט מה נכנס לעבודה ומה לחריג.
לאחר מכן אנחנו חוזרים עם הערכה ותוכנית: שלבים, היקף כללים מותאמים ל-Semgrep, רמת הרעש הרצויה ומדדים שלפיהם נבדוק את התוצאה. תארו את המשימה — נתחיל בניתוח המאגר.







