בפברואר 2026 נחשפה בפומבי פגיעות קריטית מסוג "בריחה מסביבת הבדיקה" (sandbox escape) ב-n8n, פלטפורמת האוטומציה של זרימות עבודה בקוד פתוח הנפוצה ביותר. הפגיעות, שזוהתה תחת המספר CVE-2026-25049, מאפשרת למשתמשים מאומתים לעקוף את סביבת הבדיקה של הערכת הביטויים ולהפעיל פקודות מערכת שרירותיות בשרת המארח, ובכך להשיג ביצוע קוד מרחוק מלא, עם ציון CVSS v3.1 של 9.9.
במסגרת תוכנית המלגותOPSWAT של OPSWAT , ערכו עמיתינו ניתוח טכני מקיף של CVE-2026-25049, ובחנו את הגורם הבסיסי, מנגנון הניצול וההשפעה הארגונית של הפגיעות.
בלוג זה מספק סקירה מפורטת של הפרצה – החל מארכיטקטורת עיבוד הביטויים של n8n ובקרות האבטחה הרב-שכבתיות שלה, ועד לטכניקה המדויקת שמצליחה לעקוף את כל חמש שכבות ההגנה בו-זמנית.

CVE-2026-25049 היא פגיעות קריטית מסוג "בריחה מארגז החול" (sandbox escape) ב-n8n, המסווגת תחת CWE-913: בקרה לא נאותה על משאבי קוד המנוהלים באופן דינמי. הפגיעות משפיעה על כל גרסאות n8n שקדמו לגרסה 1.123.17, וכן על גרסאות 2.0.0 עד 2.5.1, ותוקנה בגרסאות 1.123.17 ו-2.5.2. היא מאפשרת למשתמשים מאומתים בעלי הרשאות ליצירת זרימות עבודה ליצור ביטויי JavaScript זדוניים העוקפים את סביבת הבדיקה של הביטויים בפלטפורמה, ובסופו של דבר לבצע פקודות שרירותיות בשרת המארח.

הפגיעות חמורה במיוחד משום ש-n8n תופס לרוב מעמד בעל הרשאות מיוחדות בתשתית הארגונית. כרכזת לאוטומציית זרימות עבודה, ל-n8n יש בדרך כלל גישה ישירה ל-API פנימיים, למסדי נתונים, למאגרי אישורים ולשירותי צד שלישי. פריצה למערך n8n לא רק חושפת את שרת האוטומציה – היא מהווה נקודת כניסה לכל מערכת מחוברת, מה שמגדיל באופן דרמטי את היקף הנזק הפוטנציאלי של הניצול.
CVE-2026-25049 אינו ממצא עצמאי, אלא עקיפה של התיקון ל-CVE-2025-68613, פרצת בריחה מסביבת הבדיקה (sandbox) קודמת במנגנון הערכת הביטויים של n8n. למרות יישום הגנות רב-שכבתיות לאחר הפגיעות הראשונית, פער מהותי באופן שבו המנקה מעבד סוגי צמתים של עץ תחביר מופשט (AST) ב-JavaScript איפשר לסוג ההתקפה המקורי לצוץ מחדש באמצעות וקטור תחבירי שונה. דפוס זה – שבו תיקון מטפל בטכניקת הניצול הספציפית ולא בחולשת התכנון הבסיסית – מדגיש את האתגר המתמשך של אבטחת סביבות הערכת קוד דינמיות.
הפגיעות נחשפה ב-4 בפברואר 2026, יחד עם עשרה דוחות אבטחה נוספים עבור n8n, והיא נבדקה באופן עצמאי על ידי מספר צוותי מחקר בתחום האבטחה.
אודות n8n
n8n היא פלטפורמת אוטומציה של זרימות עבודה בקוד פתוח, המאפשרת לארגונים לחבר בין מערכות, לבצע אוטומציה של תהליכים וליצור אינטגרציות בין מאות שירותים. בזכות אימוץ נרחב ומעל 1,300 אינטגרציות זמינות, n8n הפכה לאחד הכלים הפופולריים ביותר בקטגוריה שלה, והיא משמשת צוותי פיתוח וארגונים לביצוע אוטומציה של כל דבר, החל מכלי עבודה פנימיים וכלה בצינורות נתונים קריטיים לעסק.

הפלטפורמה תומכת הן בפריסות עצמאיות והן בפריסות ענן, ומספקת בונה זרימות עבודה חזותי לצד תמיכה ישירה ב-JavaScript עבור לוגיקה מותאמת אישית. הארכיטקטורה של n8n מבוססת על צמתים: זרימות העבודה מורכבות מצמתים מקושרים המעבירים נתונים בפורמט JSON בין טריגרים, פעולות ושלבי פונקציות. הביצוע יכול להתבצע במצב ידני לצורך בדיקה או במצב ייצור לצורך פריסה חיה. ארכיטקטורה זו, בשילוב עם תמיכה מובנית בביטויי JavaScript וגישה ל-API פנימיים ולמאגרי אישורים, הופכת את n8n לכלי אוטומציה רב עוצמה – אך גם ליעד בעל ערך גבוה כאשר מתעוררות פגיעויות.
רקע טכני
עצי תחביר מופשטים
עץ תחביר מופשט (AST) הוא ייצוג היררכי של קוד מקור שנוצר על ידי מנתח תחבירי. במקום להתייחס לקוד כאל מחרוזת שטוחה, ה-AST מפרק אותו לצמתים מובנים המייצגים את מרכיביו התחביריים – הצהרות על משתנים, ביטויי פונקציות, ביטויי חברים, מזהים וערכים קבועים.

הבנת סוגי הצמתים ב-AST חיונית לניתוח זה, שכן בקרות האבטחה של n8n פועלות ברמת ה-AST. מנגנוני הסינון בודקים סוגי צמתים ספציפיים כדי לזהות ולחסום דפוסים מסוכנים. הפגיעות מנצלת את העובדה שאותה פעולה סמנטית – גישה למאפיין של אובייקט – עשויה לייצר סוגי צמתים שונים לחלוטין ב-AST, בהתאם לדקדוק ה-JavaScript שבו נעשה שימוש.

לדוגמה, הביטוי obj.constructor מייצר צומת MemberExpression, בעוד ש-const { constructor } = obj מייצר VariableDeclaration המכיל ObjectPattern עם צומת Property. שניהם מחלצים את אותה תכונה, אך מבני ה-AST שונים בתכלית – ומנגנוני הסינון של n8n בודקים רק את התבנית הראשונה.
הערכת ביטויי n8n וארכיטקטורת האבטחה
הארכיטקטורה של n8n מחולקת לחמש שכבות: Frontend, CLI, Core, Workflow ו-Nodes. שכבת ה-Workflow אחראית על הערכת ביטויים, והיא הרכיב הרלוונטי לפגיעות זו.

n8n מאפשרת למשתמשים לשלב ביטויי JavaScript בפרמטרים של צמתים בתהליך העבודה כדי לעבד נתונים באופן דינמי. ביטויים אלה מחושבים בצד השרת באמצעות ספרייה בשם Tournament, המפרשת את הביטויים למבנה עץ תחבירי (AST) לפני ביצועם. ווים לניקוי נתונים מוזרקים ישירות לתהליך היצירה של Tournament, ומבצעים בדיקות במהלך בניית ה-AST כדי ליירט תבניות מסוכנות לפני ביצוע הקוד.

מכיוון שהביטויים הללו פועלים בתוך אותו תהליך Node.js שבו פועל שרת n8n, הפלטפורמה מיישמת חמש שכבות אבטחה נפרדות שנועדו למנוע מקוד לא מהימן לחמוק מהארגז החולי.
שכבה 1 - החלפת ההקשר הגלובלי
לפני חישוב כל ביטוי, n8n יוצר סביבת ביצוע מוגבלת על ידי החלפת אובייקטים ופונקציות גלובליים מסוכנים. מאפיינים כגון document, window, globalThis, eval, setTimeout, setInterval ו-Function מוחלפים באובייקטים ריקים, ובכך נמנעת גישה ישירה ליכולות אלה.


לגישה זו יש מגבלה מובנית: אם תוקף מצליח לחמוק מההקשר המוגבל ולהגיע לאובייקט התהליך הגלובלי האמיתי, המאפיינים שהוחלפו מאבדים את הרלוונטיות שלהם.
שכבה 2 - אימות באמצעות ביטוי רגולרי
לפני שהביטוי מגיע למנתח, n8n מבצע בדיקת ביטוי רגולרי על מחרוזת הביטוי הגולמית כדי לחסום את הגישה למאפיין ה-constructor — וקטור נפוץ להשגת ה-constructor של Function ולביצוע קוד.

ביטוי הרגולרי /\.\s*constructor/gm מזהה גישה באמצעות סימון הנקודה ל -.constructor. עם זאת, בדיקה זו מוגבלת ביסודה, שכן JavaScript מציע מספר דרכים תחביריות לגישה לאותו מאפיין, ולא כולן כרוכות בשימוש בסימון הנקודה.
שכבה 3 - מנקה זמן ריצה של AST – PrototypeSanitizer
ההגנה המתוחכמת ביותר פועלת במהלך בניית ה-AST. ה-hook של PrototypeSanitizer סורק את ה-AST ובודק את צמתי ה-MemberExpression כדי לקבוע אם המאפיין שאליו ניגשים מופיע ברשימת החסימה של מאפייני אובייקטים לא בטוחים – כולל constructor, __proto__, prototype, mainModule ו-binding.

ה-sanitizer מטפל בשלושה מקרים: סימון נקודתי (obj.prop), שבו הוא בודק את שם המזהה; סימון בסוגריים סטטי (obj['prop']), שבו הוא בודק את ערך המחרוזת המילולי; וביטויים דינמיים העטופים בפונקציית sanitizer בזמן ריצה. כפי שמוצג באיור 10, נבדקים רק צמתים מסוג MemberExpression – דפוסי פירוק לא נבדקים.
שכבה 4 - פונקציית ה-Sanitizer של AST Runtime: ThisSanitizer
FunctionThisSanitizer, שנוסף כתיקון ישיר ל-CVE-2025-68613, מיירט ביטויי פונקציה המופעלים באופן מיידי (IIFE) ומשכתב אותם כך שיקשרו את `this` לאובייקט ריק. פעולה זו מונעת את הטכניקה ששימשה בפריצה המקורית, שבה (function(){ return this })() גרמה לדליפת אובייקט התהליך הגלובלי באמצעות הפניה ל-`this` שלא נקשרה.

חשוב לציין כי מחטא זה מטפל רק בצמתים מסוג FunctionExpression. הוא חוזר באופן מפורש מוקדם יותר עבור כל מתודה מקבלת קריאה שאינה FunctionExpression, כולל פונקציות חץ.
מאפיינים מסוכנים כגון eval, Function ו-process.mainModule מוסרים או מוחלפים בהקשר הביצוע, ובכך נמנעת גישה ישירה לפרימיטיבים של ביצוע קוד, גם אם עוקפים את השכבות הקודמות.
ניתוח פגיעויות
הגורם השורשי
הגורם הבסיסי ל-CVE-2026-25049 טמון בהנחה משותפת לכל חמש שכבות האבטחה: כל שכבה הניחה שגישה למאפיינים תתבצע באמצעות סימון הנקודה (obj.constructor) או סימון הסוגריים (obj['constructor']). אף אחת מהן לא לקחה בחשבון את תחביר פירוק המבנים ב-JavaScript.
פירוק מבנה ב-JavaScript מאפשר לחלץ תכונות מאובייקטים באמצעות מבנה AST שונה בתכלית:
// Traditional access - produces MemberExpression node
obj.constructor; // Blocked by regex, AST sanitizer, and runtime checks
// Destructuring - produces ObjectPattern → Property node
const { constructor } = obj; // Not checked by any layer
למרות ששני התבניות משיגות את אותה התוצאה, הן מייצרות ייצוגים שונים לחלוטין ב-AST. ה-PrototypeSanitizer בודק רק צמתים מסוג MemberExpression, והביטוי הרגולרי מתאים רק לתבניות מסוג .constructor. הקצאות פירוק יוצרות צמתים מסוג VariableDeclaration → ObjectPattern → Property, שאף אחד מהמטהרים אינו סורק.
לכך מתווספת הדרך שבה n8n מטפל בפונקציות חץ. ה-FunctionThisSanitizer יירט רק צמתים מסוג FunctionExpression ויערוך אותם מחדש כדי לקשר את `this` להקשר בטוח. פונקציות חץ מייצרות צמתים מסוג ArrowFunctionExpression ב-AST, שה-sanitizer אינו מעבד. מכיוון שפונקציות חץ יורשות את `this` מההיקף המקיף אותן (lexical this), הן מאפשרות גישה להקשר הגלובלי שלא עבר ניקוי.
שתי השגיאות הללו יחד יוצרות עקיפה מוחלטת: פירוק המבנה מחלץ את בונה הפונקציה (Function constructor) מבלי להפעיל בדיקות גישה למאפיינים, ופונקציות החץ מספקות הקשר ביצוע ש-FunctionThisSanitizer אינו מיירט.
ניצול
הפרצה משלבת את שתי הפגיעויות כדי לפרוץ את כל שכבות האבטחה בו-זמנית. הצוות שלנו איתר את מסלול הניצול הבא:
שלב 1 – הזנת פונקציית חץ. המטען מתחיל בפונקציית חץ העטופה בביטוי פונקציה המופעל מיד (IIFE):
={{(() => {
// פונקציית חץ - עוקפת את FunctionThisSanitizer
...
})()}}
ה-FunctionThisSanitizer בודק אם המתקשר הוא FunctionExpression; מכיוון שמדובר ב-ArrowFunctionExpression, ה-sanitizer חוזר מוקדם מבלי לשכתב את הקריאה. פונקציית החץ מתבצעת עם גישה מלאה להקשר הגלובלי האמיתי.
שלב 2 – עקיפת פירוק. בתוך פונקציית החץ, פירוק מוציא את בונה הפונקציה מתוך מופע של פונקציית החץ:
const { constructor } = () => {};
מכיוון שמדובר בהקצאה לפירוק, ה-AST מכיל צומת ObjectPattern במקום MemberExpression. בדיקת הביטוי הרגולרי אינה מזהה תבנית .constructor, ו-PrototypeSanitizer אינו בודק את שם המאפיין. כעת, לתוקף יש הפניה למבנה ה-Function.
שלב 3 – ביצוע קוד דינמי. לאחר שהשיג את בונה הפונקציות, התוקף בונה ומבצע קוד שרירותי:
return constructor(
'return process.mainModule.require("child_process").execSync("whoami").toString()',
)();
הפונקציה הנבנית באופן דינמי פועלת מחוץ להקשר של סביבת הבדיקה (sandbox) עם גישה מלאה לאובייקט התהליך של Node.js, מה שמאפשר ביצוע פקודות מערכת שרירותיות על המחשב המארח.

הוכחת קונספט
כדי להדגים את ההשפעה בפועל של פגיעות זו, החוקרים שלנו שיחזרו את הניצול בסביבה מבוקרת במעבדה. תרחיש ההתקפה כולל הפעלת מופע n8n פגיע וייבוא של זרימת עבודה המכילה את המטען הזדוני בתוך פרמטר של צומת — תוך התמקדות ספציפית בצומת "ערוך שדות" (Edit Fields Node), המאפשרת הערכת ביטויים.

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

הסלמת Webhook ל-RCE ללא אימות
חומרת הפגיעות הזו גוברת באופן משמעותי בשילוב עם פונקציונליות ה-webhook של n8n. n8n מאפשרת לתהליכי עבודה לחשוף נקודות קצה HTTP כ-webhooks עם אפשרויות אימות הניתנות להגדרה, כולל אסימוני bearer, אימות בסיסי, ו—חשוב מכך—ללא אימות כלל. תוקף בעל גישה ליצירת זרימות עבודה יכול להגדיר webhook ציבורי עם אימות: "none", להטמיע את המטען של RCE בצומת מחובר, ולהפעיל את זרימת העבודה. בשלב זה, כל בקשת HTTP לכתובת ה-URL של ה-webhook – מכל מקום באינטרנט – מפעילה ביצוע פקודות שרירותיות בשרת המארח.
מסלול ההסלמה הזה הופך את CVE-2026-25049 מפגיעות פנימית המאובטחת באמצעות אימות, למנגנון תקיפה שאינו מאובטח למעשה, החשוף לכל רחבי האינטרנט.
הֲקָלָה
צוות n8n טיפל בפגיעות CVE-2026-25049 בגרסאות 1.123.17 ו-2.5.2 באמצעות יישום בדיקת טיפוסים נאותה בזמן ריצה בפונקציות הטיהור והרחבת כיסוי ה-AST כדי לטפל בדפוסי פירוק. על ארגונים המשתמשים בגרסאות המושפעות לשדרג את התוכנה באופן מיידי.
אם שדרוג מיידי אינו אפשרי, על המנהלים להגביל את ההרשאות ליצירה ולעריכה של זרימות עבודה למשתמשים מהימנים בלבד, ולהטמיע את n8n בסביבה מאובטחת עם הרשאות מערכת הפעלה וגישה לרשת מוגבלות.
לאור חומרת הפגיעות והקלות שבה ניתן לנצל אותה – במיוחד בשילוב עם וובהוקים ציבוריים – על ארגונים לבצע גם ביקורת על תהליכי העבודה הקיימים כדי לאתר ביטויים חשודים, לפקח על ביצוע פקודות מערכת חריגות שמקורן בתהליך n8n, ולבדוק את תצורות הוובהוקים כדי לאתר נקודות קצה חשופות ללא אימות.
הפחתת סיכונים באמצעות OPSWAT
באמצעות השימוש OPSWAT , ארגונים יכולים לזהות במהירות רכיבי n8n פגיעים בתשתית שלהם ולנקוט בצעדים לפני שתתבצע פריצה. OPSWAT , טכנולוגיה בסיסית בפלטפורמת MetaDefender®, מספקת רשימה מקיפה של כל רכיבי התוכנה, הספריות והתלות הנמצאים בשימוש בסביבת הארגון.

כפי שמוצג באיור 15, MetaDefender סרק את קובץ package.json המכיל את התלות ב-n8n וסימן באופן אוטומטי את CVE-2026-25049 כ"קריטי", תוך הצגת טווח הגרסאות המושפעות והגרסאות המתוקנות המומלצות לתיקון. הדבר מאפשר לצוותי האבטחה לזהות במהירות את הפגיעות ולתעדף אותה בכל סביבת הפריסה שלהם.
OPSWAT זמין ב MetaDefender וב MetaDefender Software Chain™, ומאפשר לצוותי האבטחה:
- איתור מהיר של רכיבים פגיעים - זיהוי מיידי של תלות בקוד פתוח המושפעות מפגיעויות של פריצה מאזור הבדיקה (sandbox escape) והפעלת קוד, מה שמאפשר תיקון או הסרה מהירים.
- הקפידו על התקנת תיקונים ועדכונים באופן יזום - עקבו באופן רציף אחר רכיבי הקוד הפתוח כדי לאתר חבילות מיושנות או לא מאובטחות, ובכך לאפשר ביצוע עדכונים בזמן ולהפחית את החשיפה לסיכונים.
- שמירה על תאימות ודיווח - עמידה בדרישות הרגולטוריות, שכן המסגרות הרגולטוריות מחייבות יותר ויותר שקיפות בשרשראות האספקה של תוכנה.
