Back to skill

Security audit

ANSIClaw

Security checks for vulnerabilities and agentic risk

Overview

This skill is an ANSI-art tool, but its bundled scripts can write fixed output files to Desktop/Documents without collision checks or clear user control.

Review before installing. The skill's local Clawbius API use is expected, but only run scripts you recognize and confirm output paths first. Watch for files named `monarch_butterfly`, `field`, or `flower_v2` on Desktop/Documents because reruns may overwrite those outputs. Prefer changing scripts to save into the skill's output folder with versioned filenames.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (4)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:19
Finding
Unpinned Third-Party Dependency Installation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:19` **Vulnerability Type**: Unpinned third-party dependency and mutable supply-chain input **Risk Level**: Medium ### Vulnerable Code ```text - Python 'requests' (pip install requests) for scripting API calls. ``` ### Technical Analysis The Skill instructs users to install `requests` without specifying an exact version, cryptographic hashes, a lock file, or an explicitly trusted package index. The artifact selected by this command can therefore change after the Skill has been reviewed. The effective package source also depends on the user's `pip` configuration. A compromised package release, package index, distribution account, or configured mirror could cause unreviewed code to be installed. Python packages can execute code during installation or whenever imported by the bundled drawing scripts. No evidence indicates that the legitimate `requests` package is malicious. The vulnerability is the absence of dependency pinning and artifact verification. ### Attack Path 1. An operator follows the prerequisite in `SKILL.md`. 2. The operator runs `pip install requests`. 3. `pip` resolves an artifact through the operator's configured package index or mirror. 4. An attacker who has compromised that distribution channel supplies a malicious or altered artifact. 5. The artifact executes during installation or when one of the scripts imports `requests`. 6. The payload runs with the permissions of the account executing `pip` or the drawing script. ### Impact Assessment Successful exploitation could execute arbitrary Python code with the current user's privileges. This may expose files, environment variables, API credentials available to the process, and any local services accessible by that user. The Skill itself does not request elevated privileges, so the direct scope is normally limited to the invoking user account. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Add a reviewed dependency lock file containing exact direct and transitive versions. - Include cryptographic hashes for every permitted distribution artifact. - Install dependencies with a command such as: ```bash python -m pip install --require-hashes -r requirements.txt ``` - Document an explicitly trusted package index rather than relying silently on user-level `pip` configuration. - Run the Skill in a dedicated virtual environment with only the dependencies it requires. - Add automated dependency auditing and controlled update review to the release process. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/draw_butterfly.py:313
Finding
Butterfly Script Can Overwrite Fixed Desktop Output Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/draw_butterfly.py:313-319` **Vulnerability Type**: Unchecked deterministic output paths **Risk Level**: Medium ### Vulnerable Code ```python print("Saving ANS file...") ans_path = os.path.expanduser("~/Desktop/monarch_butterfly.ans") result = post("/api/file/save-as", {"path": ans_path}) print(f" ANS: {result}") print("Exporting PNG...") png_path = os.path.expanduser("~/Desktop/monarch_butterfly.png") result = post("/api/file/export/png", {"path": png_path}) ``` ### Technical Analysis The script saves and exports to deterministic paths under the user's Desktop without checking whether either destination already exists. Re-running the script sends the same paths to Clawbius, allowing the service's save and export operations to replace existing content if those endpoints permit replacement. This behavior contradicts the non-overwrite requirement in `SKILL.md`, which requires versioned filenames unless the operator explicitly authorizes replacement. It also writes outside the Skill's designated output directory. ### Attack Path 1. The user already has `~/Desktop/monarch_butterfly.ans` or `~/Desktop/monarch_butterfly.png`. 2. The user or agent invokes `draw_butterfly.py`. 3. The script creates the artwork and submits the fixed existing paths to the local Clawbius API. 4. Clawbius saves or exports to those destinations. 5. If Clawbius permits replacement, the previous files are overwritten without confirmation or backup. ### Impact Assessment The issue can cause loss or corruption of files at the two fixed Desktop paths. It does not provide a demonstrated privilege escalation: writes occur through Clawbius with the filesystem permissions of the Clawbius process. The affected scope is therefore limited to destinations writable by that process. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Save outputs under the Skill's designated `outputs/` directory. - Check for destination existence before calling the API. - Allocate a unique versioned name such as `monarch_butterfly_v1.ans`, incrementing the version when a collision occurs. - Use the same unique stem for the corresponding PNG. - Where possible, reserve the chosen filename atomically to prevent time-of-check/time-of-use races. - Require explicit operator confirmation before replacing an existing file. - Treat an API response indicating an existing destination as an error rather than retrying destructively. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/draw_field.py:193
Finding
Field Script Can Overwrite Fixed Desktop Output Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/draw_field.py:193-194` **Vulnerability Type**: Unchecked deterministic output paths **Risk Level**: Medium ### Vulnerable Code ```python post("/api/file/save-as", {"path": os.path.expanduser("~/Desktop/field.ans")}) post("/api/file/export/png",{"path": os.path.expanduser("~/Desktop/field.png")}) ``` ### Technical Analysis The script submits fixed Desktop destinations to Clawbius without checking for existing files, creating backups, generating versioned names, or obtaining replacement approval. Every execution uses the same `.ans` and `.png` destinations. This violates the Skill's documented rule against overwriting existing ANSI files without explicit operator authorization and bypasses its designated output directory. ### Attack Path 1. A file exists at `~/Desktop/field.ans` or `~/Desktop/field.png`. 2. The operator or agent runs `draw_field.py`. 3. The script sends the same fixed destinations to `/api/file/save-as` and `/api/file/export/png`. 4. If Clawbius allows replacement, it writes the newly generated artwork over the existing files. 5. The previous content is lost without an interactive warning or recovery copy. ### Impact Assessment Exploitation results in unauthorized replacement or loss of files at the fixed destinations. Filesystem access is constrained by the permissions of the Clawbius service; no evidence of elevated privileges or writes beyond those requested paths was found. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Route generated files to the documented Skill `outputs/` directory. - Refuse to use an existing destination by default. - Generate paired versioned paths, for example `field_v1.ans` and `field_v1.png`. - Perform collision handling atomically where supported. - Require explicit operator authorization before any replacement. - Verify and report the API response for both operations so failed or destructive behavior is not silently ignored. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/flower_v2.py:290
Finding
Flower Script Uses Fixed Output Names Without Collision Protection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/flower_v2.py:290-297` **Vulnerability Type**: Unchecked deterministic output paths **Risk Level**: Medium ### Vulnerable Code ```python import os out_dir = os.path.expanduser("~/Documents/ANSIClaw Output") ans_path = f"{out_dir}/flower_v2.ans" png_path = f"{out_dir}/flower_v2.png" post("/api/file/save", {"path": ans_path}) r = requests.post(f"{BASE}/api/file/export/png", json={"path": png_path}) ``` ### Technical Analysis The script constructs deterministic output paths without checking for existing files or selecting a new version. The PNG export can consequently replace `flower_v2.png` if the Clawbius export endpoint permits overwriting. The code also passes a `path` argument to `/api/file/save`, although the bundled API reference documents that endpoint as saving to the current file path and identifies `/api/file/save-as` as the endpoint that accepts a destination. Depending on the running Clawbius implementation, the requested ANSI destination may therefore be ignored rather than safely creating `flower_v2.ans`. This mismatch does not eliminate the fixed-path risk for PNG export. ### Attack Path 1. `~/Documents/ANSIClaw Output/flower_v2.png` already contains artwork or another user file. 2. The operator or agent invokes `flower_v2.py`. 3. The script submits the fixed PNG path to `/api/file/export/png`. 4. If Clawbius permits replacement, the existing PNG is overwritten without confirmation. 5. Separately, the `/api/file/save` request may save to the canvas's current path or perform no useful save, potentially leaving the operator with an unexpected ANSI output state. ### Impact Assessment The confirmed exposure is potential loss of the PNG at the fixed destination. The API mismatch may also cause the ANSI file to be absent or saved somewhere other than the displayed path. Operations remain constrained to the filesystem permissions of the Clawbius process, and no privilege escalation ...[truncated 22 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Use `/api/file/save-as` when specifying the ANSI destination, in accordance with the bundled API reference. - Create the intended output directory safely if it does not exist. - Check whether the `.ans` or `.png` destination exists before making API calls. - Generate a fresh versioned pair, such as `flower_v2a.ans` and `flower_v2a.png`, when a collision is detected. - Require explicit operator approval before replacement. - Validate the `ok` field and resulting file path for both save and export operations before printing a success message. - Prefer the Skill-local `outputs/` directory to keep writes within the documented workspace. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (24)

Vague Triggers

High
Confidence
97% confidence
Finding
The trigger guidance says to use the skill anytime the user asks for ANSI art, or when the agent wants to create it on its own initiative. Self-initiated activation materially increases risk because the skill can perform file and local API operations without a tightly scoped user request, making unintended actions more likely.

Lp3

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding
The skill instructs the agent to make network requests to a local REST API, but the manifest declares no explicit tool scope or permission boundary. That mismatch creates an undeclared capability path where an agent may perform networked actions without clear policy constraints or user visibility, increasing the chance of misuse or overreach.

External Transmission

Medium
Category
Data Exfiltration
Content
```python
import requests, json
# Open the reference file
requests.post("http://127.0.0.1:7777/api/file/open",
    json={"path": "/absolute/path/to/resources/file.ans"})

# Get canvas info
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
```python
import requests, json
# Open the reference file
requests.post("http://127.0.0.1:7777/api/file/open",
    json={"path": "/absolute/path/to/resources/file.ans"})

# Get canvas info
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Internal Network Request

Medium
Category
Server-Side Request Forgery
Content
```python
import requests, json
# Open the reference file
requests.post("http://127.0.0.1:7777/api/file/open",
    json={"path": "/absolute/path/to/resources/file.ans"})

# Get canvas info
Confidence
93% confidence
Finding
The skill performs HTTP requests to an internal loopback service and passes a filesystem path into that service's file-open endpoint. Even though the host is 127.0.0.1, this still exposes an internal request surface that can be abused to access or manipulate local resources through the API if the agent is induced to use attacker-chosen paths.

Internal Network Request

Medium
Category
Server-Side Request Forgery
Content
json={"path": "/absolute/path/to/resources/file.ans"})

# Get canvas info
info = requests.get("http://127.0.0.1:7777/api/canvas/info").json()

# Get full canvas data and analyze color/code usage
data = requests.get("http://127.0.0.1:7777/api/canvas/data").json()
Confidence
70% confidence
Finding
Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.

Internal Network Request

Medium
Category
Server-Side Request Forgery
Content
json={"path": "/absolute/path/to/resources/file.ans"})

# Get canvas info
info = requests.get("http://127.0.0.1:7777/api/canvas/info").json()

# Get full canvas data and analyze color/code usage
data = requests.get("http://127.0.0.1:7777/api/canvas/data").json()
Confidence
70% confidence
Finding
Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.

External Transmission

Medium
Category
Data Exfiltration
Content
BASE = "http://127.0.0.1:7777"

def post(path, data):
    r = requests.post(f"{BASE}{path}", json=data)
    resp = r.json()
    if not resp.get("ok"): print(f"WARN {path}: {resp}")
    return resp
Confidence
91% confidence
Finding
The generic helper posts arbitrary JSON to arbitrary API paths on the configured local service, creating a broad action surface for state-changing operations. In a skill that can be triggered too broadly, this abstraction makes it easier for the agent to invoke unintended endpoints or destructive actions without granular safeguards.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The documented API exposes file-writing operations such as save-as and export to arbitrary absolute paths, which can modify local files if an agent uses them on untrusted or ambiguous user input. In an agent skill context, this is dangerous because the documentation normalizes these capabilities without any safety guidance, increasing the chance that automation will overwrite user files or write to sensitive locations on the host.

Unrestricted Tool Access

Medium
Category
Excessive Agency
Content
Python scripts that draw ANSI art via the Clawbius API. Each script is self-contained and re-runnable.

To run any script, just ask Clawd — or run directly:
```
python3 ~/.openclaw/workspace/skills/ANSIClaw/scripts/<script_name>.py
```
Confidence
84% confidence
Finding
The instruction to 'run any script' encourages unrestricted execution of local tool-capable Python files from the skill directory. In an agent context, this reduces friction for arbitrary code execution and can amplify the effects of any unsafe script behavior such as filesystem writes or local API abuse.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The README tells users to 'run any script' or 'just ask Clawd' without constraining which script may be executed or warning that execution runs local Python code. Broad invocation guidance can lead users or an agent to execute arbitrary scripts in the skill directory without review, increasing the chance of unintended code execution.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The README states that output files are written to '~/Documents/ANSIClaw Output/' but does not present this as a user-facing warning or ask for consent. Silent writes to a user's Documents folder can cause privacy surprises, clutter trusted storage locations, and overwrite or create files in a location users may not expect a skill to modify.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The README notes that scripts use 'requests' to call a local API at 'http://127.0.0.1:7777' but does not clearly warn users that execution performs HTTP requests. Even though the destination is localhost, local services can expose privileged functionality, and users should be informed that running the scripts will interact with another process over the network stack.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script writes files directly to the user's Desktop without prompting, which can create unwanted side effects and overwrite expectations about where data is stored. Although the filenames are fixed and the content is benign art output, silent writes to a user-visible location are risky behavior for an agent skill because they bypass user consent and could expose generated content to others with access to the desktop.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The manifest says the skill draws BBS-compatible ANSI art via the Clawbius API, which aligns with creating ANSI canvas content and saving an .ans file. The code additionally invokes a PNG export operation, producing a non-ANSI derivative artifact that goes beyond the described ANSI-only scope.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The script unconditionally writes output files to ~/Desktop, which modifies the user's filesystem without consent or configurability. While the files are benign image/art outputs in this context, unexpected writes can overwrite existing files, leak activity, or violate user expectations in an agent-executed environment.

External Transmission

Medium
Category
Data Exfiltration
Content
BASE = "http://127.0.0.1:7777"

def post(path, data):
    r = requests.post(f"{BASE}{path}", json=data)
    resp = r.json()
    if not resp.get("ok"):
        print(f"WARN {path}: {resp}")
Confidence
80% 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
BASE = "http://127.0.0.1:7777"

def post(path, data):
    r = requests.post(f"{BASE}{path}", json=data)
    resp = r.json()
    if not resp.get("ok"):
        print(f"WARN {path}: {resp}")
Confidence
80% 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
BASE = "http://127.0.0.1:7777"

def post(path, data):
    r = requests.post(f"{BASE}{path}", json=data)
    resp = r.json()
    if not resp.get("ok"):
        print(f"WARN {path}: {resp}")
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The script writes output files directly into the user's Documents directory and performs export actions without any prompt, confirmation, or configurable destination. In an agent-skill context, silent filesystem writes are risky because execution has side effects outside the immediate drawing task and can surprise users or overwrite expected artifacts if naming collides.

External Transmission

Medium
Category
Data Exfiltration
Content
post("/api/file/save", {"path": ans_path})

r = requests.post(f"{BASE}/api/file/export/png", json={"path": png_path})
print("PNG export:", r.text[:80])
print(f"Saved: {ans_path}")
print("ALL DONE ✓")
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Low
Confidence
89% confidence
Finding
The open-file endpoint accepts arbitrary absolute local paths, enabling reads of local files if an agent is induced to call it with attacker-influenced input. While this is an API reference rather than executable code, documenting the capability without warning makes misuse more likely in an automated skill that may access host-local resources.

Intent-Code Divergence

Low
Confidence
92% confidence
Finding
The README first says reference files can be analyzed with a Peekaboo screenshot, but later instructs users not to use Peekaboo because it captures the wrong window. These instructions actively conflict and create ambiguity about the intended analysis method.

Missing User Warnings

Low
Confidence
87% confidence
Finding
The script sends HTTP requests to a local service on 127.0.0.1:7777 without any upfront disclosure to the user. Even though the target is localhost rather than an external host, undisclosed network interaction in a skill is still security-relevant because it depends on another process, may trigger unintended actions, and could interact with a different service if that port is occupied by something else.

Static analysis

No suspicious patterns detected.