Back to skill

Security audit

Trent OpenClaw Security Assessment

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real security-audit skill, but it needs Review because it uploads packaged local skill/code artifacts and can send the Trent API key to unvalidated custom API endpoints.

Install only if you are comfortable sending redacted OpenClaw metadata and packaged local skill/code archives to Trent. Before upload, review the generated .skill archives and avoid setting custom TRENT_CHAT_API_URL or TRENT_AGENT_API_URL unless the endpoint is trusted and intended to receive your Trent API key.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/openclaw_trent/lib/trent_client.py:33
Finding
Configurable API endpoints can disclose the Trent API key to an arbitrary server<![CDATA[ ## Vulnerability Details **File Location**: `scripts/openclaw_trent/lib/trent_client.py:33-37`, `scripts/openclaw_trent/lib/trent_client.py:142-163`, and `scripts/openclaw_trent/lib/trent_client.py:259-274` **Vulnerability Type**: Unvalidated authenticated API endpoint **Risk Level**: High ### Vulnerable Code ```python def _get_chat_url() -> str: return os.environ.get("TRENT_CHAT_API_URL") or _DEFAULT_CHAT_URL def _get_agent_url() -> str: return os.environ.get("TRENT_AGENT_API_URL") or _DEFAULT_AGENT_URL ``` The configurable URL is subsequently used with the Trent API key: ```python headers = { "Authorization": auth_header, "Content-Type": "application/json", "Accept": "text/event-stream", } req = urllib.request.Request( f"{_get_chat_url()}/v1/chat", data=payload, headers=headers, method="POST", ) ``` The same issue affects agent API requests: ```python def _api_request(method: str, endpoint: str, json_data: dict | None = None) -> dict: auth_header = _get_auth_header() url = f"{_get_agent_url()}/v1/trent-agent{endpoint}" payload = json.dumps(json_data).encode() if json_data is not None else None headers: dict[str, str] = { "Authorization": auth_header, "Content-Type": "application/json", } req = urllib.request.Request(url, data=payload, headers=headers, method=method) with urllib.request.urlopen(req, timeout=60) as resp: data = json.loads(resp.read().decode()) ``` ### Technical Analysis Both API base URLs are taken directly from environment variables. Although `_is_trusted_trent_url()` exists elsewhere in the module, it is not applied to `TRENT_CHAT_API_URL` or `TRENT_AGENT_API_URL`. Consequently, a party capable of influencing the audit process's environment can redirect authenticated requests to an arbitrary endpoint. The `Authorization` header containing `TRENT_API_KEY` is attached before the request is sent. The chat request can additionally expose ...[truncated 1525 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate both configured base URLs before attaching credentials: - Require the `https` scheme. - Reject user information, fragments, malformed ports, and empty hostnames. - Restrict hosts to an explicit allowlist such as `trent.ai` and approved subdomains. 2. Call the existing `_is_trusted_trent_url()` function from `_get_chat_url()` and `_get_agent_url()`, failing closed when validation fails. 3. Normalize URLs with `urllib.parse.urlparse()` rather than relying on string concatenation. 4. Disable automatic cross-origin redirects for authenticated requests, or verify every redirect target before forwarding credentials. 5. If self-hosted or development endpoints must be supported, use separate endpoint-specific credentials rather than the production Trent API key. 6. Require explicit user confirmation when a non-default endpoint is selected and display the normalized destination hostname. 7. Add tests covering HTTP URLs, user-information URLs, lookalike domains, fragments, alternate ports, redirects, and attacker-controlled hosts. A hardened pattern would be: ```python def _validated_base_url(env_name: str, default: str) -> str: url = (os.environ.get(env_name) or default).strip().rstrip("/") if not _is_trusted_trent_url(url): raise RuntimeError(f"Untrusted API endpoint configured in {env_name}") return url ``` ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/openclaw_trent/lib/package_skills.py:350
Finding
Unrecognized binary files are packaged and uploaded without secret inspection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/openclaw_trent/lib/package_skills.py:313-319` and `scripts/openclaw_trent/lib/package_skills.py:350-364` **Vulnerability Type**: Incomplete secret filtering before remote upload **Risk Level**: Medium ### Vulnerable Code ```python def _add_file_to_zip( zf: zipfile.ZipFile, fp: pathlib.Path, arcname: pathlib.PurePosixPath | str, workspace_root: pathlib.Path | None = None, ) -> int: """Add a single file to a ZIP with secret redaction. Skips symlinks and files that resolve outside the workspace root. Excludes dangerous file types entirely. Text files are redacted. Binary files are added as-is (secrets in binaries are rare in skill code). ``` Files that fail UTF-8 decoding are added unchanged: ```python file_size = fp.stat().st_size # Refuse to package files too large to redact safely if file_size > MAX_REDACT_FILE_SIZE: logger.warning("Excluded %s — too large for safe redaction (%d bytes)", arcname, file_size) return 0 # Try to read as text and redact try: content = fp.read_text(encoding="utf-8") redacted, count = redact_file_content(content) if count > 0: logger.info("Redacted %d secret(s) in %s", count, arcname) zf.writestr(str(arcname), redacted) return count except (UnicodeDecodeError, ValueError): # Binary file — add as-is zf.write(fp, arcname) return 0 ``` ### Technical Analysis The packager recursively processes files in discovered skills and workspace code projects. Known sensitive extensions and filenames are excluded, but the filtering model is denylist-based. Any file that: - Is no larger than 10 MB; - Does not use a specifically excluded extension or filename; and - Cannot be decoded as UTF-8 is treated as a binary file and copied directly into the `.skill` archive. No content inspection, entropy analysis, file-signature validation, or explicit approval is applied to that file. Sensitive information ...[truncated 1762 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Adopt an allowlist for packageable file types rather than uploading every file not present on a denylist. 2. Exclude binary files by default. Only include recognized source-code, documentation, and text configuration formats. 3. If binary files are necessary: - Mark each one as unscanned. - Display its relative path, type, and size before upload. - Require explicit per-file or per-package confirmation. 4. Generate and present a complete archive manifest containing: - Included files; - Excluded files; - Redacted files; - Unscanned files; - File sizes and detected types. 5. Detect file types from content signatures rather than relying only on extensions. 6. Expand protection for private-key headers, encrypted credential stores, archives, serialized data, and high-entropy content. 7. Fail closed when redaction cannot be performed instead of copying the original file. 8. Add automated tests using extensionless binaries, non-UTF-8 fixtures, renamed private keys, embedded archives, and uncommon credential formats. The safe default branch should be similar to: ```python except (UnicodeDecodeError, ValueError): logger.warning("Excluded unscanned binary file %s", arcname) return 0 ``` ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/openclaw_trent/lib/trent_client.py:168
Finding
Race-prone temporary output file creation permits local symlink attacks<![CDATA[ ## Vulnerability Details **File Location**: `scripts/openclaw_trent/lib/trent_client.py:168-174` **Vulnerability Type**: Insecure temporary file creation **Risk Level**: Low ### Vulnerable Code ```python # Write chunks to a file as they arrive — survives sandbox SIGTERM out_path = output_file or tempfile.mktemp(prefix="trent_chat_", suffix=".json") content_chunks: list[str] = [] returned_thread_id: str | None = thread_id expiration_warning: str | None = None try: with urllib.request.urlopen(req, timeout=300) as resp, open(out_path, "w") as out: ``` ### Technical Analysis `tempfile.mktemp()` returns a candidate pathname but does not securely create or reserve the file. There is a time-of-check/time-of-use window between selecting the pathname and opening it with `open(out_path, "w")`. A local attacker who can discover or predict the path can create a file or symbolic link at that location before the Skill opens it. Because the file is opened in write mode, the target is truncated and replaced with streamed assessment output. The issue is most relevant on shared systems, environments where temporary-directory contents are observable, or where another process under the same account is compromised. Supplying `output_file` explicitly can introduce additional arbitrary-write risk if untrusted callers control that argument, although the documented workflow does not expose it directly to remote input. ### Attack Path 1. The Skill calls `tempfile.mktemp()` and obtains an unused-looking pathname under the temporary directory. 2. Before `open()` executes, a local attacker learns or anticipates that pathname. 3. The attacker creates a symbolic link at the path pointing to another file writable by the audit process. 4. The Skill calls `open(out_path, "w")`. 5. The linked target is truncated and receives the remote assessment output. 6. Depending on the target, this can cause data corruption or expose the assessment response to another local process. # ...[truncated 448 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace `tempfile.mktemp()` with `tempfile.NamedTemporaryFile()` or `tempfile.mkstemp()`. 2. Keep and use the securely created file descriptor rather than closing and reopening the pathname. 3. Ensure owner-only permissions, preferably mode `0600`. 4. If `output_file` is supplied by a caller: - Resolve and validate the destination against an approved directory; - Reject symbolic links; - Use exclusive creation where overwriting is unnecessary; - Document that the argument must not be derived from untrusted input. 5. Add tests that attempt symlink replacement and concurrent file creation. For example: ```python temp = tempfile.NamedTemporaryFile( mode="w", encoding="utf-8", prefix="trent_chat_", suffix=".json", delete=False, ) out_path = temp.name try: with urllib.request.urlopen(req, timeout=300) as resp, temp as out: # Process and write the response. ... ``` ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (21)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill description understates that it performs general-purpose chat calls to a remote API, prepares uploads through an agent API, and may send content to presigned S3 URLs while writing streamed output locally. For a security-focused skill, hidden or under-disclosed outbound communication is especially sensitive because users may provide privileged configuration and code during analysis.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The skill description understates that it performs general-purpose chat calls to a remote API, prepares uploads through an agent API, and may send content to presigned S3 URLs while writing streamed output locally. For a security-focused skill, hidden or under-disclosed outbound communication is especially sensitive because users may provide privileged configuration and code during analysis.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The skill description understates that it performs general-purpose chat calls to a remote API, prepares uploads through an agent API, and may send content to presigned S3 URLs while writing streamed output locally. For a security-focused skill, hidden or under-disclosed outbound communication is especially sensitive because users may provide privileged configuration and code during analysis.

Credential Access

High
Category
Privilege Escalation
Content
".p12",
    ".pfx",
    ".jks",  # crypto keys/certs
    ".env",  # environment files (secrets.env, prod.env, etc.)
    ".exe",
    ".dll",
    ".so",
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
".p12",
    ".pfx",
    ".jks",  # crypto keys/certs
    ".env",  # environment files (secrets.env, prod.env, etc.)
    ".exe",
    ".dll",
    ".so",
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
".p12",
    ".pfx",
    ".jks",  # crypto keys/certs
    ".env",  # environment files (secrets.env, prod.env, etc.)
    ".exe",
    ".dll",
    ".so",
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Filenames that are never included in ZIPs (may contain secrets)
EXCLUDED_FILENAMES = {
    ".env",
    ".env.local",
    ".env.production",
    ".env.development",
    "credentials.json",
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
EXCLUDED_FILENAMES = {
    ".env",
    ".env.local",
    ".env.production",
    ".env.development",
    "credentials.json",
    "service-account.json",
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
".env",
    ".env.local",
    ".env.production",
    ".env.development",
    "credentials.json",
    "service-account.json",
    # SSH keys
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
".env.local",
    ".env.production",
    ".env.development",
    "credentials.json",
    "service-account.json",
    # SSH keys
    "id_rsa",
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"id_dsa.pub",
    # Credential stores
    ".pgpass",
    ".netrc",
    ".npmrc",
    ".pypirc",
    ".git-credentials",
Confidence
80% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Credential stores
    ".pgpass",
    ".netrc",
    ".npmrc",
    ".pypirc",
    ".git-credentials",
    ".htpasswd",
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
".netrc",
    ".npmrc",
    ".pypirc",
    ".git-credentials",
    ".htpasswd",
    ".htaccess",
    # OS artifacts
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"desktop.ini",
}

# Pattern to catch all .env variants (.env.staging, .env.test, .env.qa, etc.)
_ENV_FILE_RE = re.compile(r"^\.env(\..+)?$", re.IGNORECASE)

# Context-aware key=value pattern: lines like `API_KEY = "sk-..."` or `token: ghp_...`
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"desktop.ini",
}

# Pattern to catch all .env variants (.env.staging, .env.test, .env.qa, etc.)
_ENV_FILE_RE = re.compile(r"^\.env(\..+)?$", re.IGNORECASE)

# Context-aware key=value pattern: lines like `API_KEY = "sk-..."` or `token: ghp_...`
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill invokes Python and shell, reads environment variables, scans the workspace, writes archives, and makes network requests, yet it declares no explicit tool scope such as permissions or allowed-tools. That gap weakens user visibility and policy enforcement, increasing the risk of overbroad execution and accidental data exposure during a security audit workflow.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The implementation performs broad workspace discovery and packages code and skills into .skill archives, which does not match the stated purpose of merely assessing deployment security risks. Even though the code attempts to exclude some secret-bearing files and redact text secrets, it still creates exportable archives of user code and metadata, expanding the chance of unintended collection, retention, or downstream exfiltration of sensitive material.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The code walks the entire workspace and emits archives for skill directories, code projects, and standalone scripts, which is a data-collection capability broader than a typical security assessment needs. In skill context, this is more dangerous because users may invoke a 'security' skill expecting analysis, not wholesale packaging of their local workspace for later upload or processing.

Description-Behavior Mismatch

Medium
Confidence
89% confidence
Finding
The code packages local skills and custom code into ZIP archives and uploads them to a remote Trent service for analysis, which is a data exfiltration/privacy risk if users believe the skill only performs local security assessment. The danger is heightened because the uploaded content may include proprietary source code, embedded secrets, or internal configuration from the workspace, and the description does not make that network transfer explicit at the point of use.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
return {
            "mode_octal": oct(mode),
            "owner_read_only": mode in (0o600, 0o400),
            "world_readable": bool(mode & stat.S_IROTH),
            "world_writable": bool(mode & stat.S_IWOTH),
        }
    except OSError:
Confidence
70% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
"mode_octal": oct(mode),
            "owner_read_only": mode in (0o600, 0o400),
            "world_readable": bool(mode & stat.S_IROTH),
            "world_writable": bool(mode & stat.S_IWOTH),
        }
    except OSError:
        return None
Confidence
70% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Static analysis

No suspicious patterns detected.