מי שעדכן את Handlebars ל-4.7.9 בסוף מרץ סגר את הכרטיס. הגרסה הזאת יושבת בתוך טווח הגרסאות המושפעות של CVE-2026-106446, חולשה בציון 9.8 שפורסמה ב-6 באוקטובר 2026. הבדיקה שנוספה ב-4.7.9 חוסמת את הניצול שבשבילו נכתבה, אבל היא מכסה שלושה סוגי צמתים בלבד, והמחקר החדש נכנס דרך השדות שהיא דילגה עליהם.

סקירה כללית

Handlebars היא ספריית תבניות ל-JavaScript, אחת החבילות הנפוצות ב-npm, ולרוב היא נכנסת לפרויקט בעקיפין. הפונקציה compile() שלה הופכת תבנית טקסט לפונקציית JavaScript שמרנדרת אותה. פחות ידוע שהיא מקבלת גם עץ תחביר מפורסר מראש (AST), כלומר אובייקט רגיל.

כאן נפתח המרחב לתוקף. אפליקציה שמעבירה ל-compile() JSON מהרשת מאפשרת לו לשלוח אובייקט שמתחזה לעץ תחביר תקין, והקומפיילר כותב ערכים מתוכו אל הקוד שהוא מייצר. ב-4.7.9 נוסף בדיוק בשביל זה validator, אלא שהוא בודק ערכים רק בצמתים מסוג PathExpression, NumberLiteral ו-BooleanLiteral, ומדלג על אובייקטים שאין להם שדה type בכלל. לפער בין מה שהקוד מצפה לקבל לבין מה שהגיע קוראים Type Confusion.

מזהה: CVE-2026-106446
סוג: הזרקת קוד דרך בלבול טיפוסים ב-AST (CWE-94, CWE-843)
מוצר: handlebars (npm)
גרסאות מושפעות: 4.0.0 עד 4.7.9 כולל
גרסה מתוקנת: 4.7.10
ניצול בפועל: לא, והחולשה אינה ברשימת ה-KEV של CISA

ציר זמן

26 במרץ 2026: גרסה 4.7.9 יוצאת, עם תיקון אבטחה שמכסה תשע התראות GHSA
27 במרץ 2026: CVE-2026-33937 עולה ל-NVD בציון 9.8, הזרקת קוד דרך שדה value של צומת NumberLiteral
5 באוקטובר 2026: גרסה 4.7.10 יוצאת, ואיתה ההתראה GHSA-8r5x-fm3f-whwj שמתארת את העקיפה
6 באוקטובר 2026: הרשומה עולה ל-NVD בציון 9.8

איך הניצול עובד

התוקף מנצל את ה-Type Confusion בדיוק בשדות שה-validator לא נוגע בהם. הווריאציה הנקייה ביותר היא blockParams של צומת Program: הקומפיילר קורא ממנו את length וכותב אותו אל הקוד המיוצר, ואובייקט שבו length הוא מחרוזת ולא מספר עובר את הבדיקה בשלום. התוכן שלו מורץ ברגע הרינדור, גם כשה-helper שהתבנית מפנה אליו לא קיים. שאר הווריאציות עוברות דרך depth, דרך value של StringLiteral ודרך original של PathExpression. ההבדל בין compile() ל-precompile() הוא ההבדל בין קורבן אחד לרבים: עם compile() הקוד מורץ על השרת שמרנדר, ועם precompile() הוא נצרב לתוך הפלט ומורץ בכל מקום שטוען אותו, הדפדפנים של המשתמשים כולל.

ניתוח ציון ה-CVSS

ציון CVSS: 9.8

הציון מתאר את התרחיש הגרוע, אפליקציה שמעבירה ל-compile() אובייקט מבחוץ: בלי דרישת אימות, בלי אינטראקציה, הרצת קוד. מי שמעביר רק מחרוזות לא חשוף, כך שכל השאלה היא איפה בקוד שלכם compile() או precompile() מקבלות משהו שלא נולד כמחרוזת.

איפה למצוא Proof of Concept (PoC)

ההתראה של הפרויקט, GHSA-8r5x-fm3f-whwj, היא גם התיעוד הטכני המלא וגם ה-PoC: היא מפרטת את ארבעת השדות שנשארו בלי בדיקה ומדגימה שרת Express שמעביר קלט מהבקשה ישר ל-compile(). היא גם מקנה קרדיט ל-16 מדווחים שונים, מספר שמסביר לבד למה הבדיקה החלקית לא החזיקה חצי שנה.

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