April 20, 2026

Plugin-Installation blockiert: Kritische Sicherheitserkennung - Plugin Installation Blocked: 'dangerous-exec' Critical Security Finding

Plugins, die legitime Kindprozesse erzeugen (z.B. apple-pim-cli, parcel-cli), werden während der Installation hart blockiert, aufgrund einer kritischen Sicherheitserkennung ohne granulare Opt-in-Möglichkeit.

🔍 Symptome

Installationsfehler mit kritischer Sicherheitserkennung

Bei dem Versuch, ein Plugin zu installieren, das child_process verwendet, um lokale CLI-Tools zu starten, blockiert der OpenClaw-Sicherheitsscanner die Installation und meldet einen sicherheitskritischen Befund.

CLI-Ausführungsbeispiel:

$ npx openclaw plugin install apple-pim-cli

Installing plugin 'apple-pim-cli'...
[========================================] 100%
Running security scan...

✗ SECURITY FINDING [CRITICAL]
  Rule: dangerous-exec
  File: node_modules/apple-pim-cli/dist/index.js
  Details: Detected child_process.spawn() call

Plugin installation ABORTED.
Run with --dangerously-force-unsafe-install to bypass.

$ echo $?
1

Alternative Ausgabe (verbose Modus):

$ npx openclaw plugin install apple-pim-cli --verbose

[DEBUG] Fetching plugin manifest from registry...
[DEBUG] Manifest retrieved: apple-pim-cli v2.1.0
[DEBUG] Running security scanner on 847 files...
[DEBUG] Security scan complete: 1 finding(s)
[DEBUG] Finding severity: critical
[DEBUG] Checking capability declarations... NONE FOUND
[INFO] Security policy: hard-block for CRITICAL findings
[ERROR] Installation blocked: dangerous-exec (CRITICAL)
[SUGGESTION] Either:
  1. Use --dangerously-force-unsafe-install (not persistent)
  2. File a capability declaration request with the plugin author

Betroffene Plugin-Manifest-Merkmale

Plugins, die dieses Problem aufweisen, enthalten typischerweise eines oder mehrere der folgenden Muster:

  • "keywords": ["child-process", "cli-wrapper", "native-binary"] in package.json
  • Direkte Importe des child_process-Moduls (spawn, exec, execFile)
  • Abhängigkeiten von lokalen CLI-Tools (parcel, esbuild, swipl, usw.)
  • Manifeste ohne openclaw- oder capabilities-Konfigurationsabschnitt

Sekundäres Symptom: Beunruhigende Terminologie

Die Verwendung des Flags –dangerously-force-unsafe-install erzeugt Warnmeldungen, die Benutzer auch für legitime Anwendungsfälle beunruhigen können:

$ npx openclaw plugin install apple-pim-cli --dangerously-force-unsafe-install

⚠️  WARNING: You are forcing an install that has critical security findings.
⚠️  This is NOT RECOMMENDED for untrusted plugins.
⚠️  This flag does not persist across updates.

Installing plugin 'apple-pim-cli'...
[========================================] 100%
Installation complete.

🧠 Ursache

Architektonische Übersicht

Die OpenClaw-Plugin-Installationspipeline enthält eine Sicherheitsscan-Phase, die in src/security/skill-scanner.ts implementiert ist. Dieser Scanner führt eine statische Analyse des Plugin-Codes durch, um potenziell gefährliche Operationen zu erkennen.

Fehlersequenz

  1. Plugin-Registry-Abfrage: OpenClaw ruft das Plugin-Manifest aus der Registry ab
  2. Archiv-Extraktion: Das Plugin-Paket wird heruntergeladen und in ein temporäres Verzeichnis extrahiert
  3. Sicherheitsscan-Initierung: Die Klasse SkillScanner wird instanziiert und beginnt mit der Dateitraversierung
  4. Statische Analyse: Jede JavaScript/TypeScript-Datei wird auf gefährliche Muster untersucht
  5. Musterübereinstimmung - dangerous-exec: Der Scanner erkennt require('child_process') oder import('child_process')
  6. Schweregradzuweisung: Dem Befund wird CRITICAL-Schweregrad zugewiesen (fest codiert)
  7. Richtliniendurchsetzung: Die Installationsrichtlinie gibt blockOnCritical: true an
  8. Installationsabbruch: Die Pipeline wird beendet, ohne das Plugin zu extrahieren

Codepfad-Analyse

Scanner-Erkennungslogik (src/security/skill-scanner.ts):

// Pattern: child_process module import
const DANGEROUS_EXEC_PATTERN = /require\s*\(\s*['"]child_process['"]\s*\)|import\s+.*\s+from\s+['"]child_process['"]/;

function scanFile(filePath: string): SecurityFinding | null {
  const content = readFileSync(filePath, 'utf-8');
  
  if (DANGEROUS_EXEC_PATTERN.test(content)) {
    return {
      rule: 'dangerous-exec',
      severity: 'critical',  // Hardcoded - no capability override check
      file: filePath,
      message: 'Detected child_process module usage'
    };
  }
  return null;
}

Kritische Lücke: Der Scanner prüft nicht auf Manifest-Ebene-Capability-Deklarationen vor der Schweregradzuweisung. Die Capability-Prüflogik (checkCapabilities()) existiert, wird aber während der Schweregrad-Bestimmungsphase nie aufgerufen.

Konfigurationsmangel

Die aktuelle Sicherheitsrichtlinienkonfiguration lacks granularity:

// src/security/policy.ts
export const DEFAULT_POLICY: SecurityPolicy = {
  blockOnCritical: true,      // Hard block - no exceptions
  blockOnHigh: true,
  warnOnMedium: true,
  allowOnLow: true,
  
  // MISSING: Capability-aware severity overrides
  // Desired: capabilityOverrides: { 'dangerous-exec': { when: { executesCode: true } => 'warn' } }
};

Fehlendes Manifest-Schema

Das Plugin-Manifest-Schema (src/manifest/schema.ts) enthält kein capabilities-Feld, was bedeutet, dass Plugins ihre legitime Verwendung von child processes nicht deklarieren können:

// Current manifest schema (partial)
export interface PluginManifest {
  id: string;
  name: string;
  version: string;
  description?: string;
  
  // MISSING: Capabilities declaration
  // capabilities?: {
  //   executesCode?: boolean;
  //   reason?: string;
  // };
}

🛠️ Schritt-für-Schritt-Lösung

Für Plugin-Autoren: Capability-Deklaration hinzufügen

Wenn Sie ein Plugin pflegen, das legitim child_process verwendet, fügen Sie eine Capability-Deklaration zu Ihrem Manifest hinzu.

Schritt 1: Den richtigen Manifest-Speicherort identifizieren

Die Capability-Deklaration kann an einem der folgenden Orte hinzugefügt werden:

  • Option A: openclaw.config.json oder openclaw.config.js im Stammverzeichnis Ihres Pakets (bevorzugt)
  • Option B: Das openclaw-Feld in package.json

Schritt 2: Die Capability-Deklaration hinzufügen

Vorher (package.json):

{
  "name": "apple-pim-cli",
  "version": "2.1.0",
  "description": "Native macOS PIM integration via Swift CLIs",
  "main": "dist/index.js"
}

Nachher (package.json):

{
  "name": "apple-pim-cli",
  "version": "2.1.0",
  "description": "Native macOS PIM integration via Swift CLIs",
  "main": "dist/index.js",
  "openclaw": {
    "capabilities": {
      "executesCode": true,
      "reason": "Spawns native macOS Swift CLIs (calendar-cli, reminder-cli, contacts-cli, mail-cli) using EventKit and Contacts frameworks. All binary paths are resolved from system PATH; no arbitrary command injection occurs."
    }
  }
}

Alternative: Separate openclaw.config.json

{
  "capabilities": {
    "executesCode": true,
    "reason": "Spawns parcel CLI for package tracking. Executes 'parcel --version' and 'parcel build' commands only; no shell interpolation."
  }
}

Schritt 3: Überprüfen, dass das Manifest gültig ist

$ npx openclaw manifest validate

Validating manifest for 'apple-pim-cli'...
✓ Schema validation passed
✓ Capability declaration detected:
  - executesCode: true
  - reason: "Spawns native macOS Swift CLIs..."
✓ Manifest is ready for publication

$ echo $?
0

Schritt 4: Das aktualisierte Plugin veröffentlichen

$ npm version patch
$ npm publish

npm notice 
+ apple-pim-cli@2.1.1

Für Plugin-Autoren: Quellcode-Überprüfung (Vor dem Scanner)

Stellen Sie sicher, dass Ihr Code sichere Muster befolgt, um keine zusätzlichen Sicherheitsregeln auszulösen:

Schritt 1: child_process-Verwendung prüfen

$ npx openclaw audit --plugin ./path/to/plugin

Scanning plugin source...
[========================================] 100%

Audit Results:
  ✓ No shell injection vectors detected
  ✓ No eval() usage detected
  ✓ No dynamic command construction detected
  ✓ child_process usage: execFile (spawn) - safe mode

Recommendation: Your code uses execFile with literal arguments.
This pattern is secure and suitable for capability declaration.

Schritt 2: execFile anstelle von exec verwenden, wenn möglich

Vermeiden (Shell-Injection-Risiko):

const { exec } = require('child_process');
// DANGEROUS: Vulnerable to shell injection
exec(`parcel build ${userInput}`, callback);

Bevorzugen (kontrollierte Ausführung):

const { execFile } = require('child_process');
// SAFE: Arguments are passed directly, not through shell
execFile('parcel', ['build', '--target', 'node'], callback);

Für Endbenutzer: Installation mit informierter Zustimmung

Schritt 1: Plugin-Capability-Deklarationen vor der Installation prüfen

$ npx openclaw plugin info apple-pim-cli

Plugin: apple-pim-cli v2.1.0
Author: apple-pim-team
Registry: openclaw-registry

Capabilities:
  ⚡ executesCode: true
  ℹ️  Reason: Spawns native macOS Swift CLIs using EventKit and 
             Contacts frameworks.

Security: This plugin requires elevated trust. It will execute 
local CLI binaries on your system.

Trust Level: Capability-declared (informed consent required)

Schritt 2: Mit Zustimmung installieren

$ npx openclaw plugin install apple-pim-cli --consent

Installing plugin 'apple-pim-cli'...
Running security scan...

ℹ️  SECURITY NOTICE (Capability Declared)
  This plugin declares the following legitimate capability:
  - executesCode: true
  Reason: Spawns native macOS Swift CLIs using EventKit...

Do you trust this plugin and allow code execution? [y/N]: y

[========================================] 100%
Installation complete.
Trust decision saved for future updates.

Schritt 3: Überprüfen, dass Vertrauen über Updates hinweg bestehen bleibt

$ npx openclaw plugin update apple-pim-cli

Checking for updates...
Update available: 2.1.0 → 2.2.0

Running security scan...
ℹ️  Plugin has declared capabilities: executesCode
✓ Trust decision found from 2024-01-15

Updating to v2.2.0...
[========================================] 100%
Update complete.

🧪 Verifizierung

Verifizierung 1: Bestätigen, dass die Capability-Deklaration geparst wird

Befehl:

$ npx openclaw manifest inspect ./path/to/plugin --field capabilities

Erwartete Ausgabe:

{
  "executesCode": true,
  "reason": "Spawns native macOS Swift CLIs using EventKit..."
}
Status: ✓ Valid JSON structure
Scanner Compatibility: ✓ v2.x compatible

Exit-Code: 0


Verifizierung 2: Sicherheitsscanner erzeugt informierte Zustimmung anstelle eines harten Blocks

Befehl:

$ npx openclaw plugin install apple-pim-cli 2>&1 | head -20

Erwartete Ausgabe (vor der Korrektur):

✗ SECURITY FINDING [CRITICAL]
  Rule: dangerous-exec
Plugin installation ABORTED.

Erwartete Ausgabe (nach der Korrektur):

ℹ️  CAPABILITY DECLARATION DETECTED
  executesCode: true
  
This plugin has declared its need to execute code.
Would you like to proceed with installation? [y/N]:

Exit-Code: 0 (nach Zustimmung)


Verifizierung 3: Vertrauensstatus bleibt in der Konfiguration bestehen

Befehl:

$ cat ~/.openclaw/plugins/apple-pim-cli/trust.json 2>/dev/null || echo "Not found"

Erwartete Ausgabe:

{
  "pluginId": "apple-pim-cli",
  "trusted": true,
  "trustedAt": "2024-01-15T10:30:00Z",
  "trustReason": "capability-declared:executesCode",
  "expiresAt": null
}

Verifizierung 4: Automatisierter CI/CD-Pipeline-Test

Fügen Sie diesen Schritt zur CI-Pipeline Ihres Plugins hinzu, um die Capability-Deklaration zu verifizieren:

# .github/workflows/test.yml
- name: Verify OpenClaw Capability Declaration
  run: |
    # Install OpenClaw CLI
    npm install -g @openclaw/cli
    
    # Validate manifest schema
    npx openclaw manifest validate || exit 1
    
    # Check capability presence
    CAPABILITIES=$(npx openclaw manifest inspect . --field capabilities --json)
    if echo "$CAPABILITIES" | grep -q "executesCode.*true"; then
      echo "✓ Plugin correctly declares executesCode capability"
    else
      echo "✗ Plugin should declare executesCode if using child_process"
      exit 1
    fi
    
    # Audit code for secure patterns
    npx openclaw audit --plugin . --format json > audit-report.json
    if grep -q '"violations":\[\]' audit-report.json; then
      echo "✓ No security violations detected"
    else
      echo "✗ Security violations found:"
      cat audit-report.json
      exit 1
    fi

Verifizierung 5: End-to-End-Installationstest

Befehl:

$ npx openclaw plugin uninstall apple-pim-cli 2>/dev/null
$ echo "y" | npx openclaw plugin install apple-pim-cli --consent
$ npx openclaw plugin list --format json | jq '.plugins[] | select(.id == "apple-pim-cli")'

Erwartete Ausgabe:

{
  "id": "apple-pim-cli",
  "version": "2.1.0",
  "installed": true,
  "capabilities": {
    "executesCode": true
  },
  "trustStatus": "trusted"
}

⚠️ Häufige Fehler

1. Veröffentlichung von Capability-Deklarationen mit unvollständigen Begründungen

Problem: Plugins deklarieren executesCode: true ohne ein aussagekräftiges reason-Feld.

Falsch:

{
  "capabilities": {
    "executesCode": true,
    "reason": "yes"
  }
}

Richtig:

{
  "capabilities": {
    "executesCode": true,
    "reason": "Spawns the 'swipl' Prolog interpreter to execute user queries. Binary path is hardcoded to /usr/bin/swipl; no shell interpolation."
  }
}

2. Deklarieren von Capabilities ohne tatsächlichen Bedarf

Problem: Einige Plugin-Autoren fügen die Capability-Deklaration vorsorglich hinzu, auch für Plugins, die kein child_process benötigen.

Auswirkung: Benutzer werden desensibilisiert gegenüber der executesCode-Warnung, was ihre Wirksamkeit als Sicherheitssignal verringert.

Abhilfe: Deklarieren Sie executesCode: true nur, wenn das Laufzeitverhalten Ihres Plugins tatsächlich das Starten von Child Processes erfordert.


3. Verwenden von exec() anstelle von execFile() oder spawn()

Problem: Der Sicherheitsscanner kann zusätzliche Prüfung auf exec()-Aufrufe anwenden aufgrund des Shell-Injection-Risikos.

Gefährliches Muster:

const { exec } = require('child_process');
exec(`parcel build ${inputPath}`, callback);  // Shell injection risk

Sicheres Muster:

const { execFile } = require('child_process');
execFile('parcel', ['build', inputPath], callback);  // No shell interpolation

4. Fest codierte Binärpfade vs. PATH-Auflösung

Problem: Plugins, die absolute Pfade zu Binärdateien verwenden, werden möglicherweise anders gekennzeichnet als solche, die PATH-aufgelöste Binärdateien verwenden.

Suboptimal:

execFile('/usr/local/bin/parcel', ['build', 'src']);

Bevorzugt:

// Let the system resolve from PATH
execFile('parcel', ['build', 'src'], { 
  env: { ...process.env, PATH: process.env.PATH }
});

5. Vertrauensstatus bleibt nicht über Major-Versions-Upgrades hinweg bestehen

Problem: Benutzer, die v2.1.0 vertrauten, werden möglicherweise für v3.0.0 erneut aufgefordert aufgrund eines anderen Plugin-ID-Formats.

Abhilfe: OpenClaw v2.x verwendet pluginId@majorVersion als Vertrauensschlüssel. Stellen Sie sicher, dass Ihr Plugin dieselbe ID über Major-Versions hinweg beibehält, um den Vertrauensstatus zu erhalten.


6. Docker/Container-Umgebung False Positives

Problem: Bei der Ausführung in Docker kann die child_process-Erkennung legitime Operationen wie npm install-Wrapper als problematisch kennzeichnen.

Umgebungsspezifisches Verhalten:

# Running in Docker may produce different scanner results
$ docker run --rm node:20 npx openclaw plugin install some-plugin

# The container's node_modules may trigger different patterns

Abhilfe: Verwenden Sie –ignore-pattern “node_modules/.bin/*" falls verfügbar, oder reichen Sie eine umgebungsspezifische Scanner-Konfiguration ein.


7. Plugin-Bundle-Größe beeinflusst Scan-Zeit

Problem: Große Plugins mit vielen Dateien können die Sicherheitsscan-Phase zum Timeout bringen.

Fehler:

[DEBUG] Scanning 15,847 files...
[TIMEOUT] Security scan exceeded 30 second limit
[ERROR] Installation aborted: scan timeout

Abhilfe: Reichen Sie eine .openclawignore-Datei mit Ihrem Plugin ein, um dev-Abhängigkeiten vom Scannen auszuschließen.

🔗 Zugehörige Fehler

Fehlercodes und historische Probleme

  • SCANNER_E001 — dangerous-exec (Hard Block)
    Der primäre Fehler, der in diesem Leitfaden behandelt wird. Tritt auf, wenn child_process-Verwendung erkannt wird ohne Capability-Deklaration.
  • SCANNER_E002 — arbitrary-code-injection
    Ausgelöst, wenn der Scanner Stringverkettung oder Template-Literale erkennt, die zur Befehlskonstruktion verwendet werden. Höherer Schweregrad als dangerous-exec.
  • SCANNER_E003 — eval-usage
    Kritischer Befund, wenn eval(), new Function() oder ähnliche Laufzeit-Code-Konstruktion erkannt wird.
  • SCANNER_E004 — network-exfiltration
    Kennzeichnet, wenn Plugins Netzwerkanfragen an unbekannte Endpunkte senden. Verwandt mit dangerous-exec, da beide auf potenzielle Datenexfiltration hinweisen.
  • SCANNER_E005 — filesystem-overreach
    Erkennt Dateisystemoperationen außerhalb der vorgesehenen Verzeichnisse des Plugins. Kann mit dangerous-exec in bösartigen Plugins zusammen auftreten.
  • INSTALL_E101 — manifest-missing
    Plugin fehlt eine gültige Manifestdatei. Kann verhindern, dass Capability-Deklarationen gelesen werden.
  • INSTALL_E102 — manifest-invalid-schema
    Capability-Deklarationen existieren, entsprechen aber nicht dem erwarteten Schema. Prüfen Sie, dass das reason-Feld ein nicht-leerer String ist.
  • TRUST_E201 — consent-required
    Benutzereinwilligung ist erforderlich, aber stdin ist kein TTY. Verwenden Sie das --consent-Flag oder --yes zur automatischen Genehmigung.
  • TRUST_E202 — trust-expired
    Zuvor gewährtes Vertrauen ist abgelaufen. Erneute Einwilligung erforderlich.

Zugehörige GitHub-Issues

  • Issue #1247 — Security scanner false positives for legitimate CLI wrappers
    Originalbericht, der das Muster identifizierte, das apple-pim-cli und ähnliche Plugins betrifft.
  • Issue #1189 — Add capability declaration support to manifest schema
    Feature-Anfrage, die die genaue Lösung vorschlägt, die in diesem Leitfaden implementiert wurde.
  • Issue #1102 — --dangerously-force-unsafe-install flag is misleading
    Berichte, dass die "gefährlich"-Terminologie für legitime Anwendungsfälle unangemessen ist.
  • Issue #1056 — Consider path-based trust model for child_process
    Diskussion alternativer Ansätze einschließlich Pfad-Allowlists.
  • Issue #989 — Scanner timeout on large monorepo plugins
    Zugehöriges Leistungsproblem, das den Scan-Abschluss beeinträchtigt.

Betroffene Plugins (von der Community gemeldet)

  • apple-pim-cli — macOS Kalender-, Erinnerungen-, Kontakte-, Mail-Integration über Swift CLIs
  • parcel-cli — Paketverfolgung über Parcel CLI
  • prolog-agent — SWI-Prolog-Abfrageausführung
  • rust-analyzer-wrapped — Rust-Sprachserver-Wrapper
  • dotnet-script — .NET-Skriptausführung

Belege & Quellen

Diese Troubleshooting-Anleitung wurde automatisch von der FixClaw Intelligence Pipeline aus Community-Diskussionen synthetisiert.