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 $?
1Alternative 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 authorBetroffene Plugin-Manifest-Merkmale
Plugins, die dieses Problem aufweisen, enthalten typischerweise eines oder mehrere der folgenden Muster:
"keywords": ["child-process", "cli-wrapper", "native-binary"]inpackage.json- Direkte Importe des
child_process-Moduls (spawn,exec,execFile) - Abhängigkeiten von lokalen CLI-Tools (parcel, esbuild, swipl, usw.)
- Manifeste ohne
openclaw- odercapabilities-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
- Plugin-Registry-Abfrage: OpenClaw ruft das Plugin-Manifest aus der Registry ab
- Archiv-Extraktion: Das Plugin-Paket wird heruntergeladen und in ein temporäres Verzeichnis extrahiert
- Sicherheitsscan-Initierung: Die Klasse
SkillScannerwird instanziiert und beginnt mit der Dateitraversierung - Statische Analyse: Jede JavaScript/TypeScript-Datei wird auf gefährliche Muster untersucht
- Musterübereinstimmung - dangerous-exec: Der Scanner erkennt
require('child_process')oderimport('child_process') - Schweregradzuweisung: Dem Befund wird
CRITICAL-Schweregrad zugewiesen (fest codiert) - Richtliniendurchsetzung: Die Installationsrichtlinie gibt
blockOnCritical: truean - 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.jsonoderopenclaw.config.jsim Stammverzeichnis Ihres Pakets (bevorzugt) - Option B: Das
openclaw-Feld inpackage.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 $?
0Schritt 4: Das aktualisierte Plugin veröffentlichen
$ npm version patch
$ npm publish
npm notice
+ [email protected]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 capabilitiesErwartete Ausgabe:
{
"executesCode": true,
"reason": "Spawns native macOS Swift CLIs using EventKit..."
}
Status: ✓ Valid JSON structure
Scanner Compatibility: ✓ v2.x compatibleExit-Code: 0
Verifizierung 2: Sicherheitsscanner erzeugt informierte Zustimmung anstelle eines harten Blocks
Befehl:
$ npx openclaw plugin install apple-pim-cli 2>&1 | head -20Erwartete 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
fiVerifizierung 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 riskSicheres Muster:
const { execFile } = require('child_process');
execFile('parcel', ['build', inputPath], callback); // No shell interpolation4. 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 patternsAbhilfe: 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 timeoutAbhilfe: 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, wennchild_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 alsdangerous-exec.SCANNER_E003— eval-usage
Kritischer Befund, wenneval(),new Function()oder ähnliche Laufzeit-Code-Konstruktion erkannt wird.SCANNER_E004— network-exfiltration
Kennzeichnet, wenn Plugins Netzwerkanfragen an unbekannte Endpunkte senden. Verwandt mitdangerous-exec, da beide auf potenzielle Datenexfiltration hinweisen.SCANNER_E005— filesystem-overreach
Erkennt Dateisystemoperationen außerhalb der vorgesehenen Verzeichnisse des Plugins. Kann mitdangerous-execin 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 dasreason-Feld ein nicht-leerer String ist.TRUST_E201— consent-required
Benutzereinwilligung ist erforderlich, aber stdin ist kein TTY. Verwenden Sie das--consent-Flag oder--yeszur 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, dasapple-pim-cliund ä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 CLIsparcel-cli— Paketverfolgung über Parcel CLIprolog-agent— SWI-Prolog-Abfrageausführungrust-analyzer-wrapped— Rust-Sprachserver-Wrapperdotnet-script— .NET-Skriptausführung