Zum Inhalt

Nativer Ausfuehrungsmodus (ohne Docker/Isolation)

Andere Sprachen


Ueberblick

Symbiont unterstuetzt den Betrieb von Agenten ohne Docker oder Container-Isolation fuer Entwicklungsumgebungen oder vertrauenswuerdige Deployments, bei denen maximale Performance und minimale Abhaengigkeiten gewuenscht sind.

Sicherheitswarnungen

WICHTIG: Der native Ausfuehrungsmodus umgeht alle containerbasierten Sicherheitskontrollen:

  • Keine Prozessisolation
  • Keine Dateisystemisolation
  • Keine Netzwerkisolation
  • Keine Durchsetzung von Ressourcenlimits
  • Direkter Zugriff auf das Hostsystem

Das native-sandbox-Feature laesst sich in Release-Builds nicht kompilieren. Es ist durch ein compile_error! unter not(debug_assertions) geschuetzt, sodass ein Release-Binary niemals den nativen Runner ausliefern kann. Es ist eine Entwicklungshilfe nur fuer Debug-Builds.

NUR VERWENDEN FUER: - Lokale Entwicklung mit vertrauenswuerdigem Code - Kontrollierte Umgebungen mit vertrauenswuerdigen Agenten - Testen und Debuggen - Umgebungen, in denen Docker nicht verfuegbar ist

NICHT VERWENDEN FUER: - Produktionsumgebungen mit nicht vertrauenswuerdigem Code - Mandantenfaehige Deployments - Oeffentlich zugaengliche Dienste - Verarbeitung nicht vertrauenswuerdiger Benutzereingaben

Architektur

Sandbox-Stufenhierarchie

┌─────────────────────────────────────────┐
│ SecurityTier::None (Native Execution)   │ ← Keine Isolation
├─────────────────────────────────────────┤
│ SecurityTier::Tier1 (Docker)            │ ← Container-Isolation
├─────────────────────────────────────────┤
│ SecurityTier::Tier2 (gVisor)            │ ← Erweiterte Isolation
├─────────────────────────────────────────┤
│ SecurityTier::Tier3 (Firecracker)       │ ← Maximale Isolation
└─────────────────────────────────────────┘

Nativer Ausfuehrungsablauf

graph LR
    A[Agent Request] --> B{Security Tier?}
    B -->|None| C[Native Process Runner]
    B -->|Tier1+| D[Sandbox Orchestrator]

    C --> E[Direct Process Execution]
    E --> F[Host System]

    D --> G[Docker/gVisor/Firecracker]
    G --> H[Isolated Environment]

Konfiguration

Option 1: TOML-Konfiguration

# symbiont.toml

[security]
# Native Ausfuehrung erlauben (Standard: false)
allow_native_execution = true

# Native Ausfuehrung ist ein eigener Top-Level-Abschnitt (nicht unter [security] verschachtelt).
[native_execution]
enabled = true
default_executable = "python3"
working_directory = "/tmp/symbiont-native"
# OS-Ressourcenlimits auch im nativen Modus anwenden
enforce_resource_limits = true
max_memory_mb = 2048              # Option<u64>
max_cpu_seconds = 300             # Option<u64> -- CPU-Zeit, keine Kernanzahl
max_execution_time_seconds = 300  # Echtzeit-Timeout
allowed_executables = ["python3", "node", "bash"]

Vollstaendiges Konfigurationsbeispiel

Eine vollstaendige config.toml mit nativer Ausfuehrung neben anderen Systemeinstellungen:

# config.toml
[api]
port = 8080
host = "127.0.0.1"
timeout_seconds = 30
max_body_size = 10485760

[database]
# Embedding-Vektordimension. LanceDB (das standardmaessige eingebettete Backend)
# benoetigt keine weitere Konfiguration. Das Backend wird zur Build-Zeit ueber das
# Cargo-Feature `vector-lancedb` (Standard) oder `vector-qdrant` ausgewaehlt -- es
# gibt keinen `vector_backend`-Konfigurationsschluessel; verwende die
# Umgebungsvariable SYMBIONT_VECTOR_BACKEND, um zur Laufzeit zu wechseln.
vector_dimension = 384

# Wird beim Betrieb mit dem Qdrant-Backend verwendet (SYMBIONT_VECTOR_BACKEND=qdrant):
# qdrant_url = "http://localhost:6333"
# qdrant_collection = "symbiont"

[logging]
level = "info"
format = "Pretty"
structured = true

[security]
key_provider = { Environment = { var_name = "SYMBIONT_KEY" } }
enable_compression = true
enable_backups = true
enable_safety_checks = true

[storage]
context_path = "./data/context"
git_clone_path = "./data/git"
backup_path = "./data/backups"
max_context_size_mb = 1024

[native_execution]
enabled = true
default_executable = "python3"
working_directory = "/tmp/symbiont-native"
enforce_resource_limits = true
max_memory_mb = 2048
max_cpu_seconds = 300
max_execution_time_seconds = 300
allowed_executables = ["python3", "python", "node", "bash", "sh"]

NativeExecutionConfig-Felder

Feld Typ Standard Beschreibung
enabled bool false Nativen Ausfuehrungsmodus aktivieren
default_executable string "bash" Standard-Interpreter/Shell
working_directory path /tmp/symbiont-native Ausfuehrungsverzeichnis
enforce_resource_limits bool true OS-Level-Limits anwenden
max_memory_mb Option Some(2048) Speicherlimit in MB
max_cpu_seconds Option Some(300) CPU-Zeitlimit
max_execution_time_seconds u64 300 Echtzeit-Timeout
allowed_executables Vec [bash, python3, etc.] Whitelist ausfuehrbarer Dateien

Option 2: Laufzeit-Sicherheitsvorkehrungen (Umgebung)

Es gibt keine SYMBIONT_NATIVE_* / SYMBIONT_ALLOW_NATIVE_EXECUTION / SYMBIONT_DEFAULT_SANDBOX_TIER Einstellungen -- native Ausfuehrung wird ueber den oben gezeigten [native_execution]-Konfigurationsabschnitt konfiguriert. Die einzigen nativ-bezogenen Umgebungsvariablen sind die beiden Laufzeit-Sicherheitsvorkehrungen, die beide gesetzt sein muessen, um den nativen (isolationsfreien) Runner tatsaechlich auszufuehren:

export SYMBI_UNSAFE_NATIVE_SANDBOX=1   # acknowledge the native runner
export SYMBIONT_ALLOW_UNISOLATED=1     # permit SandboxTier::None

Option 3: Konfiguration auf Agentenebene

metadata {
  version = "1.0.0"
  description = "Local Development Agent"
}

agent native_worker(task: String) -> String {
  capabilities = ["local_filesystem", "network"]

  policy dev_only {
    allow: ["local_filesystem", "network"] if true
  }

  # tier 0 = keine Sandbox (Host-Ausfuehrung); erfordert die oben genannten Opt-ins
  with sandbox = "none" {
    return process(task);
  }
}

Anwendungsbeispiele

Beispiel 1: Entwicklungsmodus

use symbi_runtime::{Config, SecurityTier, SandboxOrchestrator};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Native Ausfuehrung fuer Entwicklung aktivieren
    let mut config = Config::default();
    config.security.allow_native_execution = true;

    let orchestrator = SandboxOrchestrator::new(config)?;

    // Code nativ ausfuehren
    let result = orchestrator.execute_code(
        SecurityTier::None,
        "print('Hello from native execution!')",
        HashMap::new()
    ).await?;

    println!("Output: {}", result.stdout);
    Ok(())
}

Beispiel 2: Bauen und Ausfuehren mit dem nativen Runner

Es gibt kein --native-CLI-Flag. Native (Host-)Ausfuehrung erfordert drei explizite Opt-ins:

  1. Mit dem native-sandbox-Feature bauen -- nur Debug-Builds. Das Feature bietet keinerlei Isolation und ist durch ein compile_error! in Release-Builds geschuetzt:
cargo build --features native-sandbox    # nur Debug; Release laesst sich nicht kompilieren
  1. Beide Laufzeit-Schutzmechanismen bestaetigen:
export SYMBI_UNSAFE_NATIVE_SANDBOX=1   # den nativen Runner bestaetigen
export SYMBIONT_ALLOW_UNISOLATED=1     # SandboxTier::None in Nicht-Dev-Laeufen erlauben
  1. Stufe 0 (keine Sandbox) im Agenten-DSL waehlen:
with sandbox = "none" {
    // ...
}

Ressourcenlimits (Speicher/CPU/Timeout) stammen aus dem with-Block / der Konfiguration (siehe oben), nicht aus CLI-Flags.

Dann normal ausfuehren:

symbi run agent.symbi

Beispiel 3: Gemischte Ausfuehrung

// Native Ausfuehrung fuer vertrauenswuerdige lokale Operationen
let local_result = orchestrator.execute_code(
    SecurityTier::None,
    local_code,
    env_vars
).await?;

// Docker fuer externe/nicht vertrauenswuerdige Operationen
let isolated_result = orchestrator.execute_code(
    SecurityTier::Tier1,
    untrusted_code,
    env_vars
).await?;

Implementierungsdetails

Native Process Runner

Der native Runner verwendet std::process::Command mit optionalen Ressourcenlimits:

pub struct NativeRunner {
    config: NativeConfig,
}

impl NativeRunner {
    pub async fn execute(&self, code: &str, env: HashMap<String, String>)
        -> Result<ExecutionResult> {
        // Direkte Prozessausfuehrung
        let mut command = Command::new(&self.config.executable);
        command.current_dir(&self.config.working_dir);
        command.envs(env);

        // Optional: Ressourcenlimits ueber rlimit anwenden (Unix)
        #[cfg(unix)]
        if self.config.enforce_limits {
            self.apply_resource_limits(&mut command)?;
        }

        let output = command.output().await?;

        Ok(ExecutionResult {
            stdout: String::from_utf8_lossy(&output.stdout).to_string(),
            stderr: String::from_utf8_lossy(&output.stderr).to_string(),
            exit_code: output.status.code().unwrap_or(-1),
            success: output.status.success(),
        })
    }
}

Ressourcenlimits (Unix)

Auf Unix-Systemen kann die native Ausfuehrung dennoch einige Limits durchsetzen:

  • Speicher: Mit setrlimit(RLIMIT_AS)
  • CPU-Zeit: Mit setrlimit(RLIMIT_CPU)
  • Prozessanzahl: Mit setrlimit(RLIMIT_NPROC)
  • Dateigroesse: Mit setrlimit(RLIMIT_FSIZE)

Plattformunterstuetzung

Plattform Native Ausfuehrung Ressourcenlimits
Linux Vollstaendig rlimit
macOS Vollstaendig Teilweise
Windows Vollstaendig Eingeschraenkt

Migration von Docker

Schritt 1: Konfiguration aktualisieren

# symbiont.toml
[security]
+ allow_native_execution = true

+ [native_execution]
+ enabled = true

Waehlen Sie anschliessend Tier 0 (kein Sandbox) pro Agent in der DSL:

with sandbox = "none" { ... }

Schritt 2: Erstellen und ausfuehren (nur Debug)

# Nicht mehr erforderlich
# docker build -t symbi:latest .
# docker run ...

# Das Feature native-sandbox ist nur fuer Debug-Builds (compile_error! in Release-Builds):
cargo build --features native-sandbox
SYMBI_UNSAFE_NATIVE_SANDBOX=1 SYMBIONT_ALLOW_UNISOLATED=1 \
  ./target/debug/symbi run agent.symbi

Hybridansatz

Verwenden Sie beide Ausfuehrungsmodi strategisch -- nativ fuer vertrauenswuerdige lokale Operationen, Docker fuer nicht vertrauenswuerdigen Code:

// Vertrauenswuerdige lokale Operationen
let local_result = orchestrator.execute_code(
    SecurityTier::None,  // Nativ
    trusted_code,
    env
).await?;

// Externe/nicht vertrauenswuerdige Operationen
let isolated_result = orchestrator.execute_code(
    SecurityTier::Tier1,  // Docker
    external_code,
    env
).await?;

Schritt 3: Umgebungsvariablen verwalten

Docker hat Umgebungsvariablen automatisch isoliert. Bei nativer Ausfuehrung muessen sie explizit gesetzt werden:

export AGENT_API_KEY="xxx"
export AGENT_DB_URL="postgresql://..."
export SYMBI_UNSAFE_NATIVE_SANDBOX=1
export SYMBIONT_ALLOW_UNISOLATED=1
symbi run agent.symbi   # Agent muss deklarieren: with sandbox = "none" { ... }

Performance-Vergleich

Modus Startzeit Durchsatz Speicher Isolation
Nativ ~10ms 100% Minimal Keine
Docker ~500ms ~95% +128MB Gut
gVisor ~800ms ~70% +256MB Besser
Firecracker ~125ms ~90% +64MB Am besten

Fehlerbehebung

Problem: Zugriff verweigert

# Loesung: Sicherstellen, dass das Arbeitsverzeichnis beschreibbar ist
mkdir -p /tmp/symbiont-native
chmod 755 /tmp/symbiont-native

Problem: Befehl nicht gefunden

# Loesung: Sicherstellen, dass die ausfuehrbare Datei im PATH ist oder absoluten Pfad verwenden
export PATH=$PATH:/usr/local/bin
# Oder absoluten Pfad konfigurieren
allowed_executables = ["/usr/bin/python3", "/usr/bin/node"]

Problem: Ressourcenlimits werden nicht angewendet

Native Ausfuehrung unter Windows hat eingeschraenkte Unterstuetzung fuer Ressourcenlimits. Erwaegen Sie: - Verwendung von Job Objects (Windows-spezifisch) - Ueberwachung und Beendigung ausser Kontrolle geratener Prozesse - Upgrade auf containerbasierte Ausfuehrung

Bewaeehrte Praktiken

  1. Nur fuer Entwicklung: Native Ausfuehrung primaer fuer die Entwicklung verwenden
  2. Schrittweise Migration: Mit Containern beginnen, bei Stabilitaet zu nativ wechseln
  3. Ueberwachung: Auch ohne Isolation die Ressourcennutzung ueberwachen
  4. Whitelists: Erlaubte ausfuehrbare Dateien und Pfade einschraenken
  5. Protokollierung: Umfassende Audit-Protokollierung aktivieren
  6. Testen: Vor dem nativen Deployment mit Containern testen

Sicherheitscheckliste

Vor der Aktivierung nativer Ausfuehrung in jeder Umgebung:

  • Gesamter Agentencode stammt aus vertrauenswuerdigen Quellen
  • Umgebung ist von der Produktion isoliert
  • Keine externen Benutzereingaben werden verarbeitet
  • Ueberwachung und Protokollierung sind aktiviert
  • Ressourcenlimits sind konfiguriert
  • Whitelist fuer ausfuehrbare Dateien ist restriktiv
  • Dateisystemzugriff ist eingeschraenkt
  • Team versteht die Sicherheitsimplikationen

Verwandte Dokumentation


Hinweis: Die native Ausfuehrung tauscht Sicherheit gegen Komfort. Verstehen Sie immer die Risiken und wenden Sie geeignete Kontrollen fuer Ihre Deployment-Umgebung an.