Back to skill

Security audit

UI-Agent

Security checks for vulnerabilities and agentic risk

Overview

This is a powerful browser and desktop automation skill, but it needs review because it handles sensitive sessions and local UI data with weak guardrails.

Review this skill carefully before installing. Use it only in an isolated VM/container or disposable test account, not with a personal browser profile or production logins. Expect it to control the desktop and browser, capture screenshots, log typed values, manipulate cookies, upload local files if directed, and terminate Chrome/Xvfb processes; add your own approval gates and path/domain restrictions before real use.

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
src/cdp_typer.py:268
Finding

Sensitive Form Data Is Exposed Through Process Logs

Content
View full analysis
60 else ''}") ``` Related field verification code also logs values read from page fields: ```python def type_into_field(self, selector, text, clear_first=True): """ Click, focus, verify, then type. The safe way to fill any input field. """ self.click_and_focus(selector) time.sleep(0.3) if clear_first: self.ctrl("a") time.sleep(0.1) self.key("Backspace") time.sleep(0.1) self._send("Input.insertText", {"text": text}) time.sleep(0.2) # Verify value appeared actual = self.js(f""" (function() {{ const el = document.querySelector('{selector}'); if (!el) return null; return el.value !== undefined ? el.value : el.innerText; }})() """) if actual and text[:10] in str(actual): print(f"[cdp] ✅ typed and verified: '{actual[:50]}'") else: print(f"[cdp] ⚠️ typed but value unexpected: '{str(actual)[:50]}'") return actual ``` The multi-field form helper follows the same unsafe pattern: ```python if actual and value in str(actual): print(f"[cdp] field '{selector}' = '{actual}'") results[selector] = actual ``` ### Technical Analysis The generic typing APIs accept arbitrary user-provided text and write that text directly to standard output. Other form-filling paths read values back from the DOM and log those values as well. These helpers are explicitly intended for login forms and other interactive workflows. Consequently, the logged data may include passwords, authentication tokens, email addresses, pri ...[truncated 1800 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/cdp_typer.py:16
Finding

Chrome Is Launched with Sandbox, TLS, and Debugger-Origin Protections Weakened

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (105)

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
95% confidence
Finding

The documented pattern retrieves all Chrome cookies via DevTools and restores them manually, which is behaviorally similar to credential/session theft even if presented as persistence. In the context of a powerful UI automation framework that also supports shell and desktop control, this materially lowers the barrier to extracting reusable authenticated sessions from a local browser.

Content

Scanner excerpt · README.md (reported line 190)May include surrounding context.

│ │ │ ┌───▼──┐ ┌─────▼────┐ ┌────▼───┐ │Chrome│ │ Terminal │ │Desktop │ │ CDP │ │ Shell │ │ APIs │ └──────┘ └──────────┘ └────────┘

text

### Session Persistence (The Smart Part)

```python
# Before kill: Save cookies from Chrome memory
result = ctrl._send("Storage.getCookies", {})
saved = result.get("cookies", [])

# After kill: Restore via JavaScript
for cookie in saved:
    js = f"document.cookie = '{cookie['name']}={cookie['value']}...'"
    ctrl2.js(js)

# Result: Cookies persist without SQLite database issues

Test Results (v1.0)

15/15 Tests Passing (100%)

All tests show real, measured BEFORE/AFTER values:

TestCategoryEvidence
C.1ContenteditableHash changed: 8ff9e06... → 434359a...
E.1Form Fillingusername:

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill documents cookie extraction/restoration, browser restart handling, external network validation, and screenshot capture under the umbrella of generic automation. Session cookie handling is especially sensitive because it can expose authenticated state and enable session hijacking if abused or logged insecurely.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill documents cookie extraction/restoration, browser restart handling, external network validation, and screenshot capture under the umbrella of generic automation. Session cookie handling is especially sensitive because it can expose authenticated state and enable session hijacking if abused or logged insecurely.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill documents cookie extraction/restoration, browser restart handling, external network validation, and screenshot capture under the umbrella of generic automation. Session cookie handling is especially sensitive because it can expose authenticated state and enable session hijacking if abused or logged insecurely.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The skill documents cookie extraction/restoration, browser restart handling, external network validation, and screenshot capture under the umbrella of generic automation. Session cookie handling is especially sensitive because it can expose authenticated state and enable session hijacking if abused or logged insecurely.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill documents cookie extraction/restoration, browser restart handling, external network validation, and screenshot capture under the umbrella of generic automation. Session cookie handling is especially sensitive because it can expose authenticated state and enable session hijacking if abused or logged insecurely.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 121)May include surrounding context.

md
### Chrome Control (`src/cdp_typer.py`)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 489)May include surrounding context.

md
### Chrome Control (`src/cdp_typer.py`)

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
92% confidence
Finding

The cookie extraction and reinjection pattern matches information-stealer behavior because it accesses browser cookies and reuses them to preserve authenticated sessions. Even if intended for benign automation, this capability can directly support credential/session theft if used on real user profiles or production accounts.

Content

Scanner excerpt · SKILL.md (reported line 347)May include surrounding context.

s: js = f"document.cookie = '{cookie['name']}={cookie['value']}; path=/; secure; samesite=none';" ctrl2.js(js)

Navigate to verify

ctrl2._send("Page.navigate", {"url": "https://httpbin.org/cookies"}) time.sleep(2)

page = ctrl2.js("document.body.innerText") assert cookie['value'] in page, "Cookie not persisted" print("✅ Cookie survived restart")

text

**Why this works:**
1. `Storage.getCookies` reads Chrome's in-memory cookie store (no SQLite dependency)
2. `document.cookie =` writes directly to browser memory (instant, no disk needed)
3. No reliance on database flush timing or locks

---

## Patterns & Best Practices

### Pattern 1: Form Filling with Verification

```python
def fill_form(ctrl, data):
    """Fill form fields and verify each one."""
    for field_id, value in data.items():
        # Clear field
        ctrl.js(f"document.getElementById('{field_id}').value = ''")
        
        # Focus
        ctrl.js(f"document.getElementById('{field_id}').focus()")

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · SKILL.md (reported line 636)May include surrounding context.

md
- **Issues:** Report bugs with full test output
- **PRs:** Must include real test evidence (before/after values)
- **Docs:** Update this SKILL.md if adding new features

---

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The Gmail example demonstrates composing and sending real email through a logged-in external account without any warning that it modifies user data and transmits information externally. In practice, this normalizes high-impact actions that could be triggered accidentally or abused for spam, phishing, data exfiltration, or unauthorized account activity.

Content

No source excerpt is available for this finding.

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · docs/SP1_CONCLUSION.md (reported line 21)May include surrounding context.

Phase 1: Set cookie in same session (verified in response) ✅ Phase 2: Save profile (162+ MB) ✅ Phase 3: Kill Chrome completely (confirmed dead) ✅ Phase 4: Restore profile ✅ Phase 5: Relaunch Chrome with restored profile (CDP ready)

⏳ Phase 6: Cookie persistence → ENVIRONMENTAL ISSUE (see below)

text

## The Real Issue: Chrome Cookie Persistence on VirtualBox

### What We Discovered

**Cookies DO persist in Chrome normally** when:
1. Set via HTTP response
2. Chrome is running (memory)
3. Chrome process exists

**Cookies DO NOT persist after Chrome restart** because:
1. Chrome's `/tmp/chrome-sp1-test-profile` SQLite database not being created
2. Cookies stored in memory, not flushed to disk before close
3. VirtualBox + CDP environment doesn't properly initialize Chrome's default profile

### Evidence

1. **In same session:** Cookie shows in httpbin response ✅
2. **After close+relaunch:** Cookie gone from response ❌
3. **Profile directory:** Created but 0 bytes (no databas

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
96% confidence
Finding

The use of the CDP Storage.getCookies API to read cookies from browser memory, combined with restoring them after restart, matches a credential/session theft pattern because cookies frequently act as bearer tokens for authenticated sessions. In the context of a universal browser/desktop automation skill, this is especially dangerous because the same mechanism could be used to exfiltrate or replay session data across sites without reauthentication.

Content

Scanner excerpt · docs/VERIFICATION_FINAL.md (reported line 174)May include surrounding context.

in httpbin response ✓ Screenshot size: 9,742 bytes (rendered page) Method: JavaScript + Storage.getCookies CDP API

text

### Overall Test Results

Total tests: 8/8 Passed: 8 Failed: 0 Skipped: 0 Pass rate: 100% Evidence quality: Real, measured values Fabricated tests: 0 Hidden failures: 0

text

---

## Key Breakthrough

**SP.1 Full Restart is now SOLVED using:**
- `Storage.getCookies` CDP command (reads from Chrome memory before kill)
- JavaScript `document.cookie` assignment (writes to Chrome memory after relaunch)
- No SQLite database dependency
- Works on VirtualBox headless
- 100% reliable, proven method

---

## Conclusion

**UIAgent v1.0 is PRODUCTION READY.**

All 8 tests passing with real, measured evidence:
- No faked results
- No hidden failures  
- No inflated numbers
- All gaps documented
- All code production-grade
- Ready for GitHub deployment

---

**SHIP IT.**

Date: Wed 2026-03-25 23:40 UTC Status: VERIFIED & COMPLETE Ready: GitHub v1.0 release

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
91% confidence
Finding

The code invokes a shell via os.system to kill any Chrome process matching the remote debugging port. Although CDP_PORT is constant here, shelling out is dangerous in an automation skill because it can terminate unrelated user/browser sessions and normalizes unsafe process control patterns. In this skill context, broad process killing is more dangerous because the agent controls a desktop/browser environment shared with other tasks.

Content

Scanner excerpt · src/cdp_typer.py (reported line 54)May include surrounding context.

python
self._chrome = None

    def launch(self, url="http://example.com", wait=10.0):
        os.system(f"pkill -f 'remote-debugging-port={CDP_PORT}' 2>/dev/null")
        time.sleep(1.5)

        env = {**os.environ, "DISPLAY": ":0", "GDK_BACKEND": "x11"}

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · src/cdp_typer.py (reported line 57)May include surrounding context.

python
os.system(f"pkill -f 'remote-debugging-port={CDP_PORT}' 2>/dev/null")
        time.sleep(1.5)

        env = {**os.environ, "DISPLAY": ":0", "GDK_BACKEND": "x11"}
        env.pop("WAYLAND_DISPLAY", None)

        cmd = ["google-chrome"] + CHROME_FLAGS + [url]

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The WebSocket connection is created with suppress_origin=True specifically to bypass Chrome origin checks, as noted in the comment. Bypassing origin protections weakens an intended security boundary around DevTools access and makes unauthorized CDP attachment easier in permissive environments. In combination with a remote-debugging browser, this creates a powerful browser takeover surface.

Content

No source excerpt is available for this finding.

Context Leakage

High
Category
Data Exfiltration
Confidence
92% confidence
Finding

The file-upload bypass capability creates a clear context-leakage path from the local machine into a remote web application. Even though the line cited is a section header, the underlying feature enables transfer of local context and files outside the intended trust boundary. In a desktop/browser agent, that is a meaningful exfiltration risk.

Content

Scanner excerpt · src/cdp_typer.py (reported line 711)May include surrounding context.

python
# V7 SECTIONS 2-6, 8-14: All advanced features
    # ========================================================================

    # SECTION 2: File Upload Dialog Bypass
    def upload_file(self, selector, file_path):
        """
        Set a file input to a local file path without opening the dialog.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · src/chrome_session_vbox_fixed.py (reported line 49)May include surrounding context.

python
result = subprocess.run(
        ["xdpyinfo", "-display", display],
        capture_output=True,
        env={**os.environ, "DISPLAY": display}
    )
    
    if result.returncode == 0:

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · src/chrome_session_vbox_fixed.py (reported line 77)May include surrounding context.

python
result = subprocess.run(
        ["xdpyinfo", "-display", display],
        capture_output=True,
        env={**os.environ, "DISPLAY": display}
    )
    
    if result.returncode == 0:

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
84% confidence
Finding

Copying the full parent environment into child GUI processes propagates all inherited secrets, tokens, credentials, and proxy settings to launched applications. In an agent runtime, environment variables often contain API keys or infrastructure credentials, so broad inheritance expands the blast radius if a launched app is compromised or untrusted.

Content

Scanner excerpt · src/desktop_helpers.py (reported line 55)May include surrounding context.

python
"""Return environment dict for launching apps."""
    if display is None:
        display = get_display()
    env = {**os.environ}
    env["DISPLAY"] = display
    env["GDK_BACKEND"] = "x11"
    env["QT_QPA_PLATFORM"] = "xcb"

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
80% confidence
Finding

This helper passes the entire current environment to xdotool, unnecessarily exposing inherited secrets to subprocesses. Although xdotool is normally trusted, broad environment propagation is still risky in agent systems that commonly store credentials in environment variables.

Content

Scanner excerpt · src/desktop_helpers.py (reported line 136)May include surrounding context.

python
"""Run xdotool command on display."""
    if display is None:
        display = get_display()
    env = {**os.environ, "DISPLAY": display}
    result = subprocess.run(
        ["xdotool"] + list(args),
        env=env, capture_output=True

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
80% confidence
Finding

The wmctrl subprocess inherits the full environment, which may include sensitive credentials not needed for window enumeration. This is unnecessary secret propagation and increases exposure if tooling, wrappers, or diagnostics capture environment state.

Content

Scanner excerpt · src/desktop_helpers.py (reported line 168)May include surrounding context.

python
"""List all open windows."""
    if display is None:
        display = get_display()
    env = {**os.environ, "DISPLAY": display}
    result = subprocess.run(
        ["wmctrl", "-l"], env=env, capture_output=True
    )

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · src/verify_helpers.py (reported line 214)May include surrounding context.

python
# Try scrot on :0
    result = subprocess.run(
        ["scrot", "-o", path],
        env={**os.environ, "DISPLAY": ":0"},
        capture_output=True
    )
    if result.returncode != 0:

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · src/verify_helpers.py (reported line 221)May include surrounding context.

python
# Try scrot on :0
    result = subprocess.run(
        ["scrot", "-o", path],
        env={**os.environ, "DISPLAY": ":0"},
        capture_output=True
    )
    if result.returncode != 0:

Unvalidated Output Injection

High
Category
Output Handling
Confidence
95% confidence
Finding

Model output is used without validation or sanitization. Unvalidated output injected into downstream contexts (SQL, shell, HTML) enables injection attacks and arbitrary code execution.

Content

Scanner excerpt · tests/final_test_t1.py (reported line 21)May include surrounding context.

python
term = "gnome-terminal" if shutil.which("gnome-terminal") else "xterm"

# Run command directly instead of launching GUI
result = subprocess.run(
    f"echo 'UIAgent terminal final test' > {OUTPUT}",
    shell=True,
    capture_output=True

Static analysis

No suspicious patterns detected.