Back to skill

Security audit

page-behavior-audit

Security checks for vulnerabilities and agentic risk

Overview

This skill broadly matches a page-auditing purpose, but it exposes high-impact browser and data-capture behavior with weak scoping and unsafe defaults.

Install only in a controlled environment. Do not expose the webhook to untrusted callers, restrict outbound and internal network access for the browser, avoid auditing authenticated or sensitive pages unless HAR and screenshot retention are acceptable, remove --no-sandbox before processing untrusted pages, pin installer versions, and avoid the optional sudo/system install unless you have reviewed the exact files being installed.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (6)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
skill.yaml:61
Finding
Unauthenticated webhook permits unrestricted browser navigation and SSRF<![CDATA[ ## Vulnerability Details **File Location**: `skill.yaml:5-9`, `skill.yaml:20-31`, and `skill.yaml:61-68` **Vulnerability Type**: Unauthenticated SSRF through attacker-controlled browser navigation **Risk Level**: High ### Vulnerable Code ```yaml trigger: type: "webhook" path: "/api/audit/scan" method: "POST" ``` ```yaml ui: runnable: true input_schema: type: "object" properties: url: type: "string" format: "uri" description: "Target URL to audit (must be HTTP/HTTPS)" include_har: type: "boolean" default: true required: - "url" ``` ```yaml - step: "navigate-and-wait" action: "builtin.navigate" depends_on: - "launch-browser" config: url: "{{ .input.url }}" wait_until: "networkidle0" timeout: "{{ .input.timeout | default 15000 }}" ``` ### Technical Analysis The POST webhook accepts a caller-controlled URI and passes it directly to the browser navigation action. No webhook authentication, authorization, hostname allowlist, protocol enforcement, address-range validation, redirect validation, or DNS-rebinding defense is defined. Although the input description says the target must use HTTP or HTTPS, the schema only specifies the generic `uri` format. More importantly, even restricting the initial URL to HTTP or HTTPS would not prevent access to loopback, private, link-local, or cloud metadata addresses. Because the browser operates from the OpenClaw host's network context, the endpoint can act as a server-side request forgery primitive. Redirects and DNS changes must also be checked, because validation of only the initial textual hostname would be insufficient. ### Attack Path 1. An attacker sends a POST request to `/api/audit/scan`. 2. The request supplies a URL resolving to a loopback, private-network, link-local, cloud metadata, or otherwise internal destination. 3. The skill passes the URL directly to `builtin.navigate`. 4. The browser requests ...[truncated 726 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Require strong authentication and authorization for the webhook. - Restrict accepted schemes explicitly to `http` and `https`. - Resolve the hostname before navigation and reject loopback, private, link-local, multicast, reserved, and cloud metadata address ranges for both IPv4 and IPv6. - Repeat destination validation after every redirect and connection resolution. - Protect against DNS rebinding by binding validation to the addresses actually used for each connection. - Use an explicit destination allowlist where operationally possible. - Place the browser in a network-isolated environment with deny-by-default egress rules. - Apply request rate limits, concurrency limits, and audit logging. - Avoid exposing captured content to the caller unless separately authorized. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
skill.yaml:51
Finding
Browser sandbox is disabled while processing attacker-selected web content<![CDATA[ ## Vulnerability Details **File Location**: `skill.yaml:51-58` **Vulnerability Type**: Unsafe browser isolation configuration **Risk Level**: High ### Vulnerable Code ```yaml - step: "launch-browser" action: "builtin.launchBrowser" config: headless: true args: - "--no-sandbox" - "--disable-gpu" - "--disable-dev-shm-usage" - "--user-data-dir=/tmp/openclaw-$(uuid)" ``` ### Technical Analysis The browser is launched with `--no-sandbox`, disabling a critical security boundary used to contain compromised renderer processes. This browser processes a URL selected by a remote webhook caller, so it must be treated as directly exposed to hostile HTML, JavaScript, media, and browser exploit content. Disabling the sandbox does not itself create a browser memory-corruption vulnerability. However, if an attacker exploits an applicable browser vulnerability, the absence of sandboxing substantially reduces the additional work required to affect the host process or environment. This configuration also contradicts the project's claim in `SKILL.md` that browser execution is sandbox-isolated. ### Attack Path 1. An attacker hosts a malicious page containing content that exploits a vulnerability in the deployed browser version. 2. The attacker submits that page's URL to the audit webhook. 3. The skill launches the browser with `--no-sandbox`. 4. The browser loads and executes the hostile page. 5. If the browser exploit succeeds, the attacker operates without the normal browser sandbox boundary. 6. The resulting access is constrained only by the operating-system account and any external container or host isolation. ### Impact Assessment Successful exploitation may provide access to files, environment variables, network services, and processes available to the account running OpenClaw. If OpenClaw runs with elevated privileges or broad filesystem access, the compromise scope increases accordingly. The exact privileges depend on de ...[truncated 67 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove the `--no-sandbox` browser argument. - Run the browser as a dedicated, unprivileged operating-system user. - Isolate each scan in a short-lived container or virtual machine. - Use a read-only root filesystem and expose only a dedicated artifact directory. - Drop Linux capabilities and enable seccomp, AppArmor, or SELinux restrictions. - Apply strict memory, CPU, process, and execution-time limits. - Restrict network egress independently of application-level URL validation. - Keep the browser and automation runtime patched. - Update the documentation so isolation claims accurately reflect the deployed controls. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
.claude/settings.local.json:1
Finding
Project configuration grants unrestricted Bash execution<![CDATA[ ## Vulnerability Details **File Location**: `.claude/settings.local.json:1-9` **Vulnerability Type**: Excessive local agent tool permissions **Risk Level**: High ### Vulnerable Code ```json { "permissions": { "allow": [ "Bash(chmod:*)", "Bash(./verify.sh:*)", "Bash(bash:*)" ] } } ``` ### Technical Analysis The permission rule `Bash(bash:*)` allows arbitrary arguments to the Bash interpreter and therefore provides a general-purpose local command-execution capability. It is substantially broader than the permissions required to describe or run a page-auditing workflow. The separate `chmod` permission allows file-mode changes, while `./verify.sh` is referenced despite not being present in the audited project. If the hosting agent automatically trusts repository-local settings, an agent operating in this project may invoke arbitrary shell commands without an additional permission decision. ### Attack Path 1. The project is opened in an environment that honors `.claude/settings.local.json`. 2. The local permission configuration grants calls matching `Bash(bash:*)`. 3. An agent action, malicious instruction, or compromised workflow invokes Bash with attacker-selected arguments. 4. Bash executes commands with the privileges of the user running the agent. 5. Those commands may read or modify files, invoke network utilities, execute installed programs, or alter file permissions. ### Impact Assessment The effective privilege is arbitrary command execution as the local agent user. The accessible scope includes that user's files, credentials, environment variables, network access, and any delegated privileges. Additional impact is possible if the user has passwordless privilege escalation or sensitive mounted resources. No evidence in the audited files proves that these permissions are automatically activated in every deployment. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Remove `Bash(bash:*)`. - Remove `Bash(chmod:*)` unless a narrowly defined installation operation demonstrably requires it. - Remove the `Bash(./verify.sh:*)` permission or include and audit the referenced script. - Permit only exact commands with fixed arguments needed by the project. - Require interactive approval for commands that execute scripts, change permissions, access secrets, or use the network. - Do not distribute developer-specific local permission settings as part of the package. - Ensure the agent runtime does not automatically trust repository-controlled permission files. ]]>

T08 · Insecure Dependencies

Warning
Location
README.md:5
Finding
Installation documentation executes an unpinned mutable package release<![CDATA[ ## Vulnerability Details **File Location**: `README.md:5-11` **Vulnerability Type**: Unpinned third-party package execution **Risk Level**: Medium ### Vulnerable Code ```markdown ## Installation ```bash npx clawhub@latest install page-behavior-audit ``` ``` ### Technical Analysis The documented installation command asks `npx` to retrieve and execute the package associated with the mutable `latest` tag. The effective code executed by this command can change after the skill has been reviewed, without any change to this repository. No exact package version, lockfile, integrity digest, or other artifact-verification mechanism is specified. This exposes users to future malicious releases, publisher-account compromise, or registry compromise. The audit did not establish that the current `clawhub` package is malicious; the issue is the mutable and unverified execution path. ### Attack Path 1. A user follows the installation command from the README. 2. `npx` resolves `clawhub@latest` through the configured package registry. 3. A compromised publisher, registry, or malicious future release changes what `latest` references. 4. `npx` downloads and executes that package on the user's system. 5. The substituted package runs with the user's privileges before or during skill installation. ### Impact Assessment A compromised installation package could execute arbitrary commands as the installing user, access user-readable files and environment variables, modify the installation, or contact external systems. If installation is performed under an elevated account, the impact may extend system-wide. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Pin `clawhub` to a reviewed exact version instead of `@latest`. - Publish and verify an integrity digest or signed release artifact. - Document the expected registry and publisher identity. - Use a lockfile or equivalent immutable dependency metadata where supported. - Review new versions before updating the documented pin. - In high-assurance deployments, download the artifact separately, verify its signature or digest, and only then execute it. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
skill.yaml:34
Finding
Policy signature verification is claimed but not implemented<![CDATA[ ## Vulnerability Details **File Location**: `skill.yaml:34-44` and `skill.yaml:86-93` **Vulnerability Type**: Missing integrity and authenticity verification **Risk Level**: Medium ### Vulnerable Code ```yaml policy: badwords: hash_list: # sha256 hashes for exact match keywords (64 hex chars) - "sha256:5e884898da28047151d0e56f8dc6292773607d2d72aa89a73c1b472a0765512e" - "sha256:2c74fd17edafd80e8447b0d4f3a7d62e86d5f3514d105a93e15596c8a1a1319f" - "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08" regex_hash_list: # sha256 hashes for regex patterns (64 hex chars) - "sha256:1f8ac10f7420b57ee1e8d77fec5c82892bb2d50e70631fe5bcb57cf342498114" source: "verified:internal://policy/content-safety/2026-q1" updated_at: "2026-02-10T08:00:00Z" signature: "ed25519:A1B2C3D4E5F6789012345678901234567890123456789012345678901234567890ABCDEF1234567890" verification_url: "https://your-org.example.com/policies/verify" ``` ```yaml - step: "check-text-policy" action: "builtin.checkTextPolicy" depends_on: - "extract-content" config: text: "{{ .steps.extract-content.output.text }}" links: "{{ .steps.extract-content.output.links }}" ``` ### Technical Analysis The configuration includes an alleged Ed25519 signature and a verification URL, but the workflow contains no verification step, no trusted public key, no canonicalization rules, and no failure behavior for an invalid signature. The verification URL also uses the placeholder domain `your-org.example.com`. The policy-checking step invokes `builtin.checkTextPolicy` directly without first establishing the integrity or authenticity of the configured policy. Consequently, the supplied signature is metadata rather than an enforceable security control. Hashing individual policy terms is not a substitute for signing and verifying the complete policy. A party able to alter the skill configuration could replace both the hashes and ...[truncated 838 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Define an explicit canonical representation of the complete signed policy. - Include or securely provision a trusted Ed25519 public key. - Add a verification step before any policy is used. - Fail closed if the signature is malformed, invalid, expired, or cannot be verified. - Bind relevant metadata, including the policy version and update timestamp, into the signed content. - Replace the placeholder verification URL with an authenticated production endpoint if remote verification is necessary. - Protect key rotation through a separately trusted mechanism. - Remove the Ed25519 verification claim from documentation until verification is actually enforced. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
skill.yaml:111
Finding
HAR files are exported even when the caller disables HAR capture<![CDATA[ ## Vulnerability Details **File Location**: `skill.yaml:27-29` and `skill.yaml:111-117` **Vulnerability Type**: Unconditional sensitive browsing-data persistence **Risk Level**: Medium ### Vulnerable Code ```yaml include_har: type: "boolean" default: true ``` ```yaml - step: "export-har" action: "builtin.harExport" depends_on: - "navigate-and-wait" config: path: "{{ env.OPENCLAW_AUDIT_DIR }}/$(date +%s)_{{ sha256 .input.url }}.har" ``` ### Technical Analysis The input schema exposes `include_har` as a caller-controlled boolean, but the `export-har` step has no condition referencing that value. Therefore, the step executes regardless of whether the caller submits `include_har: false`. HAR files can contain sensitive URLs, query parameters, request and response headers, cookies, authorization data, request bodies, and response metadata. The configuration also provides no explicit redaction, retention, quota, or file-permission controls. ### Attack Path 1. A caller submits an audit request with `include_har: false`. 2. The skill navigates to the requested page. 3. The unconditional `export-har` step runs after navigation. 4. Network-transaction information is written beneath `OPENCLAW_AUDIT_DIR`. 5. Any user or process with access to that directory may inspect the retained data. ### Impact Assessment Sensitive browsing and authentication data may be persisted contrary to the caller's explicit selection. Exposure is limited to information captured by the HAR implementation and principals able to read the audit directory. Repeated requests may also consume storage because no retention or quota control is shown. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Add a condition such as `if: "{{ .input.include_har }}"` to the export step. - Ensure downstream aggregation handles the absence of a HAR path safely. - Redact cookies, authorization headers, sensitive query parameters, and confidential request or response bodies. - Create output files with owner-only permissions. - Use a dedicated, non-world-readable artifact directory. - Define automatic retention and secure deletion policies. - Apply per-request and total-storage quotas. - Document exactly what information HAR capture records and obtain appropriate caller consent. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (21)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared purpose is a page-behavior audit, but the detected behavior includes installation-like actions, directory creation, file writes, and invocation of privileged or system commands such as sudo, mkdir, cp, grep, and openclaw. A mismatch between declared and actual behavior is dangerous because it can mislead operators into approving a skill that performs broader system modification than expected.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The skill is described as a page auditing tool, but the README requires a `WECOM_WEBHOOK_URL`, indicating outbound communication to a third-party endpoint not reflected in the stated behavior. This discrepancy undermines transparency and could enable exfiltration of scan results or metadata to an external service without users fully understanding that network egress is part of the skill's operation.

External Transmission

Medium
Category
Data Exfiltration
Content
## Usage

```bash
curl -X POST http://localhost:8080/api/audit/scan \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com"}'
```
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
## Usage

```bash
curl -X POST http://localhost:8080/api/audit/scan \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com"}'
```
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Lp3

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding
The skill advertises webhook-triggered auditing, screenshots, HAR export, and CLI execution, which imply execution and file/network side effects, but it declares no explicit tool scope or permissions. That ambiguity can cause the host to grant broader-than-expected capabilities or prevent reviewers from understanding that shell/file/network actions are required, increasing the risk of unsafe execution.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
Screenshots, HAR files, and audit logs can capture credentials, tokens, personal data, internal URLs, and page contents, and the skill description does not clearly warn users that this data is stored on disk. In a web-auditing context this is especially sensitive because the audited pages may be authenticated, internal, or otherwise confidential.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill sends critical findings to an external WeCom webhook but does not clearly warn users that audit-derived data may leave the local environment. External transmission raises confidentiality and compliance concerns, especially if alert payloads include URLs, page content, internal hostnames, or other sensitive evidence from scans.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
*)
            echo -e "${RED}Unknown option: $1${NC}"
            echo "Usage: $0 [--user|--system]"
            echo "  --user   : Install to user directory (default, no sudo required)"
            echo "  --system : Install to system directory (requires sudo)"
            exit 1
            ;;
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
*)
            echo -e "${RED}Unknown option: $1${NC}"
            echo "Usage: $0 [--user|--system]"
            echo "  --user   : Install to user directory (default, no sudo required)"
            echo "  --system : Install to system directory (requires sudo)"
            exit 1
            ;;
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
*)
            echo -e "${RED}Unknown option: $1${NC}"
            echo "Usage: $0 [--user|--system]"
            echo "  --user   : Install to user directory (default, no sudo required)"
            echo "  --system : Install to system directory (requires sudo)"
            exit 1
            ;;
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
*)
            echo -e "${RED}Unknown option: $1${NC}"
            echo "Usage: $0 [--user|--system]"
            echo "  --user   : Install to user directory (default, no sudo required)"
            echo "  --system : Install to system directory (requires sudo)"
            exit 1
            ;;
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
*)
            echo -e "${RED}Unknown option: $1${NC}"
            echo "Usage: $0 [--user|--system]"
            echo "  --user   : Install to user directory (default, no sudo required)"
            echo "  --system : Install to system directory (requires sudo)"
            exit 1
            ;;
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
if [ "$MANUAL_INSTALL" = true ]; then
    echo "Installing skill manually..."
    if [ "$USE_SUDO" = true ]; then
        sudo cp skill.yaml "$SKILL_FILE" || {
            echo -e "${RED}Failed to copy skill.yaml${NC}"
            exit 1
        }
Confidence
72% confidence
Finding
In system mode, the script copies a local skill.yaml into a privileged destination with sudo without validating the source file or constraining the destination beyond environment-derived paths. If an attacker can replace skill.yaml in the working directory or influence OPENCLAW_HOME before execution, they may cause installation of a malicious skill with elevated trust/persistence.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
openclaw skill install skill.yaml || {
        echo -e "${RED}Failed to install via CLI, trying manual install...${NC}"
        if [ "$USE_SUDO" = true ]; then
            sudo cp skill.yaml "$SKILL_FILE"
        else
            cp skill.yaml "$SKILL_FILE"
        fi
Confidence
75% confidence
Finding
The fallback path again performs sudo cp of skill.yaml into the system skills directory after a CLI failure, with no integrity check on the source file and potential reliance on environment-controlled destination paths. This broadens the attack surface because privileged installation occurs even when the primary mechanism fails, making tampering with the local package or path selection more impactful.

External Transmission

Medium
Category
Data Exfiltration
Content
echo ""
echo "Usage:"
echo "  1. Via Webhook:"
echo "     curl -X POST http://localhost:8080/api/audit/scan \\"
echo "       -H 'Content-Type: application/json' \\"
echo "       -d '{\"url\": \"https://example.com\"}'"
echo ""
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The skill exposes a POST webhook that accepts an arbitrary URL and then launches a browser to visit it, with no visible authentication, allowlisting, or trigger constraints in the manifest. That makes the skill effectively a remotely triggerable browsing/probing primitive, which can be abused for SSRF-like internal access, scanning, or driving the agent to collect artifacts from attacker-specified destinations.

Description-Behavior Mismatch

Medium
Confidence
89% confidence
Finding
The skill presents itself as a hashed-policy/CSP-compliant page auditor, but it also captures full-page screenshots and HAR archives, which can collect sensitive page content, tokens in URLs, headers, and third-party network metadata unrelated to simple text-policy auditing. In this context, the extra collection and persistence materially expand data exposure and retention risk, especially because the target URL is attacker-controlled input via the webhook.

Context-Inappropriate Capability

Medium
Confidence
82% confidence
Finding
The skill includes an outbound webhook capability that can transmit aggregated audit results to an external WeCom endpoint, but that egress is not tightly scoped or justified by the basic auditing function. Since the report may include alert details, paths to artifacts, and potentially sensitive findings derived from arbitrary target pages, this creates an avoidable exfiltration channel if misconfigured or abused.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The post-install instructions direct users to configure `WECOM_WEBHOOK_URL` with a fixed `qyapi.weixin.qq.com` endpoint, which bakes in a specific communication platform and locale context. There is no indication that this locale-specific choice is optional, user-selectable, or justified as region-specific behavior.

Natural-Language Policy Violations

Low
Confidence
63% confidence
Finding
The fixed template name "FRONTEND_BEHAVIOR_ALERT" suggests alerts may be sent in a predetermined language/locale, and the manifest provides no user opt-in or locale-selection mechanism. Because language/locale policy applies to all file types, a hardcoded notification format without documented choice can be a policy concern.

Static analysis

No suspicious patterns detected.