github →

New request

#3383: RFC: Subprocess-isolated plugin backend API bridge

We'll provision a sandbox, run an agent against the issue, and open a draft PR. You can pull the branch and iterate from there.

Issue
enhancementtracking

Summary

Add a plugin backend API system where each plugin runs in its own subprocess, communicating with WebUI via stdin/stdout JSON. This replaces the need for standalone HTTP servers per plugin and avoids the security risks of running plugin code in-process.

Motivation

From PR #2622 discussion:

  1. No viable in-process sandbox — CPython has no reliable in-process sandbox (ctypes bypasses everything). Running third-party plugin code via exec_module() is unsafe for public plugin use.
  2. Standalone servers are heavy — port allocation, process lifecycle, CORS boilerplate per plugin adds unnecessary complexity.
  3. Interest from reviewers — both nesquena-hermes and AJV20 agree subprocess isolation is the right direction.

Proposed Design

Plugin JS (sandboxed iframe, from PR #2622)
  │  fetch('/api/plugins/<name>/<sub_route>')
  ▼
WebUI (proxy layer)
  │  serialize request → JSON, write to subprocess stdin
  ▼
Plugin subprocess (isolated, resource-limited)
  │  run handler, serialize response → JSON, write to stdout
  ▼
WebUI wraps JSON → HTTP response

Key properties:

  • stdin/stdout JSON-line protocol (one line per request/response)
  • Each plugin gets its own subprocess (crash isolation)
  • Resource limits via setrlimit (512MB RAM, 5min CPU, 256 files)
  • Minimal environment passed to plugin (no API tokens)
  • CompatHandler mimics BaseHTTPRequestHandler so existing plugin code needs minimal changes
  • Controlled by HERMES_WEBUI_PLUGIN_MODE=subprocess (defaults to in-process)

Guardrails (from review discussion)

  1. Manifest contract — plugin manifest declares backend command/args, supported methods, timeout
  2. Minimal env — explicit passthrough only; no ambient secrets
  3. Bounded protocol — structured request/response with id, method, params, timeout, error shape
  4. Lifecycle ownership — WebUI owns start/stop/restart/health; plugin is a sidecar, not an extension
  5. Permission model — manifest declares capabilities; UI surfaces them
  6. Failure isolation tests — hung process, invalid JSON, crash, oversized response, stderr leaks

Scope

  • Start with one minimal read-only demo endpoint to validate the protocol/lifecycle
  • Keep PR #2622 focused on iframe/frontend isolation
  • Follow-up RFC/PR for the subprocess backend bridge

Related

Assessmentadvisory
feature●●● hard90% confidence

Architectural addition of a subprocess-isolated plugin bridge spanning API routing, process lifecycle management, and frontend proxy integration.

Likely files
  • entry/api/server.py
  • entry/api/plugin_bridge.py
  • entry/bootstrap.py
  • static/plugin-proxy.js
  • infra/config/plugin-manifest.schema.json
  • infra/unknown/test_plugin_bridge.py
Create the request

This opens a fresh agent run and a draft PR for issue #3383.

Cancel