Z-CMS が Node.js VM ではなく V8 Isolate を採用する理由
モダンな open-source CMS のための、より安全な plugin runtime 設計
Plugin system の背後にある設計課題
Z-CMS の plugin system を設計する際、中心となった問いは「別の JavaScript module をどう load するか」ではありませんでした。本当の課題は、third-party developer に CMS を拡張する自由を与えながら、各 plugin に server への無制限な権限を与えないことです。
Plugin は platform を十分に拡張できる必要があります。一方で、単一の bug、memory leak、無限 loop が CMS 全体を不安定にしない程度に isolation されていなければなりません。すべての plugin を CMS Core と同じ Node.js runtime で動かすと、1 つの plugin が全 tenant と全 request に影響を与える可能性があります。
従来の Node.js アプローチ
基本的な plugin loader は require() や dynamic import で実装できます。分かりやすく短期間で作れますが、plugin は Core と同じ process、event loop、memory space、environment variables、Node.js APIs を共有します。意図しないコードでも重大な incident を引き起こし得ます。
Node.js vm が最終的な security boundary ではない理由
標準の vm module は独立した JavaScript context を作成できます。Controlled scripting には有効ですが、その context は同じ V8 Isolate、同じ operating-system process の中に存在します。そのため event loop、process memory、garbage collector は CMS Core と共有されます。
Z-CMS が必要としたのは context separation だけではなく、plugin ごとの independent memory limit、execution timeout、lifecycle control です。
CMS Core
│
├── Plugin SEO
│ └── V8 Isolate
├── Plugin AI
│ └── V8 Isolate
└── Plugin Analytics
└── V8 IsolateV8 Isolate モデル
V8 Isolate は V8 engine 内の独立した JavaScript execution environment です。各 isolate は専用の heap、global object、execution context、garbage collector を持ちます。
Plugin は process.env、host filesystem、child_process、Core 内部 object に自動的にはアクセスできません。Z-CMS が明示的に expose した capability だけを受け取ります。
Capability-based API
Z-CMS は Node.js runtime 全体を expose せず、管理された SDK を提供します。Plugin は manifest に従って content、storage、cache、event、logging、HTTP、settings capability を利用します。
すべての bridge call は Core 側で validate されます。storage:write permission を持たない plugin が write method を呼んでも、その operation は拒否されます。
{
"name": "@z-cms/plugin-seo",
"permissions": [
"content:read",
"content:update",
"settings:read"
],
"runtime": {
"memoryLimitMb": 64,
"timeoutMs": 2000
}
}CPU、timeout、memory limit
Request lifecycle 内で実行される hook は無期限に動作してはいけません。Z-CMS は execution ごとに maximum duration を設定し、policy を超えた isolate を terminate または recycle できます。
Memory policy も plugin 単位で定義できます。小規模 plugin には小さな heap を割り当て、承認済みの processing plugin にはより大きな allocation を与えます。
Isolate だけで完全な sandbox になるわけではない
Isolation の強度は host が expose する bridge に依存します。Core が危険な system command API を提供すれば、isolate では補えません。Z-CMS は raw Node.js API や database connection を expose せず、filesystem と network access を制限し、runtime boundary を越える値を validate・serialize し、tenant・user・plugin permission を Core で enforce します。
Plugin ごとに container を使わない理由
Container は強い operating-system isolation を提供しますが、image distribution、network management、service discovery、startup latency、logging complexity、resource overhead が増えます。一般的な plugin business logic では、V8 Isolate が isolation、startup speed、operational cost の現実的なバランスになります。
Failure containment と結論
Plugin が失敗した場合、isolate だけを terminate し、CMS Core は稼働を継続できます。Repeated failure には circuit breaker を適用し、platform 全体を維持したまま plugin を一時 suspend できます。
Marketplace-driven CMS において plugin isolation は付加機能ではなく platform foundation です。V8 Isolate により、各 plugin に独立 runtime、explicit capability、resource limit、制御可能な lifecycle を提供できます。
Key takeaways
- Security boundary は plugin の善意ではなく Core 側で enforce する必要があります。
- Lifecycle、permission、tenant context、observability は同じ platform contract の一部です。
- 優れた developer experience は、安全な runtime と supply chain の設計によって持続可能になります。
GitHub: https://github.com/zscontributor/z-cms
Website: https://z-cms.org