Μετάβαση στο περιεχόμενο

Υποσυστήματα sandbox

Backend Τιμή Πλατφόρμα Διαθεσιμότητα
Απομονωμένο VM microvm macOS, Linux, Windows (υπερεπόπτης microVM) Εξαρτάται από ανίχνευση στον χρόνο εκτέλεσης microVM· εφαρμόζεται σε διαδραστικά τερματικά — το κέλυφος εκτελείται μέσα σε έναν σταθμό, όχι στον κεντρικό υπολογιστή
Εγγενές sandbox native macOS (Seatbelt), Linux και WSL2 (bubblewrap) Ανιχνεύεται κατά την εκκίνηση· το Linux αρνείται μια εκτέλεση που απαιτεί απορρίψεις εγγραφής με glob ονόματος αρχείου, τις οποίες το bubblewrap δεν μπορεί να επιβάλει
Χωρίς απομόνωση none Όλες Η προεπιλογή της ανάλυσης, η προεπιλογή του τερματικού και η εφεδρική λύση όταν δεν υπάρχει διαθέσιμο backend ή έχει οριστεί --sandbox off

Το SandboxBackend.fromName επιστρέφει none για αποθηκευμένη τιμή null ή μη αναγνωρίσιμη. Μια αποθηκευμένη τιμή "docker" αντιστοιχίζεται σε native.

Το microvm είναι το μόνο backend με όριο πυρήνα — το φορτίο εργασίας πραγματικά δεν εκτελείται στον κεντρικό υπολογιστή. Δεν αποτελεί ποτέ σιωπηλή εφεδρική λύση προς καμία κατεύθυνση: η ρητή αίτησή του σε έναν κεντρικό υπολογιστή που δεν μπορεί να εκκινήσει VM αποτυγχάνει με θόρυβο («ζήτησα VM και πήρα το λάπτοπ μου» είναι η μία υποβάθμιση που το περίβλημα δεν μπορεί να αντέξει), και μόνο μια μη καθορισμένη προεπιλογή υποχωρεί στο native, με μια γραμμή καταγραφής να το δηλώνει. Το πραγματικό backend της συνεδρίας αναφέρεται πίσω στον πελάτη και επισημαίνεται με ένδειξη, ώστε ένα τερματικό να μην μπορεί ποτέ να ισχυριστεί ότι είναι περίκλειστο ενώ εκτελείται στον κεντρικό υπολογιστή. Ο κύκλος ζωής, οι εικόνες και η εξερχόμενη κίνηση του ίδιου του VM καλύπτονται από την αναφορά σταθμών.

Τα Windows δεν έχουν εγγενές sandbox. Το NativeSandboxAdapter.probe επιστρέφει available: false σε κάθε κεντρικό υπολογιστή που δεν είναι macOS ή Linux/WSL2. Η αποστολή πρακτόρων στα Windows χρησιμοποιεί επομένως none. Το backend microvm είναι ξεχωριστό: εξαρτάται από ανίχνευση στον χρόνο εκτέλεσης microVM και εφαρμόζεται σε διαδραστικά τερματικά και σταθμούς, όχι στο περιτύλιγμα του bash στον κεντρικό υπολογιστή.

Η ανίχνευση είναι η πύλη της επιβολής. Εκτελείται μία φορά, στην εκκίνηση του διακομιστή.

Κεντρικός υπολογιστής available Σημείωση / υπόδειξη
macOS true sandbox-exec (Seatbelt) — απομόνωση namespace, χωρίς όριο πυρήνα
Linux ή WSL2 με bwrap και socat true bubblewrap — απομόνωση namespace, χωρίς όριο πυρήνα
Linux ή WSL2 χωρίς ένα από τα δύο εργαλεία false requiresInstall: true, με υπόδειξη εγκατάστασης που ονομάζει τα πακέτα που λείπουν
Οποιαδήποτε άλλη πλατφόρμα false Το εγγενές sandbox δεν προσφέρεται σε αυτή την πλατφόρμα

Ο διακομιστής καταγράφει το αποτέλεσμα σε μία γραμμή εκκίνησης: agent sandbox ON μαζί με τη σημείωση, no OS-native agent sandbox on this host μαζί με την υπόδειξη, ή agent sandbox DISABLED by --sandbox off. Το GET /healthz δεν φέρει πεδίο sandbox.

Το --sandbox / CC_SERVER_SANDBOX δέχεται on (προεπιλογή) ή off. Είναι εξαίρεση, όχι ενεργοποίηση: το on σημαίνει «περιτύλιξε όταν ο κεντρικός υπολογιστής προσφέρει backend», ποτέ «απαίτησε ένα».

Χρησιμοποιεί τον μηχανισμό sandbox Seatbelt της Apple (το ίδιο σύστημα που χρησιμοποιεί το macOS App Sandbox).

Το παραγόμενο προφίλ είναι επιτρεπτικό από προεπιλογή ((allow default)) και χαράσσει εξαιρέσεις απόρριψης, επειδή ένα προφίλ που απορρίπτει τα πάντα από προεπιλογή καθιστά ένα διαδραστικό κέλυφος άχρηστο — οι κλήσεις dyld, XPC και Mach που θα έπρεπε να καταγραφούν είναι υπερβολικά πολλές. Η πρακτική συνέπεια είναι ότι ένας πράκτορας μπορεί ακόμη να διαβάσει το μεγαλύτερο μέρος του κεντρικού υπολογιστή· τα καταχωρισμένα checkouts σας προστατεύονται από ρητές απορρίψεις εγγραφής και μετονομασίας, όχι από αορατότητα.

  • Αναγνώσεις του συστήματος αρχείων: απορρίπτονται για τις μυστικές διαδρομές (~/.ssh, ~/.aws, ~/.gnupg, ~/.config/gh, ~/Library/Keychains και το υπόλοιπο σύνολο αποκλεισμού ανάγνωσης)
  • Εγγραφές στο σύστημα αρχείων: επαναφέρονται σε απόρριψη και έπειτα δίνονται ρητές επιτρεπτικές εξαιρέσεις για υποδιαδρομές, με τις διαδρομές υποχρεωτικής απόρριψης (αρχεία rc του κελύφους, .git/hooks, ρυθμίσεις Claude, προστατευμένα checkouts) αποκλεισμένες ακόμη και μέσα σε εγγράψιμη ρίζα. Το file-write-unlink απορρίπτεται σε κάθε απορριπτόμενη διαδρομή και στους προγόνους της, ώστε μια μετονομασία να μην μπορεί να παρακάμψει μια απόρριψη εγγραφής
  • Διεργασίες: το process-exec απορρίπτει τα πάντα επικίνδυνα εκτελέσιμα, συν έναν αποκλεισμό εκτέλεσης οτιδήποτε βρίσκεται σε εγγράψιμο κατάλογο
  • Δίκτυο: περιορίζεται στις θύρες των proxy εντός διεργασίας συν το DNS — το loopback δεν επιτρέπεται καθολικά και οι υποδοχές Unix δεν επιτρέπονται. Οι proxy επιβάλλουν τη λίστα επιτρεπόμενων τομέων ανά συνεδρία (δείτε την εξερχόμενη κίνηση δικτύου)
  • Διαμόρφωση: τα προφίλ παράγονται ανά εκκίνηση από το SandboxSpec

Απαιτήσεις:

  • sandbox-exec (/usr/bin/sandbox-exec), μέρος κάθε εγκατάστασης macOS — δεν απαιτούνται πρόσθετα εργαλεία

Χρησιμοποιεί το bubblewrap (bwrap) για να δημιουργήσει namespace προσάρτησης και PID.

  • Σύστημα αρχείων: δημιουργεί namespace προσάρτησης όπου είναι ορατές μόνο οι προσδεμένες διαδρομές
  • Δίκτυο: εκτελείται σε μη κοινόχρηστο namespace δικτύου· η κίνηση φτάνει στους proxy του κεντρικού υπολογιστή μέσω γεφυρών υποδοχών Unix του socat
  • Διεργασίες: απομόνωση namespace PID

Απαιτήσεις:

  • Εγκατεστημένα τα bubblewrap και socat (sudo apt-get install bubblewrap socat σε Debian/Ubuntu)
  • Υποστήριξη namespace στον πυρήνα (στάνταρ στο σύγχρονο Linux)

Το Bubblewrap μπορεί να επισκιάσει μια υπάρχουσα διαδρομή, αλλά δεν μπορεί να απαγορεύσει ένα νέο αρχείο .env, *.key ή *.pem μέσα σε εγγράψιμο bind. Η τυπική πολιτική αποστολής απαιτεί αυτές τις απορρίψεις με glob ονόματος αρχείου, οπότε η εγγενής αποστολή πρακτόρων αποτυγχάνει κλειστά σε Linux/WSL2 ακόμη και όταν η ανίχνευση βρίσκει το bubblewrap. Δεν εκτελείται με σιωπηλά ασθενέστερη πολιτική. Για να αποκατασταθεί η εγγενής αποστολή στο Linux απαιτείται ένα backend με κανόνες ονομάτων αρχείου κατά τη δημιουργία. Η απενεργοποίηση του sandboxing είναι ρητή εξαίρεση χωρίς περιορισμούς, όχι ισοδύναμο υποκατάστατο.

Χωρίς sandboxing. Η διεργασία εκτελείται απευθείας στον κεντρικό υπολογιστή, με πρόσβαση στο σύστημα αρχείων, το δίκτυο και τις διεργασίες του. Το ACP και το εργαλείο bash του harness παίρνουν ακόμη καθαρισμό περιβάλλοντος και την πολιτική εντολών· το Claude Code μέσω του NoSandboxAdapter κληρονομεί το περιβάλλον του κεντρικού υπολογιστή. Σε αυτό καταφεύγει η αποστολή πρακτόρων σε έναν κεντρικό υπολογιστή χωρίς διαθέσιμο backend ή με --sandbox off, και είναι η προεπιλογή του τερματικού όταν ένας πελάτης δεν ονομάζει κανένα backend.

Τερματικό φιλοξενούμενο στον διακομιστή

Ενότητα με τίτλο «Τερματικό φιλοξενούμενο στον διακομιστή»

Το τερματικό μπαίνει σε sandbox με δικούς του όρους, όχι από την ανίχνευση της αποστολής. Το defaultBackend του TerminalSessionService είναι none και το cc_server δεν το παρακάμπτει, οπότε μια συνεδρία τερματικού εκτελεί το κέλυφος του κεντρικού υπολογιστή εκτός αν ο πελάτης ζητήσει ρητά native — ο πίνακας τερματικού της επιτραπέζιας εφαρμογής δεν το κάνει.

Όταν ζητείται το native, το κέλυφος περιτυλίγεται μέσω του SandboxManager κάτω από ένα σταθερό προφίλ τερματικού: τα $HOME και ο κατάλογος εργασίας της συνεδρίας είναι εγγράψιμα, το δίκτυο είναι ανοιχτό και οι αναγνώσεις των ~/.ssh, ~/.aws, ~/.gnupg, ~/.config/gh και ~/Library/Keychains απορρίπτονται. Το token φιλοξενίας κώδικα μόνο για ανάγνωση και η πύλη push δεν ισχύουν — αυτά είναι ζητήματα της αποστολής. Αν το περιτύλιγμα δεν υποστηρίζεται, η συνεδρία αποτυγχάνει αντί να δείξει ένδειξη εγγενούς sandbox πάνω σε ένα PTY του κελύφους του κεντρικού υπολογιστή.

Όταν εκκινείται ένα sandbox, η εξερχόμενη πρόσβαση στο δίκτυο επιβάλλεται από proxy εντός διεργασίας, όχι από κανόνες τείχους προστασίας του πυρήνα. Σε έναν κεντρικό υπολογιστή χωρίς διαθέσιμο backend τίποτα από αυτά δεν ισχύει και μια εκκινημένη διεργασία φτάνει στο δίκτυο ακριβώς όπως θα έφτανε ο χρήστης του διακομιστή.

  • Ο χρόνος εκτέλεσης του sandbox τρέχει έναν proxy HTTP/HTTPS και έναν proxy SOCKS5 στο 127.0.0.1 μέσα στη διεργασία του cc_server, ένα ζεύγος ανά περιορισμένη συνεδρία (http_proxy.dart, socks_proxy.dart). Οι ταυτόχρονες εκτελέσεις δεν μοιράζονται ζεύγος.
  • Οι διεργασίες μέσα σε sandbox λαμβάνουν μεταβλητές περιβάλλοντος proxy (HTTP_PROXY/HTTPS_PROXY → ο proxy HTTP, ALL_PROXY → ο proxy SOCKS· το GIT_SSH_COMMAND δρομολογεί το git-over-SSH μέσω του proxy SOCKS). Στο Linux το namespace δικτύου δεν είναι κοινόχρηστο, οπότε οι proxy είναι η μόνη διέξοδος· στο macOS το sandbox μοιράζεται το loopback του κεντρικού υπολογιστή και μιλά απευθείας μαζί τους.
  • Ο κεντρικός υπολογιστής-στόχος κάθε σύνδεσης αντιστοιχίζεται με τη λίστα επιτρεπόμενων τομέων της συνεδρίας· οτιδήποτε άλλο απορρίπτεται. Δύο μορφές μπαλαντέρ, καθεμία με ακριβώς ένα *: ένα αρχικό *.example.com ταιριάζει με κάθε υποτομέα (συμπεριλαμβανομένου του a.b.example.com) αλλά όχι με τον ίδιο τον τομέα κορυφής· ένα μπαλαντέρ σε ενδιάμεσο επίπεδο bedrock.*.amazonaws.com ταιριάζει με ακριβώς ένα επίπεδο (bedrock.us-east-1.amazonaws.com, όχι bedrock.evil.attacker.amazonaws.com).
  • Η λίστα επιτρεπομένων επιλύεται ανά συνεδρία από το επιμελημένο βασικό σύνολο (kBaselineAllowedDomains: πάροχοι LLM, φιλοξενία Git, μητρώα πακέτων), συν τους τομείς GitHub (kGithubDomains), συν το SandboxSpec.egressAllowlist. Η διαδρομή αποστολής δεν περνά ποτέ πρόσθετες εγγραφές egressAllowlist, οπότε στην πράξη κάθε εκτέλεση παίρνει το βασικό σύνολο συν το GitHub.
  • Μια σταθερή λίστα απαγόρευσης (kBaselineDeniedDomains: τελικά σημεία μεταδεδομένων cloud, προορισμοί τηλεμετρίας) υπερισχύει όλων των επιτρεπτικών.
  • Το networkEnabled: false ξεκινά ακόμη τους proxy ανά συνεδρία, αλλά η λίστα επιτρεπομένων είναι κενή, οπότε κάθε εξερχόμενη σύνδεση απορρίπτεται. Η αποστολή το ορίζει όταν ξεκινά η εκτέλεση από τον κανόνα Πρόσβαση στο δίκτυο: η απόρριψη κλείνει το δίκτυο, η αποδοχή και η ερώτηση πρώτα το αφήνουν ανοιχτό.

Η προδιαγραφή που περνά στο SandboxPort.launch:

Πεδίο Τύπος Περιγραφή
sessionId String Σταθερό αναγνωριστικό συνεδρίας (συνήθως το id του χώρου)
workspaceId String Το id του χώρου εργασίας στον οποίο ανήκει
agentId String? Ο πράκτορας που είναι αυτή τη στιγμή δεσμευμένος στο sandbox, αν υπάρχει
bindMounts List<SandboxBindMount> Προσαρτήσεις από τον κεντρικό υπολογιστή στο φιλοξενούμενο· το sandbox βλέπει μόνο τις διαδρομές που παρατίθενται εδώ
networkEnabled bool (προεπιλογή true) Ορίζεται κατά την αποστολή από τον κανόνα εξερχόμενης δικτυακής κίνησης (ανενεργό μόνο όταν αυτός επιλύεται σε απόρριψη). Όταν είναι ανενεργό, οι proxy ανά συνεδρία ξεκινούν ακόμη, αλλά η λίστα επιτρεπομένων είναι κενή, οπότε κάθε εξερχόμενη σύνδεση απορρίπτεται
egressAllowlist List<String> (προεπιλογή []) Πρόσθετοι επιτρεπόμενοι τομείς εξερχόμενης κίνησης· υποστηρίζονται μπαλαντέρ (*.example.com, συν μια ενδιάμεση μορφή ενός επιπέδου). Η αποστολή δεν το συμπληρώνει ποτέ, οπότε μια περιτυλιγμένη εκτέλεση παίρνει το επιμελημένο βασικό σύνολο συν τους τομείς GitHub
guestWorkdir String? Προεπιλεγμένος κατάλογος εργασίας μέσα στο sandbox· μεμονωμένες κλήσεις exec μπορούν να τον παρακάμψουν
mode Mode (προεπιλογή chat) Χαράσσει τους κανόνες εγγραφής του συστήματος αρχείων: το chat διατηρεί τα bind mounts εγγράψιμα· τα review, plan και orchestrate είναι μόνο για ανάγνωση
protectedPaths List<String> (προεπιλογή []) Διαδρομές του κεντρικού υπολογιστή που δεν πρέπει ποτέ να είναι εγγράψιμες μέσα στο sandbox, σε καμία λειτουργία
runnerStateDirs List<String> (προεπιλογή []) Κατάλογοι του κεντρικού υπολογιστή όπου ο runner κρατά τη δική του κατάσταση, εγγράψιμοι σε κάθε λειτουργία (ένας CLAUDE_CONFIG_DIR υπό τη διαχείριση του Control Center είναι ο τρέχων)
execGrantRoots List<String> (προεπιλογή []) Δέντρα καταλόγων εγκεκριμένα από τον χειριστή που ανοίγουν ξανά τον αποκλεισμό exec του εγγράψιμου καταλόγου στο macOS. Το Linux τα αγνοεί — το bwrap δεν έχει αποκλεισμό exec για το $HOME που θα άνοιγε ξανά

Το protectedPaths περιέχει τα αρχικά καταχωρισμένα checkouts των αποθετηρίων, που επιλύονται ανά αποστολή από τα αποθετήρια του χώρου εργασίας. Οι πράκτορες εργάζονται αποκλειστικά σε worktrees copy-on-write ανά συνομιλία, οπότε τα πρωτότυπα δεν πρέπει ποτέ να είναι εγγράψιμα από μέσα στο sandbox — στο macOS, η καθολική επιτρεπτική εξαίρεση εγγραφής του Seatbelt για το $HOME θα τα άφηνε κατά τα άλλα εγγράψιμα μέσω bash. Εντάσσονται στο σύνολο απαγόρευσης εγγραφής των μυστικών σε κάθε λειτουργία, chat συμπεριλαμβανομένης.

Κάθε διαδρομή αποκλεισμού ανάγνωσης και εγγραφής εκπέμπεται και στην κυριολεκτική γραφή της και στη γραφή της μετά την επίλυση symlink. Ο πυρήνας αντιστοιχίζει έναν κανόνα απόρριψης με την επιλυμένη διαδρομή, οπότε ένας κανόνας γραμμένος για μια διαδρομή με symlink δεν ενεργοποιείται ποτέ — και στο macOS αυτή είναι η συνήθης περίπτωση και όχι η εξωτική, αφού το /tmp επιλύεται σε /private/tmp και το /var/folders/… σε /private/var/folders/…. Οι εγγραφές που περιέχουν * ή ? αντιμετωπίζονται ως glob και μένουν ως έχουν· μια διαδρομή που δεν επιλύεται διατηρείται όπως γράφτηκε.

Πεδίο Τύπος Περιγραφή
hostPath String Απόλυτη διαδρομή στον κεντρικό υπολογιστή
guestPath String Διαδρομή μέσα στο sandbox (με το εγγενές sandbox ισούται με το hostPath· διατηρείται για τη συμμετρία των προσαρμογέων)
readOnly bool (προεπιλογή false) Προσάρτηση μόνο για ανάγνωση όταν είναι true

Επιστρέφεται από το SandboxPort.launch:

Πεδίο Τύπος Περιγραφή
sessionId String Αναγνωριστικό συνεδρίας
backend SandboxBackend Ποιο backend εκτελείται
state SandboxState Κατάσταση κύκλου ζωής
error Object? Ορίζεται όταν το state είναι error
details Map<String, Object?> Εσωτερικά δεδομένα τήρησης του προσαρμογέα (κατάλογος εργασίας, PID, διαδρομή προφίλ κ.λπ.)
Κατάσταση Περιγραφή
created Η προδιαγραφή δημιουργήθηκε, αλλά το VM δεν έχει ξεκινήσει ακόμη
warm Εκτελείται και είναι έτοιμο να δεχτεί εντολές exec
active Εκτελεί αυτή τη στιγμή μια εντολή
suspended Σε παύση / με σημείο ελέγχου στον δίσκο για εξοικονόμηση RAM
destroyed Καταστράφηκε· η λαβή δεν είναι πλέον έγκυρη
error Η εκκίνηση απέτυχε — δείτε το SandboxHandle.error
Τύπος γεγονότος Περιγραφή
stdout Τυπική έξοδος από το sandbox
stderr Τυπικό σφάλμα από το sandbox
exit Η διεργασία του sandbox τερματίστηκε (φέρει exitCode)
starting Το sandbox ξεκινά
ready Το sandbox είναι έτοιμο να δεχτεί κλήσεις exec
killed Η διεργασία τερματίστηκε βίαια από τον κεντρικό υπολογιστή (OOM, χρονικό όριο, χειροκίνητη διακοπή)
violation Παραβιάστηκε μια πολιτική sandbox (φέρει ένα SandboxViolation)
Πεδίο Τύπος Περιγραφή
action String Το ρήμα που απορρίφθηκε (π.χ. file-read*, network-outbound)
target String Διαδρομή ή κεντρικός υπολογιστής που ήταν ο στόχος της απορριφθείσας λειτουργίας
raw String? Ακατέργαστη γραμμή καταγραφής, χρήσιμη για αποσφαλμάτωση