הוא קורא את הכללים שלכם
הקובץ ~/.ai-jail שלכם נחשב אמין. קובץ .ai-jail שנמצא בתוך הפרויקט נחשב לא אמין: הוא יכול להדק את ה-sandbox, ולעולם לא לפתוח אותו. דגלים בשורת הפקודה גוברים על שניהם.
הכלי ai-jail בונה עותק קטן וסגור של המערכת שלכם, שם בתוכו את הפרויקט ומעלה את הסוכן בפנים. החומות הן יכולות של מערכת ההפעלה עצמה, ולכן הסוכן רץ במהירות מלאה ולא יכול לכבות אותן. בכל הפעלה הרשת סגורה חוץ מה-host של ה-API של הסוכן עצמו, פתוחה לכמה hosts בשם, או פתוחה לגמרי.
למהנדס שרוצה לדעת מה נאכף. לכל השאר מספיקים הפסקה הראשונה והתמונה הראשונה.
זה לוקח רגע, בכל פעם מחדש, ואחר כך שום דבר לא ממשיך לרוץ ברקע.
↔ החליקו לצדדים כדי לראות את התרשים המלא
הקובץ ~/.ai-jail שלכם נחשב אמין. קובץ .ai-jail שנמצא בתוך הפרויקט נחשב לא אמין: הוא יכול להדק את ה-sandbox, ולעולם לא לפתוח אותו. דגלים בשורת הפקודה גוברים על שניהם.
כל השכבות שמתוארות למטה מוקמות עוד לפני שהסוכן קיים, וה-toolchains שיש לכם (mise, cargo, ה-caches של npm ואחרים) ממופים לקריאה בלבד או לתוך cache ששייך לכלא. אם קובץ הגדרות לא קריא או לא תקין, ai-jail עוצר ולא עולה עם כללים חלשים יותר.
הסוכן יורש את החומות, וכך גם כל סקריפט, חבילה ושרת MCP שהוא מפעיל. כשהסוכן יוצא, גם ai-jail יוצא.
כל הפעלה בוחרת אחד משלושה מצבי רשת. ברירת המחדל היא המצב ההדוק ביותר: בלי יציאה, חוץ ממה שהפרוקסי המסנן מעביר, כלומר ה-host של ה-API של סוכן מוכר בשתי הפלטפורמות, וב-Linux כשה-toolchains דלוקים (ברירת המחדל) גם רשימה קצרה של registries של חבילות. שני האחרים הם דגלים שמעבירים בכוונה.
↔ החליקו לצדדים כדי לראות את התרשים המלא
ברירת המחדל. ה-sandbox מקבל network namespace פרטי בלי שום יציאה, חוץ מדרך הפרוקסי המסנן. לסוכן מוכר הפרוקסי מעביר את ה-host של ה-API שלו, ב-Linux וב-macOS, ולכן ai-jail claude חשוף עובד. ב-Linux, כשה-toolchains דלוקים (ברירת המחדל), הוא מעביר גם רשימה קבועה של registries של חבילות, ולכן npm install ו-cargo build עובדים; ב-macOS ה-registries נשארים סגורים. --no-network מנתק לגמרי.
--allow-host HOST, אפשר לחזור עליו. ה-namespace נשאר סגור. גשר קטן בפנים מעביר את התעבורה לפרוקסי CONNECT בחוץ, שמחייג רק ל-hosts שברשימה ולתת-הדומיינים שלהם. הפרוקסי פותר כל שם פעם אחת, בחוץ, ומחייג לכתובת שבדק. הכלי ai-jail מגדיר http_proxy בפנים, ותוכנית שמתעלמת ממנו לא מגיעה לשום מקום.
--network. החומה נעלמת בצד הרשת, והסוכן יכול לשלוח החוצה כל מה שהוא יכול לקרוא.
| Linux | macOS | |
|---|---|---|
| מה מגדר במצב מסונן | ה-network namespace עצמו, ועוד הגשר שבתוכו | כלל sandbox-exec אחד שמתיר חיבורים יוצאים רק לפורט של הפרוקסי |
| DNS בתוך ה-sandbox | נכשל. הפרוקסי פותר שמות בחוץ. | ה-resolver של המערכת לא מגודר, ולכן נשאר ערוץ DNS ברוחב פס נמוך |
אף חומה לא אמורה להחזיק לבדה. ב-Linux הסוכן יושב מאחורי חמש חומות שהקרנל אוכף כל אחת מהן, ונוספים עליהן שני מסננים: אחד על מה שנכנס ואחד על מה שיוצא.
↔ החליקו לצדדים כדי לראות את התרשים המלא
ai-sandbox). אין לו ערוצי תקשורת בין-תהליכית מול תוכנות של המארח, ויש לו network namespace בלי שום יציאה, אלא אם פתחתם אחת עם --allow-host או --network. אם ai-jail מת, כל מה שבפנים מת יחד איתו./usr זמינות לקריאה בלבד. תיקיית הבית ו-/tmp חדשות ומוחזקות בזיכרון. ה-toolchains שיש לכם (mise, cargo, ה-caches של npm) ממופים לתוך תיקיית הבית החדשה הזו, לקריאה בלבד או כ-cache ששייך לכלא.~/.ssh, ~/.aws, ~/.gnupg, ~/.docker והפרופילים של הדפדפן נמצאים ברשימה מובנית של נתיבים שלעולם לא מעוגנים. תיקיית המצב של ה-harness עצמו, למשל ~/.claude של Claude, היא היוצא מן הכלל: ai-jail מעגן אותה כברירת מחדל לקריאה וכתיבה כדי שהסוכן יעלה מחובר, ו---no-agent-state משאיר אותה בחוץ. כל מה שנכתב מחוץ לפרויקט נעלם בסוף הסשן.ptrace, mount, bpf, מודולי קרנל, io_uring, ה-keyring של הקרנל, raw sockets, וגם את TIOCSTI, קריאה שיכולה להקליד תווים לתוך הטרמינל שלכם. זו רשימת חסימה בכוונה, כדי שקומפיילרים ו-runtimes ימשיכו לעבוד. התהליך היחיד שעולה לפני ש-Landlock ו-seccomp חלים הוא הגשר הקטן שמוציא החוצה את תעבורת הרשת המסוננת, ולכן רק הוא נשאר בלי הגבלה.PATH, HOME, TERM, הגדרות locale, פרוקסי ותעודות.ANTHROPIC_API_KEY עבור Claude, שמועתק כברירת מחדל יחד עם ההתחברות שלו; --no-agent-state עוצר את זה. כשמשימה צריכה משתנה אחר, מעבירים אותו לפי שם בעזרת --env.ב-macOS אין namespaces, אין Landlock ואין seccomp. אותה מדיניות הופכת לפרופיל של sandbox-exec, ה-sandbox המובנה של Apple. התיעוד של ai-jail אומר במפורש שזה לא שקול לבידוד שמתקבל ב-Linux.
↔ החליקו לצדדים כדי לראות את התרשים המלא
| Linux | macOS | |
|---|---|---|
| Backend | הכלי bubblewrap, ואחריו Landlock, seccomp ומגבלות משאבים | sandbox-exec עם פרופיל שנוצר לכל הפעלה. Apple סימנה אותו כ-deprecated, ואין משהו טוב יותר בלי kernel extensions. |
| תיקיית הבית | תיקיית בית חדשה בזיכרון. התיקייה האמיתית לא מעוגנת. | הפרופיל מתחיל בלי הרשאות קריאה גלובליות, ואז מתיר רק את הנתיבים שהסוכן צריך. כך תיקיית הבית האמיתית נשארת סגורה. |
/tmp | פרטית, נזרקת ביציאה | התיקייה /tmp של המארח, כי אין mount namespace. המשתנה TMPDIR מצביע על תיקייה פרטית שנוצרת להפעלה, וזה נתיב ה-temp היחיד שמותר. |
| מיפויי copy-on-write | עם --overlay-map הסוכן כותב לעותק | מטופל כמיפוי לקריאה בלבד |
| רשת | סגורה כברירת מחדל: בלי יציאה, חוץ מה-host של ה-API של סוכן מוכר ומה-registries של החבילות שמותרים כשה-toolchains דלוקים. --allow-host או --network פותחים יותר, --forward-port מעביר פורט אחד מה-loopback של המארח, --no-network סוגר הכול. תחת --lockdown הרשת הפתוחה חסומה תמיד, גם עם --network. | אותה ברירת מחדל ואותם דגלים, כולל ה-host של ה-API של הסוכן המוכר, אבל בלי --forward-port, בלי ה-registries ובלי מיפויי ה-cache של ה-toolchains, שקיימים רק ב-Linux. גם כאן lockdown חוסם את הרשת הפתוחה. |
| תוכנות אחרות | בלתי נראות: רשימת תהליכים נפרדת, בלי IPC של המארח | הגישה אל Mach, IOKit ו-IPC של המארח נדחית, אלא אם העברתם --macos-host-ipc |
הפרויקט כותב בעצמו כמה שפחות קוד אבטחה. הוא מפעיל את bubblewrap, כלי קטן שארוז בכל הפצה מרכזית ושנמצא בשימוש יומיומי דרך Flatpak, ומוסיף מעליו יכולות של הקרנל.
| אפשרות | למה לא |
|---|---|
| Firejail | מסוגל לעשות את העבודה, אבל זה קובץ בינארי עם setuid root, וכמה CVEs נובעים מהתכנון הזה. לעומתו, bubblewrap עובד בלי root. |
| לשכתב את bubblewrap ב-Rust | יותר מ-500 שורות של קוד רגיש מבחינת אבטחה שצריך לתחזק ולתקן לבד, רק כדי לחסוך תלות של בערך 50 KB שמקבלת תיקונים מה-upstream. |
| nsjail | מסוגל, אבל נבנה לשרתים, מוגדר דרך קובצי protobuf, וארוז בפחות הפצות. |
| systemd-nspawn | דורש systemd, ולכן נכשל בתוך קונטיינרים ובמערכות שאין בהן systemd. |
הכלי כולו הוא תוכנת Rust סינכרונית אחת, בלי async runtime, בלי daemon ובלי image של קונטיינר.
התלויות נספרו בריפוזיטורי של ai-jail בגרסה 2.9.0; הבדיקות בגרסה 2.9.0.
כל ai-jail הוא קובץ בינארי אחד, בלי daemon ובלי root. מוסיפים מילה אחת לפני הפקודה שאתם מריצים ממילא.
brew tap akitaonrails/tap && brew install ai-jailai-jail claude