Context Isolation — מניעת זליגת מידע בין משתמשים וסוכנים

מאת צוות מדיה דיל · 12.08.2026 · Context Engineering · 5 דק׳

איך מונעים מצב שבו מידע מלקוח אחד, ממשתמש אחד או מסוכן אחד מזליג בטעות להקשר של אחר — ברמת ה-retrieval, הזיכרון והתהליך עצמו.

מערכת תמיכה מבוססת AI שרתה כמה לקוחות B2B על אותה תשתית עלתה לפרודקשן, ותוך שבוע נציג של לקוח אחד קיבל מהסוכן תשובה שכללה פרט קטן אבל בלתי אפשרי — התייחסות למדיניות תמחור שלא הייתה שייכת לחברה שלו בכלל, אלא ללקוח אחר לגמרי במערכת. אף אחד לא "פרץ" למערכת. הבעיה הייתה שכבת ה-retrieval לזיכרון וה-RAG לא סיננה לפי tenant בצורה קשיחה מספיק — שאילתת דמיון סמנטי פשוט מצאה את המסמך "הכי דומה" בכל המאגר, בלי להתחשב במי הבעלים שלו. Context Isolation הוא העיקרון שמידע של ישות אחת (משתמש, לקוח, טננט, או אפילו סוכן משנה בתוך מערכת multi-agent) לעולם לא זולג להקשר של ישות אחרת, גם כשהתשתית הטכנית משותפת.

למה זה קורה גם בלי כוונה או פריצה

זליגת הקשר כמעט אף פעם לא תוצאה של פרצת אבטחה קלאסית — היא תוצאה של תשתית זיכרון או RAG משותפת שלא נבנתה עם isolation כעיקרון יסוד. כשמנוע חיפוש סמנטי (ראו embeddings) עובד על אינדקס אחד גדול לכל הלקוחות, "הכי דומה" זה קריטריון גיאומטרי טהור שלא יודע כלום על גבולות ארגוניים. אם לא מוסיפים סינון מפורש, המערכת תמצא בהחלט את התוצאה הכי רלוונטית סמנטית — היא פשוט עלולה להיות שייכת לגורם הלא נכון. אותה בעיה בדיוק קיימת בזיכרון אפיזודי (ראו Episodic Memory): אפיזודה ששייכת לביצוע משימה עבור לקוח אחד לא אמורה לעולם להישלף כתקדים בהקשר של לקוח אחר, גם אם התיאור דומה להפליא.

שכבות הבידוד הנדרשות

Isolation אמיתי דורש אכיפה בכמה שכבות בו-זמנית, כי כל שכבה לבד ניתנת לעקיפה בטעות:

  • אינדקס / namespace — כל tenant מקבל namespace נפרד באינדקס ה-vector, לא רק שדה metadata לסינון. סינון מבוסס metadata לבדו נשען על כך שהמפתח תמיד יזכור להוסיף את התנאי — טעות אנוש אחת חושפת הכל.
  • שכבת האחסון של הזיכרון המובנה — רשומות ב-Structured Memory חייבות מפתח tenant/user כחלק בלתי נפרד מכל שאילתה, לא כפרמטר אופציונלי.
  • שכבת ה-prompt בזמן ריצה — גם אם השליפה עצמה מבודדת נכון, יש לוודא שאין דרך לגרום למודל, דרך prompt injection, "לבקש" מידע מהקשר של משתמש אחר בעקיפין.
  • שכבת ה-cache — אם משתמשים ב-prompt caching לחיסכון בעלות, יש לוודא שמפתח ה-cache כולל מזהה tenant, כדי ש-cache שנוצר עבור לקוח אחד לא "יוגש" בטעות ללקוח אחר עם prefix דומה.

בידוד בין סוכנים, לא רק בין משתמשים

בארכיטקטורות multi-agent, isolation לא רלוונטי רק בין לקוחות אלא גם בין סוכנים בתוך אותה משימה. סוכן משנה (sub-agent) שמבצע חיפוש רגיש או מעבד מידע פנימי לא תמיד צריך להעביר את כל ההקשר שלו בחזרה לסוכן הראשי — לפעמים נכון להעביר רק את התוצאה המסוננת, לא את שרשרת החשיבה המלאה, כדי למנוע דליפת מידע ביניים לא מכוון דרך שכבות שלא אמורות לראות אותו. הדפוס הזה קשור ישירות לאופן שבו מתכננים חלוקת אחריות בארכיטקטורת זיכרון סוכנים — לא כל שכבה בהיררכיה צריכה גישה לכל מה שכל שכבה אחרת יודעת.

בדיקה: לא מספיק "זה עבד בטסט אחד"

הדרך היחידה לבדוק isolation ברצינות היא לבנות eval ייעודי שמדמה בכוונה ניסיון זליגה: יוצרים שני "לקוחות" מדומים עם מידע שונה וקרוב מספיק סמנטית, ובודקים שוב ושוב שבקשה בהקשר של לקוח A לעולם לא מחזירה מידע ששייך רק ל-B, גם כשהניסוח כמעט זהה בין שני הלקוחות. בדיקה חד-פעמית לא מספיקה כי isolation יכול להישבר בשקט אחרי שינוי לא קשור — הוספת שדה חדש לסכמה, שינוי בלוגיקת החיפוש, עדכון גרסת ספריית embeddings — בלי שאף אחד יבחין מיד.

עלות מול סיכון

בידוד מלא, עם אינדקסים נפרדים לכל tenant, יקר יותר תפעולית מאינדקס משותף עם סינון. עבור מוצרים עם עשרות לקוחות B2B ברמת רגישות גבוהה, העלות הנוספת מוצדקת כמעט תמיד. עבור מערכת consumer עם מיליוני משתמשים בודדים ובלי מידע רגיש חוצה-ארגוני, סינון מבוסס metadata עם בדיקות תקינות קפדניות יכול להספיק — כל עוד יש מודעות מלאה לכך שזו החלטת פשרה מכוונת, ולא מחדל בהיעדר החלטה.

ברירת מחדל בטוחה: deny by default

העיקרון החשוב ביותר בעיצוב שכבות isolation הוא איזו התנהגות קורית כשמשהו משתבש — מתי חסר תג tenant על רשומה, כשקריאה ל-API נכשלת באמצע, כשמפתח נשלף אבל בלי הקשר מלווה. מערכת שנבנתה עם "allow by default" (אם אין הוראה מפורשת לחסום, מציגים) חושפת את עצמה לכל באג עתידי כמקרה זליגה פוטנציאלי. מערכת שנבנתה עם "deny by default" הופכת כל תקלה כזו לכשל בטוח — המשתמש מקבל שגיאה או תשובה חלקית במקום מידע שלא שייך לו. ההבדל הזה נשמע כמו פרט מימוש קטן, אבל בפועל הוא ההבדל בין מערכת שבה כל באג הוא אירוע אבטחה פוטנציאלי, לבין מערכת שבה רוב הבאגים נכשלים בבטחה. יישום בפועל דורש שכל שכבת שליפה — RAG, זיכרון מובנה, cache — תדרוש מזהה tenant מפורש כפרמטר חובה, בלי ברירת מחדל של "הכל" כשהפרמטר חסר, כדי שהשגיאה תתגלה מיד בזמן פיתוח ולא תישאר סמויה עד שהיא מתפוצצת בפרודקשן.

isolation ומבחני חדירה ייעודיים

מעבר לבדיקות אוטומטיות שנבנות כחלק מ-eval שוטף, מערכות רגישות מרוויחות ממבחן חדירה ייעודי (penetration test) שממוקד ספציפית בזליגת הקשר, לא רק באבטחת אפליקציה כללית. מבחן כזה כולל ניסיונות מכוונים לגרום למערכת "לחשוף" מידע ממשתמש אחר — בקשות מנוסחות בעדינות שמנסות לפתות את המודל לצטט תוכן מהקשר של tenant אחר, ניסיונות prompt injection שמטרתם לשנות את תנאי הסינון של שאילתת ה-RAG, ובדיקת מקרי קצה כמו משתמשים ששייכים בטעות לשני tenants בו-זמנית (למשל אחרי מיזוג חברות או שינוי הרשאות). ההבדל בין מבחן חדירה כזה לבין בדיקת אבטחה רגילה הוא שהוא לא בודק רק אם התוקף יכול "לפרוץ" במובן הטכני, אלא אם עצם התנהגות המודל, שנועדה להיות מועילה ולענות על שאלות, עלולה לחשוף מידע דרך נתיב שלא היה מכוון כפרצה מלכתחילה.

תגיות: Context Isolation · Multi-Tenant · RAG Security · Prompt Injection · Agent Memory

← חזרה לבלוג · צור קשר