Back to skill

Security audit

OpenClaw Security Audit

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent read-only OpenClaw security audit skill, but it can print unredacted secrets from proxy configuration files and has one audit reliability weakness.

Install only if you are comfortable with a local audit tool reading OpenClaw-related config paths and reporting host state. Treat its output as potentially sensitive: proxy findings may include live credentials, so avoid sharing transcripts or logs until those values are redacted. The symlink check should not be treated as definitive until its path-containment logic is fixed.

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

Warning
Location
audit_proxy/audit_proxy.py:7
Finding

Proxy Audit Discloses Plaintext Credentials in Its Output

Content
View full analysis

Vulnerability Details

File Location: audit_proxy/audit_proxy.py, lines 7–19
Vulnerability Type: Plaintext sensitive-data exposure
Risk Level: Medium

Vulnerable Code

python
def scan_text_for_patterns(text):
    patterns = {
        "url_credential_leak": [r"token=", r"gatewayUrl=", r"key=", r"secret=", r"Authorization"],
        "risky_proxy_to_18789": [r"reverse_proxy\s+(127\.0\.0\.1|localhost):18789", r"proxy_pass\s+http://(127\.0\.0\.1|localhost):18789"]
    }
    findings = []
    lines = text.splitlines()
    for i, line in enumerate(lines, 1):
        for risk_type, ps in patterns.items():
            for p in ps:
                if re.search(p, line, re.IGNORECASE):
                    findings.append(f"[{risk_type}] L{i}: {line.strip()}")
    return findings

Technical Analysis

The scanner deliberately searches proxy configuration lines for credential-related markers such as token=, key=, secret=, and Authorization. When a match is found, it copies the entire source line into the finding without masking the sensitive value.

The findings are subsequently serialized as JSON and written to standard output. As a result, credentials stored in readable Nginx or Caddy configuration files can be propagated into agent context, command logs, audit transcripts, CI logs, or downstream reports. This transforms a credential-detection feature into a secondary disclosure channel.

Attack Path

  1. A Caddy or Nginx configuration contains a credential on a line matching one of the configured patterns, such as:
    nginx
    proxy_set_header Authorization "Bearer sensitive-token";
    
  2. The user or agent invokes audit_proxy.py.
  3. The scanner reads the configuration and detects Authorization.
  4. The complete line, including the credential, is added to findings.
  5. The unredacted finding is emitted through standard output as JSON.
  6. Any system retaining or displaying tool output receives a copy of the credential.

...[truncated 534 chars]

Remediation
View remediation

Remediation Suggestions

  • Never include the complete matching configuration line in output.
  • Return only the file path, line number, matched credential type, and a sanitized excerpt.
  • Redact values following credential-related keys and authorization schemes before serialization.
  • Apply masking conservatively, including quoted values, URL query parameters, headers, and whitespace-separated assignments.
  • Avoid returning a fixed portion of the original line unless it has first passed through a robust redaction function.
  • Add tests covering bearer tokens, basic authorization headers, URL credentials, quoted secrets, and mixed-case key names.
  • Ensure downstream audit logs also apply secret redaction.

A safer finding format would be:

python
findings.append({
    "risk_type": risk_type,
    "line": i,
    "detail": "Potential credential detected; value redacted"
})

T09 · Insecure Skill Coding Practices

Warning
Location
check_workspace_symlinks/check_workspace_symlinks.py:18
Finding

String-Prefix Validation Fails to Detect Some Workspace-Escaping Symlinks

Content
View full analysis

Vulnerability Details

File Location: check_workspace_symlinks/check_workspace_symlinks.py, lines 18–31
Vulnerability Type: Incorrect path-containment validation
Risk Level: Medium

Vulnerable Code

python
for root, dirs, files in os.walk(workspace_dir):
    for name in dirs + files:
        file_path = os.path.join(root, name)
        # Check whether the path is a symbolic link
        if os.path.islink(file_path):
            try:
                # Resolve the link to its absolute target
                target_path = os.path.realpath(file_path)

                # Incorrect containment check based on a textual prefix
                if not target_path.startswith(os.path.realpath(workspace_dir)):
                    dangerous_links.append(
                        f"{file_path} -> [escape target] -> {target_path}"
                    )
            except Exception:
                pass

Technical Analysis

The scanner determines whether a symlink target remains inside the workspace by using str.startswith(). Filesystem containment cannot safely be established through textual prefix comparison.

For example, if the workspace resolves to:

text
/home/user/.openclaw/workspace

then this external sibling path also passes the prefix check:

text
/home/user/.openclaw/workspace-escape/secret.json

Although the second path is outside the workspace directory, its string representation begins with the workspace string. The scanner therefore omits the link from dangerous_links and may return a clean result.

This is a false-negative security-control failure. The scanner itself does not follow the link to read or modify its target, but it can incorrectly assure downstream users or automation that no escaping symlink exists.

Attack Path

  1. An attacker or compromised process creates an external sibling directory whose name begins with the workspace path’s final component, such as:
    text
    /home/user/.openclaw/work
    

...[truncated 1017 chars]

Remediation
View remediation

Remediation Suggestions

  • Resolve the workspace once before traversal.
  • Use filesystem-aware containment validation with os.path.commonpath() rather than textual prefix comparison.
  • Handle ValueError explicitly for paths on different drives or incompatible roots and classify such targets as outside the workspace.
  • Consider using pathlib.Path.resolve() and Path.is_relative_to() on supported Python versions.
  • Report resolution errors instead of silently ignoring all exceptions.
  • Add regression tests for sibling-prefix paths, .. components, nested links, broken links, relative links, and cross-device paths.

Example correction:

python
workspace_real = os.path.realpath(workspace_dir)
target_real = os.path.realpath(file_path)

try:
    inside_workspace = (
        os.path.commonpath([workspace_real, target_real]) == workspace_real
    )
except ValueError:
    inside_workspace = False

if not inside_workspace:
    dangerous_links.append(
        f"{file_path} -> [escape target] -> {target_real}"
    )
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (30)

Docker Socket Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Potential security issue detected. Manual review is recommended.

Content

Scanner excerpt · audit_sandbox_config/audit_sandbox_config.md (reported line 7)May include surrounding context.

md
排查官方文档中警告的常见沙箱逃逸和权限滥用风险:
1. **沙箱模式**: 检查 `agents.defaults.sandbox.mode` 是否处于危险的 "off" 状态(这会导致所有命令直接在宿主机执行)。
2. **工作区越权**: 检查 `workspaceAccess` 是否被过度授权为 "rw"(读写模式),官方建议默认为 "none" 或 "ro"(只读)。
3. **高危挂载 (Binds)**: 扫描 `sandbox.docker.binds` 数组,检查是否将宿主机的敏感目录(如 `/var/run/docker.sock`, `/etc`, `/root`)以 "rw" 模式挂载到了沙箱内部,这会导致直接的容器逃逸。
4. **网络暴露**: 检查是否为不需要联网的沙箱修改了默认的 `network: "none"`。

# Parameters:

Docker Socket Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Potential security issue detected. Manual review is recommended.

Content

Scanner excerpt · audit_sandbox_config/audit_sandbox_config.py (reported line 34)May include surrounding context.

python
排查官方文档中警告的常见沙箱逃逸和权限滥用风险:
1. **沙箱模式**: 检查 `agents.defaults.sandbox.mode` 是否处于危险的 "off" 状态(这会导致所有命令直接在宿主机执行)。
2. **工作区越权**: 检查 `workspaceAccess` 是否被过度授权为 "rw"(读写模式),官方建议默认为 "none" 或 "ro"(只读)。
3. **高危挂载 (Binds)**: 扫描 `sandbox.docker.binds` 数组,检查是否将宿主机的敏感目录(如 `/var/run/docker.sock`, `/etc`, `/root`)以 "rw" 模式挂载到了沙箱内部,这会导致直接的容器逃逸。
4. **网络暴露**: 检查是否为不需要联网的沙箱修改了默认的 `network: "none"`。

# Parameters:

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill file is written entirely in Chinese and specifies communication style and output requirements in Chinese, but it does not state that language selection depends on user preference. This creates a natural-language policy concern because it effectively constrains the interaction language without explicit user opt-in or documented locale justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This Python file contains natural-language comments and emitted result strings entirely in Chinese, including the primary findings users will receive. The file does not offer any language choice or explain that it is intentionally limited to a Chinese-speaking or region-specific context, which violates the locale-choice policy for natural-language behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill's entire natural-language description is written only in Chinese, with no indication that users may choose another language or that the skill is intended solely for a Chinese-speaking or region-specific context. This creates a language/locale policy concern because it implicitly constrains use to a specific language without opt-in or justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The fallback finding string is hard-coded in Chinese, which imposes a specific language on users regardless of their locale or preferences. The file provides no opt-in, language selection, or justification that this tool is intended only for a Chinese-speaking or region-specific environment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The entire skill description, parameters, and return-value documentation are written only in Chinese, with no indication that language choice is optional or that the skill is intended exclusively for a Chinese-speaking or region-specific context. This creates a natural-language locale constraint that is not opt-in and may violate organizational language policy requirements.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file's comments and all user-facing findings/messages are written in Chinese, including the final printed results, with no indication that language is configurable or that the skill is region-specific. This creates a language/locale policy issue because the skill effectively forces a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The user-facing description, parameters, and return information are entirely written in Chinese, which imposes a specific language on users without offering a language choice or documenting a justified locale restriction. This matches the policy category for language or locale constraints that are not opt-in.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · check_docker_ports/check_docker_ports.py (reported line 8)May include surrounding context.

python
def main():
    result = {"status": "unknown", "docker_info": ""}
    try:
        p = subprocess.run(
            ["docker", "ps", "--format", "{{.Names}}\\t{{.Ports}}"],
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code returns user-facing status messages in Chinese only, such as '当前没有运行中的 Docker 容器。' and '系统中未找到 docker 命令。' There is no indication that the skill is China-specific or that users can choose their language, which creates a locale-policy issue under the natural-language policy rules.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The entire user-facing skill description is written only in Chinese, with no indication that language choice is configurable or that the skill is intended solely for a Chinese-speaking or region-specific context. This can violate language/locale policy when users are not given an explicit opt-in or alternative language option.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The entire skill description is written in Chinese and instructs the agent to summarize command output to the user in that language context, with no opt-in or note that the skill is intended only for Chinese-language users. This can violate language/locale policy when a skill imposes a specific language without user choice or documented regional justification.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · check_gateway/check_gateway.py (reported line 9)May include surrounding context.

python
def main():
    result = {"status": "unknown", "output": ""}
    try:
        p = subprocess.run(
            ["openclaw", "gateway", "status"],
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code returns human-readable status messages such as "无输出" and error text in Chinese, which imposes a specific language on users and downstream agents. The policy for natural-language content requires either offering a language/locale choice or clearly documenting a justified locale constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The entire skill description is written only in Chinese, including the operational description and return-value documentation. Under the stated policy, a language-specific constraint should either offer user opt-in/choice or be clearly justified as region-specific; neither is present here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The natural-language content describing the skill's behavior, parameters, and return values is entirely in Chinese. Per the policy, forcing a specific language without offering the user a language or locale choice is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Multiple comments and user-visible error strings are written only in Chinese, which imposes a specific language/locale without any user opt-in or explanation. The policy requires avoiding forced language constraints unless the skill offers a choice or documents a justified regional scope.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · live_sandbox_explain/live_sandbox_explain.py (reported line 10)May include surrounding context.

python
try:
        # 执行官方诊断命令
        p = subprocess.run(
            ["openclaw", "sandbox", "explain"],
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The entire skill description, parameters, and return documentation are written only in Chinese, which indicates a language-specific constraint without any user opt-in or documented locale justification. The policy for natural-language violations says to flag skills that force a specific language unless they offer a choice or clearly justify the locale restriction.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · openclaw_security_audit/openclaw_security_audit.py (reported line 27)May include surrounding context.

python
try:
        # 执行命令
        p = subprocess.run(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scan_ports/scan_ports.py (reported line 10)May include surrounding context.

python
result = {"status": "unknown", "tool_used": "", "raw_output": ""}
    try:
        # 优先使用 ss 命令
        p = subprocess.run(["ss", "-lntup"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, timeout=10)
        if p.returncode == 0:
            result.update({"status": "success", "tool_used": "ss", "raw_output": p.stdout.strip()})
        else:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scan_ports/scan_ports.py (reported line 15)May include surrounding context.

python
result.update({"status": "success", "tool_used": "ss", "raw_output": p.stdout.strip()})
        else:
            # 退回使用 netstat
            p2 = subprocess.run(["netstat", "-an"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, timeout=10)
            result.update({"status": "success", "tool_used": "netstat", "raw_output": p2.stdout.strip()})
    except Exception as e:
        result.update({"status": "error", "raw_output": f"端口扫描执行异常: {str(e)}"})

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The natural-language description, parameters, and return details are presented exclusively in Chinese. This can constitute a language/locale policy issue when the skill forces a specific language without offering the user a choice or documenting a justified locale constraint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

This code accesses the OPENCLAW_WORKSPACE environment variable to determine where to read configuration from. For code files, access to sensitive environment variables or environment-derived configuration should have some visible disclosure such as a comment, docstring, or user-facing message; this line has none nearby.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.