Core concepts

Sandbox + Executor + Egress

See how portable policy, bounded execution and one network enforcement engine compose per spawn.

La phrase de conception est : trois traversées de frontière, deux frontends, un moteur Egress.

CODE
client Maelys-aware ── fd 4/SCM_RIGHTS ───────────────┐
                                                      ├─► moteur Egress cible
outil standard ── HTTP/SOCKS ── relay L4 Bubblewrap ─┘

Les deux chemins terminent maintenant dans Egress. Pour fd4, le broker ne possède aucune allowlist : il traduit le datagramme vers le connecteur natif Egress et transmet au workload l’extrémité cliente du stream relayé. Egress garde le pair, observe les octets et émet le receipt. Le chemin standard reste HTTP/SOCKS de bout en bout.

Ce que fait l’adaptateur

Pour chaque spawn médié, libmaelys_executor_egress_adapter.a :

  1. crée une policy Egress privée ; le proxy AF_UNIX lie un principal immuable à l'identité de son endpoint, tandis que fd4 et le proxy TCP Seatbelt créent encore un credential explicite ;
  2. traduit exactement les destinations du plan Executor en policy Egress ;
  3. lance Egress en mode connecteur natif sans listener pour fd4, sur AF_UNIX sous Bubblewrap, Apple Container et Krun proxy, ou TCP loopback sous Seatbelt proxy ;
  4. pour fd4, crée le canal datagramme et le broker ; pour proxy, clone la request en retirant les anciennes variables proxy ;
  5. injecte les URLs proxy et vide NO_PROXY/no_proxy ;
  6. conserve le contrat EXTERNAL_CHANNEL ou MEDIATED_PROXY choisi ;
  7. attend Egress puis, sous Bubblewrap, relay-ready avant l’exec workload ;
  8. arrête workload/relay éventuel avant Egress et nettoie les ressources privées.

Le relay ne reçoit ni allowlist ni autorité. Egress reste le seul composant qui authentifie, résout, connecte, vérifie éventuellement SNI, compte les octets et émet les receipts réseau.

Isolation entre spawns

Deux spawns ont deux principals, deux sockets, deux policies et deux threads Egress. Sur AF_UNIX, aucun credential n'est transporté : l'endpoint d'une exécution ne sélectionne jamais le principal de l'autre. Egress applique en outre un quota de connexions par principal et conserve la validation du pair de même EUID comme vérification additive. Les user mounts Bubblewrap sont appliqués avant le mount réservé du pont et ne peuvent pas le masquer.

Chemin macOS Seatbelt

Seatbelt applique NETWORK_NONE, le frontend fd4 et le frontend proxy. Le proxy standard ne lance aucun relay : Egress écoute directement sur un port 127.0.0.1 aléatoire et le profil SBPL autorise seulement localhost:PORT. L’adaptateur réserve le même port sur ::1 sans listener avant d’exposer le credential, empêchant qu’un service IPv6 homonyme devienne un second canal. Les autres ports loopback et le réseau direct restent refusés.

Chemin Apple Container

Apple Container exécute le workload dans un autre noyau. Le chemin fd4 natif ne peut donc pas y transmettre un socket hôte par SCM_RIGHTS. Les candidats Apple livrent le frontend proxy standard :

CODE
workload invité
   │ HTTP_PROXY / SOCKS sur loopback privé
   ▼
relay L4 invité
   │ Containerization UDS/vsock
   ▼
Egress hôte par exécution
   │ allowlist + DNS/pinning + relay + receipt
   ▼
destination autorisée

Avec apple-container-bubblewrap, le relay reste dans la VM mais hors de la sandbox Bubblewrap intérieure. Le réseau ambiant de la VM reste absent et le workload ne peut atteindre que le loopback du relay. Voir apple-container.md et backend-capabilities.md.

Chemin Krun

Les candidats krun et krun-bubblewrap livrent le même frontend proxy à travers une microVM libkrun sans carte réseau ni TSI :

CODE
workload invité
   │ HTTP_PROXY / SOCKS sur loopback privé
   ▼
relay invité Warden épinglé
   │ AF_VSOCK, CID hôte, port 4520
   ▼
Egress hôte par exécution, listener AF_UNIX privé
   │ allowlist + DNS/SNI + quotas + receipt
   ▼
destination autorisée

Le relay invité appartient au bundle Warden scellé dans la racine ext4 ; il reste aveugle au protocole et ne reçoit ni policy de destination ni credential. Avec krun-bubblewrap, il reste hors de la sandbox Bubblewrap intérieure. Le pont AF_UNIX hôte lie un principal immuable à l'identité de son endpoint et les URLs proxy injectées ne portent aucun secret. Voir krun-driver.md et backend-capabilities.md.