Back to skill

Security audit

OpenCode Remote

Security checks for vulnerabilities and agentic risk

Overview

This skill is a remote OpenCode control helper with expected network access, but it includes under-scoped high-impact operations such as remote shell execution, destructive session actions, plaintext unauthenticated API examples, and automatic monitoring.

Review before installing. Use this only with OpenCode servers you control, preferably behind HTTPS or a trusted private network with real authentication. Avoid using the shell, delete, revert, config, PTY, and file-content endpoints unless you explicitly intend that authority. Be aware that the skill may store session IDs locally, create ongoing monitoring, and repeat full prompts or outputs that could contain sensitive information.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/opencode_client.py:18
Finding
Unauthenticated Plaintext Transport for Privileged OpenCode API Operations<![CDATA[ ## Vulnerability Details **File Location**: `scripts/opencode_client.py`, lines 18-45 **Vulnerability Type**: Unauthenticated and unencrypted remote API communication **Risk Level**: High ### Vulnerable Code ```python class OpenCodeClient: def __init__(self, base_url: str, proxy: Optional[str] = None): self.base_url = base_url.rstrip('/') self.proxy = proxy def _request(self, method: str, path: str, data: Optional[dict] = None) -> dict: url = f"{self.base_url}{path}" headers = {"Content-Type": "application/json"} req = urllib.request.Request( url, method=method, headers=headers, data=json.dumps(data).encode() if data else None ) # 配置代理 if self.proxy: proxy_handler = urllib.request.ProxyHandler({ 'http': self.proxy, 'https': self.proxy }) opener = urllib.request.build_opener(proxy_handler) urllib.request.install_opener(opener) try: with urllib.request.urlopen(req) as response: return json.loads(response.read().decode()) except urllib.error.HTTPError as e: return {"error": f"HTTP {e.code}: {e.reason}", "details": e.read().decode()} except Exception as e: return {"error": str(e)} ``` The client also exposes privileged server-side operations, including arbitrary shell-command requests: ```python def shell_command(self, session_id: str, command: str) -> dict: """在 session 中执行 shell 命令""" return self._request("POST", f"/session/{session_id}/shell", {"command": command}) ``` ### Technical Analysis The request layer only sends a `Content-Type` header. It provides no bearer token, API key, client certificate, request signature, or other authentication mechanism. It also accepts arbitrary base URLs without requiring HTTPS. The project docu ...[truncated 2247 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require `https://` endpoints by default and reject plaintext `http://` URLs unless the user supplies an explicit, prominently warned development-only override. 2. Add authenticated request support, preferably using short-lived bearer tokens, mutually authenticated TLS, or another server-supported authentication mechanism. 3. Retrieve credentials from protected environment variables, an operating-system credential store, or a dedicated secret manager. Do not place credentials in source code or session metadata. 4. Validate TLS certificates and hostnames. Do not introduce an option that silently disables certificate verification. 5. Apply server-side authorization independently of the client. Separate read-only session access from prompt submission, destructive session management, and shell execution. 6. Disable the shell endpoint unless it is explicitly required. If retained, require elevated authorization, explicit user confirmation, command restrictions, audit logging, and isolation in a low-privilege sandbox. 7. Add confirmation gates for destructive operations such as deletion, abortion, and shell execution. 8. Restrict network exposure of the OpenCode service through firewall rules, private networking, or an authenticated gateway. 9. Avoid globally installing a proxy opener with `urllib.request.install_opener`; use a client-specific opener so proxy behavior cannot unexpectedly affect unrelated requests in the process. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main_session_manager.py:11
Finding
Session Metadata File Is Written Without Explicit Restrictive Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/main_session_manager.py`, lines 11-22 **Vulnerability Type**: Insecure local storage and file creation **Risk Level**: Medium ### Vulnerable Code ```python # 主session配置存储 MAIN_SESSIONS_FILE = "/root/.openclaw/workspace/opencode-sessions.json" def load_main_sessions(): """加载主session列表""" try: with open(MAIN_SESSIONS_FILE, 'r') as f: return json.load(f) except FileNotFoundError: return {} def save_main_sessions(sessions): """保存主session列表""" with open(MAIN_SESSIONS_FILE, 'w') as f: json.dump(sessions, f, indent=2) ``` ### Technical Analysis The session registry contains endpoint addresses, session identifiers, task descriptions, creation times, and monitoring state. The code creates or truncates this file using the default process umask and does not explicitly enforce owner-only permissions. As a result, the confidentiality of the registry depends on external runtime configuration. If the parent directory or resulting file is accessible to other local users or processes, those parties may obtain internal infrastructure information and active session identifiers. The file is also written directly rather than through an atomic replacement procedure. Process interruption, storage failure, or concurrent writers can leave a partially written or invalid JSON file. In addition, the implementation does not verify that the target is a regular file rather than a symbolic link. The practical exploitability of a symbolic-link attack depends on whether an attacker can modify the parent directory; the hardcoded `/root` path commonly limits that possibility, but the code does not enforce the assumption. ### Attack Path 1. The session manager runs with a permissive umask or in an environment where the workspace directory is accessible to another local account or compromised process. 2. The manager writes `opencode-sessions.json` without explicitly sett ...[truncated 1357 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create the parent directory with owner-only permissions, such as mode `0700`. 2. Create the registry with mode `0600`, independent of the process umask. For example, use `os.open` with `O_CREAT`, `O_WRONLY`, and an explicit mode. 3. Verify that the destination is a regular file and reject symbolic links. Where available, use `O_NOFOLLOW`. 4. Write updates to a protected temporary file in the same directory, flush and synchronize the data, set the correct ownership and mode, and atomically replace the destination with `os.replace`. 5. Use file locking if multiple manager processes may update the registry concurrently. 6. Validate the loaded JSON structure before using it, and fail safely when the file is corrupted rather than silently overwriting recoverable state. 7. Store only metadata required for operation. Avoid persisting sensitive task details when a short non-sensitive description is sufficient. 8. Consider deriving the storage location from a securely resolved per-user configuration directory instead of hardcoding a root-specific workspace path. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (23)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
This mismatch is security-relevant because the skill's stated purpose is benign session management, while the analysis indicates undeclared capability to execute shell commands in a remote session. Hidden remote shell functionality materially changes risk: it can run arbitrary commands on connected infrastructure while escaping user expectations and policy review.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This mismatch is security-relevant because the skill's stated purpose is benign session management, while the analysis indicates undeclared capability to execute shell commands in a remote session. Hidden remote shell functionality materially changes risk: it can run arbitrary commands on connected infrastructure while escaping user expectations and policy review.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
This mismatch is security-relevant because the skill's stated purpose is benign session management, while the analysis indicates undeclared capability to execute shell commands in a remote session. Hidden remote shell functionality materially changes risk: it can run arbitrary commands on connected infrastructure while escaping user expectations and policy review.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
### 删除 Session
```
DELETE /session/{sessionID}
```

---
Confidence
80% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
GET /pty                  # 列出 PTY 会话
POST /pty                 # 创建 PTY
GET /pty/{id}             # 获取 PTY 详情
DELETE /pty/{id}          # 关闭 PTY
GET /pty/{id}/connect     # WebSocket 连接
```
Confidence
80% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The client exposes a dedicated remote shell execution API that is outside the skill's stated session-management and messaging purpose. Even though the code only forwards requests to the OpenCode server, this capability can be abused to run arbitrary commands on the remote instance if the server honors the endpoint, materially increasing attack surface and privilege impact.

Missing User Warnings

High
Confidence
96% confidence
Finding
Remote shell execution is presented as a normal CLI feature without any safety notice or elevated-friction workflow despite its ability to run arbitrary commands on a remote system. In this skill context, that omission makes misuse more likely because users may not appreciate that they are invoking code execution rather than ordinary session management.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The CLI exposes arbitrary user-supplied shell command execution against a remote server without showing that such power is necessary for the advertised workflow. This creates a dangerous command-execution primitive that could be used for destructive actions, persistence, or data exfiltration on the remote OpenCode host.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill advertises and instructs use of network, shell, file read/write, and scheduling-like capabilities, but it does not declare any explicit tool scope or permission boundaries. That creates an over-privileged and non-transparent execution model where an agent may invoke sensitive capabilities without user-visible restriction or least-privilege controls.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The manifest description is entirely in Chinese and presents the skill's behavior and requirements in that language without indicating that users may interact in another language. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is explicitly justified.

Ssd 3

Medium
Confidence
96% confidence
Finding
The skill explicitly instructs the agent to echo back the full prompt sent to a remote session. Prompts often contain sensitive operational details, credentials, internal URLs, proprietary code fragments, or incident data, so mandatory verbatim replay creates a built-in exfiltration channel from one trust boundary to another.

External Transmission

Medium
Category
Data Exfiltration
Content
```bash
# ✅ 不指定 agent(推荐)
curl -s -X POST http://<host>:<port>/session/<sessionID>/message \
  -H "Content-Type: application/json" \
  -d '{
    "parts": [{"type": "text", "text": "prompt内容"}],
Confidence
86% confidence
Finding
This skill sends arbitrary user-supplied prompt content over HTTP to a remote OpenCode server. External transmission is expected for a remote-control skill, but the example uses plain HTTP and lacks safeguards such as transport security, destination validation, or warnings about sending sensitive content to third-party endpoints.

Ssd 3

Medium
Confidence
97% confidence
Finding
The monitoring workflow requires extracting and reporting the complete final output of remote sessions, which may include secrets, sensitive files, system details, or private task data collected during execution. Because this is automatic and framed as a normal completion behavior, it normalizes disclosure and increases the chance of leaking high-value information to users or logs that do not need full raw output.

External Transmission

Medium
Category
Data Exfiltration
Content
### 创建命令

```bash
curl -s -X POST http://<host>:<port>/session \
  -H "Content-Type: application/json" \
  -d '{"title": "新 session 标题"}'
```
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The file presents the API reference entirely in Chinese, which effectively forces a specific language for users reading the skill documentation. The policy allows locale constraints only when users are given a choice or when the restriction is clearly documented and justified; neither is present here.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
This markdown file describes operations such as deleting sessions, reverting sessions, aborting runs, executing shell commands, updating config, and closing PTY sessions, but it provides no warning that these actions can alter state, discard work, or affect the host system. For markdown files, omission of warnings about behaviors that may affect user data or system integrity is in scope for missing-user-warning findings.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The module docstring and all user-facing CLI messages are written only in Chinese, with no indication that language selection is optional or that the tool is intentionally region-specific. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This Python file contains user-facing natural-language strings entirely in Chinese, including the module description, status messages, and command usage text. That creates a locale policy concern because the skill imposes a specific language on users without any opt-in, fallback, or documented justification that it is intended only for Chinese-speaking or region-specific use.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"""使用 curl 获取数据"""
    try:
        cmd = ['curl', '-s', '--socks5-hostname', proxy, '--max-time', '15', url]
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=20)
        if result.returncode == 0:
            return json.loads(result.stdout)
        else:
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The client exposes irreversible remote session deletion with no confirmation prompt, dry-run, or warning. In an automation or operator-error scenario, this can lead to accidental destruction of conversations, task state, or audit history on the remote OpenCode service.

Intent-Code Divergence

Medium
Confidence
99% confidence
Finding
The CLI help and parser define `shell <session_id> <command>` as executing a shell command, but the dispatch code calls `client.shell_command(args.session_id, args.command)`. Here `args.command` is the selected subparser name (`'shell'`), not the user-supplied shell command argument, so the implementation contradicts the documented behavior.

Missing User Warnings

Low
Confidence
77% confidence
Finding
The documentation lists endpoints for reading file contents and searching project data, which may expose sensitive user or repository information, but it does not warn readers about privacy implications or expected authorization boundaries. For markdown files, missing warnings about behaviors affecting user data or privacy should be flagged when documentation presents such capabilities without disclosure.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
Natural-language strings throughout the file, including the module description, docstrings, and CLI help text, are presented in Chinese only. This imposes a specific language choice on users without opt-in or an alternative locale option.

Static analysis

No suspicious patterns detected.