Install
openclaw skills install @zkeviny/secure-script-runnerZero‑exposure script execution using MGC Blackbox. Store scripts encrypted, execute in blackbox, AI sees no plaintext. Supports MCP (mgc_run) / API / WebUI execution, internal credential calls, and script sealing. Includes MGC 1.4.9 temporary workaround guidelines. This skill only executes scripts w
openclaw skills install @zkeviny/secure-script-runnerSecure Script Runner is a documentation skill that teaches how to execute scripts with zero plaintext exposure using MGC Blackbox.
This skill enables:
mgc_run, recommended), API, WebUIThis skill only provides documentation, but involves script execution, which requires manual human approval.
After reading this documentation, an AI agent will understand how to:
ext02pip install mgc-blackbox>=1.4.9mgc (WebUI: http://127.0.0.1:57218, API: http://127.0.0.1:57219)mgc_save, mgc_run, mgc_list, mgc_seal, mgc_open_webui~/.mgc/database/mgc_black_box/.mgc_tokenImportant: For AI agents, use MCP tools.
mgc_runis the preferred tool for executing scripts as it provides true zero‑exposure.
Sandbox mode (Trae Work / Workbuddy): MGC 1.4.9 introduced sandbox mode. In this mode, scripts executed via
mgc_runrun in an isolated environment, further enhancing security. The AI can callmgc_open_webuito guide the user to view the status.
Script (plaintext) → MGC Encryption → Encrypted Storage
↓
Blackbox Execution (MGC)
↓
AI receives result only
AI executes but never sees script plaintext or standard output.
| Mode | Interface | Use Case |
|---|---|---|
| MCP (Recommended) | mgc_run | AI agents (blackbox, zero‑exposure) |
| REST API | /api/mgc/sensitive/run | System scripts |
| WebUI | http://127.0.0.1:57218 | Human operators |
Note:
mgc_get(action="run")is still available, butmgc_runis recommended as it is explicitly designed for execution and does not expose the process.
Store a script with execution metadata:
# Via MCP tool
mgc_save(
info_type="script",
info_owner="my_script",
ext01="python", # Startup command (e.g., python, python3)
ext02="", # Default runtime args (optional)
content="print('Hello from zero‑exposure!')"
)
| Parameter | Required | Description |
|---|---|---|
| info_type | Yes | Must be "script" |
| info_owner | Yes | Unique script identifier |
| ext01 | Yes | Startup command (python, node, etc.) |
| ext02 | No | Default runtime arguments |
| content | Yes | Script plaintext (encrypted at rest) |
Execute using the mgc_run tool:
# Basic execution
result = mgc_run(
info_owner="my_script"
)
# Execution with parameters (via ext02)
import json
params = {"arg1": "value1", "arg2": "value2"}
result = mgc_run(
info_owner="my_script",
ext02=json.dumps(params) # Must be a JSON string
)
# AI receives execution result only
ext02 Parameter Specification:
ext02is used to pass runtime parameters to the script.- It must be converted to a JSON string using
json.dumps().- Failure to do so may cause MCP serialization errors (HTTP 422).
- The script can read these parameters from environment variables or standard input.
# Execute script
curl -X POST http://127.0.0.1:57219/api/mgc/sensitive/run \
-H "Content-Type: application/json" \
-H "X-MGC-Token: $(cat ~/.mgc/database/mgc_black_box/.mgc_token)" \
-d '{
"info_type": "script",
"info_owner": "my_script",
"ext02": "{\"arg1\": \"value1\"}"
}'
Important: MGC 1.4.9 has known engineering defects in script execution that may cause scripts to silently fail or produce no output. Please strictly follow these scripting guidelines. The MGC team will fix these issues in a future release.
parse_known_args instead of parse_argsimport argparse
parser = argparse.ArgumentParser()
parser.add_argument('--output_dir')
parser.add_argument('--content')
parser.add_argument('--filename')
# ❌ Wrong: parse_args() exits on unknown parameters
# args = parser.parse_args()
# ✅ Correct: parse_known_args() ignores extra parameters
args, unknown = parser.parse_known_args()
def _strip_quotes(v):
"""Remove quotes added by MGC's ext02 parameter passing"""
if isinstance(v, str) and len(v) >= 2 and v[0] == v[-1] and v[0] in ('"', "'"):
return v[1:-1]
return v
# Apply to all fields that may contain paths or content
args.output_dir = _strip_quotes(args.output_dir)
args.content = _strip_quotes(args.content)
# ❌ Wrong: print() output exceeding 4KB causes PIPE blocking
# print(f"Processing completed, result: {result}")
# ✅ Correct: Write results to a file
with open(output_file, 'w', encoding='utf-8') as f:
f.write(f"Processing completed\n")
f.write(f"Result: {result}\n")
| Rule | Recommended | Avoid |
|---|---|---|
| Path separator | ✅ Forward slash / (D:/path) | ❌ Backslash \ (D:\path) |
| Parameters with spaces | ✅ Use T to separate (2026-07-28T00:00:00) | ❌ Use spaces directly |
| Parameter structure | ✅ --key "value" explicitly named | ❌ Positional arguments |
import argparse
import os
from datetime import datetime
def main():
parser = argparse.ArgumentParser(description='MGC Script Template')
parser.add_argument('--content', default='Default content')
parser.add_argument('--output_dir', default=os.path.expanduser("~/Desktop"))
parser.add_argument('--filename', default=None)
# Rule 1: Use parse_known_args
args, unknown = parser.parse_known_args()
# Rule 2: Strip quotes
def _strip_quotes(v):
if isinstance(v, str) and len(v) >= 2 and v[0] == v[-1] and v[0] in ('"', "'"):
return v[1:-1]
return v
args.content = _strip_quotes(args.content)
args.output_dir = _strip_quotes(args.output_dir)
args.filename = _strip_quotes(args.filename)
# Business logic
if not os.path.exists(args.output_dir):
os.makedirs(args.output_dir)
filename = args.filename or f"output_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"
output_file = os.path.join(args.output_dir, filename)
# Rule 3: Write to file
with open(output_file, 'w', encoding='utf-8') as f:
f.write(f"content={args.content}\n")
f.write(f"output_dir={args.output_dir}\n")
# Return execution result (concise)
print(f"SUCCESS:{output_file}")
if __name__ == "__main__":
main()
Note: These guidelines are temporary workarounds for MGC 1.4.9. The MGC team will fix
ext02parameter parsing andstdoutblocking issues in a future release, at which point these workarounds can be removed.
Scripts can call MGC internal credentials using the internal API:
# Example: Call MGC credential from script
import urllib.request
import json
def get_mgc_credential(info_type, info_owner):
data = json.dumps({
"info_type": info_type,
"info_owner": info_owner
}).encode("utf-8")
req = urllib.request.Request(
"http://127.0.0.1:57219/api/mgc/sensitive/get",
data=data,
headers={
"Content-Type": "application/json",
"X-MGC-Token": open("/path/to/token").read()
},
method="POST"
)
with urllib.request.urlopen(req) as resp:
return json.loads(resp.read().decode())["data"]
Note: Credentials are retrieved locally, script executes in blackbox, AI never sees plaintext.
For cross‑node delegation, scripts can be sealed using the node's public key:
# Via MCP tool
node_pub = mgc_get(
info_type="__NODE_PUB__",
info_owner="__NODE_PUB__"
)
# Via MCP tool
sealed = mgc_seal(
info_type="script",
info_owner="my_script",
ext04=node_pub # Target node public key
)
# Store sealed version
mgc_save(
info_type="script",
info_owner="my_script_sealed",
ext01="python",
content=sealed
)
Sealed scripts are encrypted and can only be executed by the target node.
Arguments:
{
"info_type": "script",
"info_owner": "unique identifier",
"ext01": "startup command (python, node, etc.)",
"ext02": "default runtime arguments (optional)",
"content": "script plaintext"
}
Arguments:
{
"info_owner": "script identifier",
"ext02": "runtime parameters (JSON string, optional)"
}
Returns: Script execution result
Arguments:
{
"info_type": "script"
}
Returns: List of scripts (no plaintext)
Arguments:
{
"info_type": "script",
"info_owner": "script identifier",
"ext04": "target node RSA public key"
}
Returns: Sealed script (encrypted with target node key)
Purpose: Opens the MGC WebUI in the browser for user to view or manually operate.
Please read the following warnings carefully
Before executing scripts, user must confirm the following: