Plugins
Plugins let you extend Madhyamas with custom logic compiled to WebAssembly (WASM). They run in a sandboxed wasmtime runtime with strict CPU and memory limits, so you can add new interception, modification, or logging behavior without compromising the proxy's stability or security.

How Plugins Work
A plugin is a .wasm module with a manifest that declares which hooks it subscribes to (e.g. on_request, on_response) and what capabilities it needs. When traffic flows through the proxy, the plugin manager dispatches matching events to each enabled plugin. Plugins can inspect and modify traffic, log activity, and expose their own settings and UI panels.
Plugins are sandboxed by design:
- No filesystem, network, or host memory access unless explicitly granted
- CPU is bounded by a fuel budget (default 10 million instructions per invocation)
- Memory is capped (linear memory limited to 256 MiB)
- Packages are verified with SHA-256 checksums on install, and optionally signed with Ed25519
Installing a Plugin
From the Registry
The plugin registry is a GitHub-backed catalog of plugins. Browse and install from it directly:
# List available plugins in the registry
madhyamas plugins registry
# Search the registry
madhyamas plugins search "cors"
# Install a plugin from the registry
madhyamas plugins install --source registry my-pluginFrom a URL
# Install from a direct URL
madhyamas plugins install https://example.com/my-plugin.zip
# With checksum verification
madhyamas plugins install https://example.com/my-plugin.zip --checksum abc123...From the Web UI
Open the Plugins view to browse the registry, install, enable, and configure plugins without leaving the browser.
Managing Plugins
madhyamas plugins list # List loaded plugins
madhyamas plugins enable my-plugin # Enable a plugin
madhyamas plugins disable my-plugin # Disable a plugin
madhyamas plugins stats my-plugin # View runtime statistics
madhyamas plugins logs my-plugin # View recent invocation logs
madhyamas plugins reload # Reload all plugins from disk
madhyamas plugins uninstall my-plugin # Uninstall a pluginEach plugin has a toggle switch in the web UI. Disabled plugins stay installed but don't process traffic.
Plugin Settings
Plugins can declare a settings schema, so they expose configurable options that you can change at runtime:
madhyamas plugins schema my-plugin # Get the settings schema
madhyamas plugins get-settings my-plugin # Get current settings
madhyamas plugins set-settings my-plugin \
--settings '{"key": "value"}' # Update settingsIn the web UI, plugin settings appear in the Plugins panel when you select a plugin.
The Plugin Registry
The registry is backed by a GitHub repository containing a plugins/registry.json catalog. The default registry is the Madhyamas project repo itself, but you can point it at any fork or private catalog:
madhyamas plugins registry-config # Show current config
madhyamas plugins registry-config owner/repo@main # Set the registry repo
madhyamas plugins registry-refresh # Force-refresh the cacheSubmitting a Plugin
- Build your plugin and package it as a zip
- Create a GitHub release with the zip attached as an asset
- Fork the registry repo and add your plugin entry to
registry.json - Open a pull request to merge your entry into the catalog
Hot Reload
During development, Madhyamas watches plugin directories for changes to .wasm, manifest, and settings files. When a file changes, the affected plugins reload automatically (with a short debounce to avoid reload storms). No manual reload command is needed while iterating on a plugin.
Scaffolding New Plugins
If you want to write your own plugin, start from a built-in template:
madhyamas plugins templates # List available templates
madhyamas plugins new cors my-cors-plugin \
--output ./plugins # Scaffold from the cors templateAvailable templates: basic, cors, request-logger, domain-blocker, response-modifier.
Plugins are written in Rust using the madhyamas-plugin-sdk crate and compiled to plugin.wasm. See the plugin development guide in the docs/ directory for the full walkthrough.
Plugin Signing
Plugin publishers can sign packages with Ed25519 so installers can verify authenticity:
madhyamas plugins gen-key # Generate a publisher keypair
madhyamas plugins sign my-plugin.zip \
--secret-key <hex> # Sign a package (writes signature.sig)When a plugin manifest declares a publisher_public_key, the installer automatically verifies the signature on install.
Common Use Cases
Adding Custom Interception Logic
Write a plugin when scripts aren't enough — for example, when you need complex state, custom protocols, or reusable distributable logic.
Sharing Reusable Tools
Publish a plugin to the registry so your team (or the community) can install a consistent debugging tool with a single command.
Protocol-Specific Helpers
Build plugins that understand specific protocols (e.g. a GraphQL inspector, a protobuf decoder) and surface their own UI panels in the web UI.
Team Standards
Distribute a plugin that enforces your team's debugging conventions — logging format, header injection, or traffic filtering — across every developer's proxy.
See also
- Scripting — sandboxed JavaScript for lighter-weight automation
- Security Overview — plugin sandboxing and signing
- CLI reference —
madhyamas pluginssubcommands - REST API reference —
/api/pluginsendpoints - Plugin development guide — writing your own plugin (developer docs)
Secrets and environment variables (issue #87)
Declare per-name grants in madhyamas-plugin.toml:
env_grants = ["UPSTREAM_API_URL"] # process env vars the plugin may receive
secret_grants = ["api_token"] # managed secret names the plugin may receiveThen reference them in the plugin's settings (via the web UI settings form or the settings API):
{ "authorization": "Bearer ${SECRET:api_token}", "url": "${ENV:UPSTREAM_API_URL}" }Placeholders are expanded at hook-dispatch time; only granted names are substituted (deny by default). Scripts use the same syntax with the scripts API's env_grants / secret_grants fields.
Managing secrets
- Web UI: Tools -> Secrets (names only; values are write-only).
- API:
GET /api/secrets(names),PUT /api/secrets/{name}with{"value": "..."},DELETE /api/secrets/{name}. - Enterprise: management is restricted to the admin role and every access is audit-logged.
Key management (OSS keystore)
Secrets are stored AES-256-GCM encrypted in <data_dir>/secrets.enc.json. The 32-byte master key is resolved in this order:
MADHYAMAS_SECRETS_KEYenv var — 64 hex characters or exactly 32 raw bytes (recommended for containers: inject from Docker/Kubernetes secrets).MADHYAMAS_SECRETS_KEY_FILE— path to a key file (keep it on a different volume than the keystore, or inject via a secret manager).- Auto-generated
<data_dir>/secrets.key(mode 0600) — development convenience only; losing this file makes stored secrets unrecoverable, and it should not be backed up alongside the keystore.
There is no rotation/TTL in v1 — update secrets manually via the API/UI.