[dangerous-exec の重大セキュリティ問題によりプラグインインストールがブロック] - Plugin Installation Blocked: 'dangerous-exec' Critical Security Finding
子プロセスを正常に生成する正当なプラグイン(例:apple-pim-cli、parcel-cli)は、細かなオプトインメカニズムがない重大セキュリティ問題により、インストール中にハードブロックされています。
🔍 症状
重要なセキュリティ検出結果によるインストール失敗
child_processを使用してローカルCLIツールを起動するプラグインのインストールを試みるとき、OpenClawセキュリティスキャナーがインストールをブロックし、重大レベル(critical)のセキュリティ検出結果を出力します。
CLI実行例:
$ 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代替出力(詳細モード):
$ 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影響を受けるプラグインのマニフェストの特徴
この問題が発生するプラグインには、通常、以下のパターンが1つ以上含まれています:
package.json内の"keywords": ["child-process", "cli-wrapper", "native-binary"]child_processモジュールの直接インポート(spawn、exec、execFile)- ローカルCLIツールへの依存(parcel、esbuild、swiplなど)
openclawまたはcapabilities設定セクションがないマニフェスト
副次的症状: 気になる用語遣い
–dangerously-force-unsafe-installフラグを使用すると、合法的なユースケースでもユーザーに不安を与える警告メッセージが表示されます:
$ 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.🧠 原因
アーキテクチャの概要
OpenClawのプラグインインストールパイプラインには、src/security/skill-scanner.tsに実装されたセキュリティスキャンフェーズが含まれています。このスキャナーは、プラグインコードに対して潜在的に危険な操作を検出するための静的解析を実行します。
失敗のシーケンス
- プラグインレジストリの検索: OpenClawはレジストリからプラグインマニフェストを取得します
- アーカイブの展開: プラグインパッケージがダウンロードされ、一時ディレクトリに展開されます
- セキュリティスキャンの開始:
SkillScannerクラスがインスタンス化され、ファイル走査を開始します - 静的解析: 各JavaScript/TypeScriptファイルに対して危険なパターンのスキャンを行います
- パターンマッチ - dangerous-exec: スキャナーが
require('child_process')またはimport('child_process')を検出します - 重要度の割り当て: 検出結果には
CRITICAL重要度(ハードコード)が割り当てられます - ポリシーの適用: インストールポリシーでは
blockOnCritical: trueが指定されています - インストールの中止: パイプラインはプラグインを展開せずに終了します
コードパスの分析
スキャナーの検出ロジック(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;
}重要なギャップ: スキャナーは、重要度の決定フェーズ中にマニフェストレベルの capability 宣言をチェックしません。capability チェックロジック(checkCapabilities())は存在しますが、重要度の決定フェーズでは呼び出されません。
設定の不備
現在のセキュリティポリシー設定には細かさがありません:
// 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' } }
};マニフェストスキーマの欠如
プラグインマニフェストスキーマ(src/manifest/schema.ts)にはcapabilitiesフィールドが含まれておらず、プラグインが child_process の合法的な使用を宣言できません:
// Current manifest schema (partial)
export interface PluginManifest {
id: string;
name: string;
version: string;
description?: string;
// MISSING: Capabilities declaration
// capabilities?: {
// executesCode?: boolean;
// reason?: string;
// };
}🛠️ 解決手順
プラグイン作者向け: Capability宣言の追加
child_processを合法的に使用するプラグインを管理している場合、マニフェストにcapability宣言を追加してください。
手順1: 正しいマニフェストの場所を確認する
capability宣言は以下に追加できます:
- オプションA: パッケージルート内の
openclaw.config.jsonまたはopenclaw.config.js(推奨) - オプションB:
package.json内のopenclawフィールド
手順2: capability宣言を追加する
変更前(package.json):
{
"name": "apple-pim-cli",
"version": "2.1.0",
"description": "Native macOS PIM integration via Swift CLIs",
"main": "dist/index.js"
}変更後(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."
}
}
}代替: 個別のopenclaw.config.json
{
"capabilities": {
"executesCode": true,
"reason": "Spawns parcel CLI for package tracking. Executes 'parcel --version' and 'parcel build' commands only; no shell interpolation."
}
}手順3: マニフェストが有効であることを確認する
$ 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手順4: 更新されたプラグインを公開する
$ npm version patch
$ npm publish
npm notice
+ [email protected]プラグイン作者向け: ソースコードの確認(スキャナー前)
追加のセキュリティルールがトリガーされないよう、コードが安全なパターンに従っていることを確認してください:
手順1: child_processの使用を監査する
$ 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.手順2: 可能な場合はexecよりもexecFileを使用する
避けるべき(シェルインジェクションのリスク):
const { exec } = require('child_process');
// DANGEROUS: Vulnerable to shell injection
exec(`parcel build ${userInput}`, callback);推奨(制御された実行):
const { execFile } = require('child_process');
// SAFE: Arguments are passed directly, not through shell
execFile('parcel', ['build', '--target', 'node'], callback);エンドユーザー向け: インフォームドコンセントによるインストール
手順1: インストール前にプラグインのcapability宣言を確認する
$ 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)手順2: 同意を得てインストールする
$ 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.手順3: アップデート後も信頼状態が続くことを確認する
$ 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.🧪 検証
検証1: Capability宣言が解析されることを確認する
コマンド:
$ npx openclaw manifest inspect ./path/to/plugin --field capabilities期待される出力:
{
"executesCode": true,
"reason": "Spawns native macOS Swift CLIs using EventKit..."
}
Status: ✓ Valid JSON structure
Scanner Compatibility: ✓ v2.x compatible終了コード: 0
検証2: セキュリティスキャナーがハードブロックではなくインフォームドコンセントを生成する
コマンド:
$ npx openclaw plugin install apple-pim-cli 2>&1 | head -20修正前の期待される出力:
✗ SECURITY FINDING [CRITICAL]
Rule: dangerous-exec
Plugin installation ABORTED.修正後の期待される出力:
ℹ️ CAPABILITY DECLARATION DETECTED
executesCode: true
This plugin has declared its need to execute code.
Would you like to proceed with installation? [y/N]:終了コード: 0(同意後)
検証3: 信頼状態が設定ファイルに永続化されることを確認する
コマンド:
$ cat ~/.openclaw/plugins/apple-pim-cli/trust.json 2>/dev/null || echo "Not found"期待される出力:
{
"pluginId": "apple-pim-cli",
"trusted": true,
"trustedAt": "2024-01-15T10:30:00Z",
"trustReason": "capability-declared:executesCode",
"expiresAt": null
}検証4: 自動CI/CDパイプラインテスト
プラグインのCIパイプラインに以下のステップを追加して、capability宣言を検証します:
# .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検証5: エンドツーエンドのインストールテスト
コマンド:
$ 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")'期待される出力:
{
"id": "apple-pim-cli",
"version": "2.1.0",
"installed": true,
"capabilities": {
"executesCode": true
},
"trustStatus": "trusted"
}⚠️ よくある落とし穴
1. 不完全な理由でCapability宣言を公開する
問題: プラグインが意味のあるreasonフィールドなしでexecutesCode: trueを宣言しています。
不正解:
{
"capabilities": {
"executesCode": true,
"reason": "yes"
}
}正解:
{
"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. 実際には必要ないのにCapabilityを宣言する
問題: 一部のプラグイン作者は、child_processを必要としないプラグインにも先手を打ってcapability宣言を追加するかもしれません。
影響: ユーザーがexecutesCode警告に麻木状態になり、セキュリティ信号としての効果が低下します。
軽減策: プラグインのランタイム動作実際に子プロセスの起動を必要とする場合にのみexecutesCode: trueを宣言してください。
3. exec()をexecFile()やspawn()の代わりに使用する
問題: セキュリティスキャナーは、シェルインジェクションのリスクにより、exec()呼び出しに追加の精査を適用する可能性があります。
危険なパターン:
const { exec } = require('child_process');
exec(`parcel build ${inputPath}`, callback); // Shell injection risk安全なパターン:
const { execFile } = require('child_process');
execFile('parcel', ['build', inputPath], callback); // No shell interpolation4. ハードコードされたバイナリパスとPATH解決の比較
問題: 絶対パスを使用してバイナリを 사용하는 플러그인은 PATH解決されたバイナリを使用する 플러그인とは異なるフラグが立てられる場合があります。
最適ではない:
execFile('/usr/local/bin/parcel', ['build', 'src']);推奨:
// Let the system resolve from PATH
execFile('parcel', ['build', 'src'], {
env: { ...process.env, PATH: process.env.PATH }
});5. メジャーバージョンアップ間で信頼状態が持続しない
問題: v2.1.0を信頼したユーザーは、異なるプラグインID形式 인해v3.0.0で再度確認求められる場合があります。
軽減策: OpenClaw v2.xではpluginId@majorVersionを信頼キーとして使用します。信頼状態を保持するには、メジャーバージョン間で同じIDを維持してください。
6. Docker/コンテナ環境での偽陽性
問題: Docker内で実行している場合、child_process検出がnpm installラッパーなどの合法的な操作にフラグを立てる可能性があります。
環境固有の動作:
# 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軽減策: 利用可能な場合は–ignore-pattern “node_modules/.bin/*"を使用するか、環境固有のスキャナー設定を提出してください。
7. プラグインのバンドルサイズがスキャン時間に影響する
問題: ファイル数が 많은 큰 플러그인은セキュリティスキャンフェーズがタイムアウトする可能性があります。
エラー:
[DEBUG] Scanning 15,847 files...
[TIMEOUT] Security scan exceeded 30 second limit
[ERROR] Installation aborted: scan timeout軽減策: 開発依存関係をスキャンから除外する.openclawignoreファイルをプラグインと一緒に提交してください。
🔗 関連するエラー
エラーコードと過去のイシュー
SCANNER_E001— dangerous-exec(ハードブロック)
このガイドで取り上げている主要なエラー。capability宣言なしにchild_processの使用が検出された場合に発生します。SCANNER_E002— arbitrary-code-injection
コマンドを構築するために文字列連結やテンプレートリテラルが使用されていることをスキャナーが検出したときにトリガーされます。dangerous-execより高い重要度です。SCANNER_E003— eval-usageeval()、new Function()、または同様のランタイムコード生成が検出された場合の重大な検出結果。SCANNER_E004— network-exfiltration
プラグインが未知のエンドポイントへのネットワークリクエストを作成したときにフラグが立てられます。dangerous-execに関連するどちらも潜在的なデータ抽出を示唆しています。SCANNER_E005— filesystem-overreach
プラグインの指定されたディレクトリ外でのファイルシステム操作を検出します。悪意のあるプラグインではdangerous-execと共存する可能性があります。INSTALL_E101— manifest-missing
プラグインに有効なマニフェストファイルがありません。capability宣言が読み取れない可能性があります。INSTALL_E102— manifest-invalid-schema
capability宣言は存在しますが、期待されるスキーマに準拠していません。reasonフィールドが空でない文字列であることを確認してください。TRUST_E201— consent-required
ユーザーの同意が必要ですが、stdinがTTYではありません。--consentフラグまたは--yesを使用して自動承認してください。TRUST_E202— trust-expired
Previously granted trust has expired. Re-consent required.
関連するGitHubイシュー
- Issue #1247 — 合法的なCLIラッパーに対するセキュリティスキャナーの偽陽性
apple-pim-cliや類似のプラグインに影響するパターンを特定した元のレポート。 - Issue #1189 — マニフェストスキーマへのcapability宣言サポートの追加
このガイドで実装された正確な解決策を提案する機能リクエスト。 - Issue #1102 — --dangerously-force-unsafe-installフラグは誤解を招く
「dangerously」という用語が合法的なユースケースには不適切であるという報告。 - Issue #1056 — child_processのPathベースの信頼モデルの検討
path許可リストを含む代替アプローチの議論。 - Issue #989 — 大規模なモノレポプラグインでのスキャナータイムアウト
スキャン完了に影響する関連パフォーマンス問題。
影響を受けるプラグイン(コミュニティ報告)
apple-pim-cli— Swift CLIを使用したmacOSカレンダー、リマインダー、連絡先、メールの統合parcel-cli— Parcel CLIによるパッケージ追跡prolog-agent— SWI-Prologクエリの実行rust-analyzer-wrapped— Rust言語サーバーラッパーdotnet-script— .NETスクリプトの実行