Back to skill

Security audit

An AI skill for OpenClaw that generates professional diagrams from natural language descriptions using EdrawMax AI APIs.

Security checks for vulnerabilities and agentic risk

Overview

This diagram skill is purpose-aligned overall, but its downloader has concrete security weaknesses that can save untrusted or tampered remote content locally.

Review before installing. Use this only for prompts you are comfortable sending to EdrawMax, avoid confidential or regulated data, and be cautious opening generated SVG files. Prefer a fixed version that keeps TLS verification enabled, restricts downloads to trusted EdrawMax/OSS hosts, limits file size, validates image content, and makes local saving explicit or optional.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/download_diagram.py:27
Finding

TLS Certificate and Hostname Verification Disabled

Content
View full analysis

Vulnerability Details

File Location: scripts/download_diagram.py, lines 27–35
Vulnerability Type: Improper certificate validation
Risk Level: High

Vulnerable Code

python
def download_file(url: str, output_path: str) -> str:
    """Download a file from URL to output_path. Returns the output_path on success."""
    ctx = ssl.create_default_context()
    ctx.check_hostname = False
    ctx.verify_mode = ssl.CERT_NONE

    req = urllib.request.Request(url, headers={"User-Agent": "EdrawMax-Skill/2.0"})
    try:
        with urllib.request.urlopen(req, context=ctx, timeout=60) as resp:

Technical Analysis

The downloader explicitly disables both TLS certificate verification and hostname validation. Consequently, an HTTPS connection succeeds even when the server presents an expired, self-signed, forged, or otherwise untrusted certificate.

This removes the authenticity and integrity guarantees normally provided by HTTPS. Although the diagram-generation API is contacted over HTTPS, the PNG and SVG resources returned by that API are downloaded through this insecure TLS context. The weakness applies to every HTTPS host passed to download_file().

SVG files are particularly relevant because they are active document formats and may contain external references, scripts, or other dangerous elements depending on the application used to open or render them.

Attack Path

  1. The Skill submits a diagram request and receives PNG and SVG download URLs.
  2. The download script connects to those URLs using a TLS context configured with CERT_NONE.
  3. An attacker in a position to intercept network traffic presents a forged certificate.
  4. The script accepts the certificate without warning.
  5. The attacker substitutes the expected image with attacker-controlled PNG, SVG, or arbitrary file content.
  6. The substituted file is written locally and its path is presented to the user as a generated diagra ...[truncated 533 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove the statements that disable hostname and certificate verification.

  • Use Python's default verified TLS configuration:

    python
    ctx = ssl.create_default_context()
    with urllib.request.urlopen(req, context=ctx, timeout=60) as resp:
        ...
    
  • Fail closed when certificate validation fails; do not retry with an insecure context.

  • Keep the operating system and Python certificate-authority stores current.

  • Combine proper TLS verification with an allowlist of expected EdrawMax and OSS hostnames.

  • Validate the downloaded file type and sanitize SVG content before exposing the file to users.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/download_diagram.py:33
Finding

Unrestricted URL Fetching Enables SSRF and Local Resource Access

Content
View full analysis

Vulnerability Details

File Location: scripts/download_diagram.py, lines 33–36, 53–54, and 68–73
Vulnerability Type: Unvalidated URL fetching / server-side request forgery
Risk Level: Medium

Vulnerable Code

python
req = urllib.request.Request(url, headers={"User-Agent": "EdrawMax-Skill/2.0"})
try:
    with urllib.request.urlopen(req, context=ctx, timeout=60) as resp:
        data = resp.read()
python
parser.add_argument("--png-url", required=True, help="PNG image URL from API response")
parser.add_argument("--svg-url", required=True, help="SVG image URL from API response")
python
downloaded_png = download_file(args.png_url, png_path)
if downloaded_png:
    result["png_path"] = os.path.abspath(downloaded_png)

downloaded_svg = download_file(args.svg_url, svg_path)
if downloaded_svg:
    result["svg_path"] = os.path.abspath(downloaded_svg)

Technical Analysis

Both URLs are accepted as arbitrary strings and passed directly to urllib.request.urlopen(). The implementation does not enforce HTTPS, restrict requests to trusted EdrawMax or OSS domains, validate redirect destinations, or reject loopback, private, link-local, reserved, and cloud-metadata addresses.

It also does not explicitly reject non-HTTP URL schemes supported by urllib, such as local file URLs. An attacker who can influence an API response URL, command-line argument, or redirect destination can therefore make the process request resources outside the intended image-storage boundary.

The retrieved response is written to a predictable output file with a PNG or SVG extension regardless of its true source or content. No automatic transmission of the resulting local file to the attacker was found, so data exfiltration would require an additional disclosure path or user action.

Attack Path

  1. An attacker gains control over, substitutes, or otherwise influences a PNG or SVG URL consumed by the ...[truncated 1344 chars]
Remediation
View remediation

Remediation Suggestions

  • Parse URLs with urllib.parse.urlsplit() and permit only the https scheme.
  • Maintain a strict allowlist of documented EdrawMax and OSS hostnames. Match normalized hostnames exactly or against carefully defined subdomains.
  • Resolve destination hostnames and reject all loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 addresses.
  • Defend against DNS rebinding by validating the address actually used for the connection, not only a preliminary DNS result.
  • Disable redirects or validate the scheme, hostname, port, and resolved address after every redirect.
  • Reject URLs containing unexpected credentials, ports, malformed hostnames, or non-HTTP schemes.
  • Apply the same validation independently to both PNG and SVG URLs.
  • Log rejected destinations without exposing sensitive URL query parameters.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/download_diagram.py:33
Finding

Unbounded and Unvalidated Downloads Permit Resource Exhaustion and File-Type Spoofing

Content
View full analysis

Vulnerability Details

File Location: scripts/download_diagram.py, lines 33–41
Vulnerability Type: Uncontrolled resource consumption and missing content validation
Risk Level: Medium

Vulnerable Code

python
req = urllib.request.Request(url, headers={"User-Agent": "EdrawMax-Skill/2.0"})
try:
    with urllib.request.urlopen(req, context=ctx, timeout=60) as resp:
        data = resp.read()
    os.makedirs(os.path.dirname(output_path) or ".", exist_ok=True)
    with open(output_path, "wb") as f:
        f.write(data)
    return output_path

Technical Analysis

Calling resp.read() without a size argument reads the entire response into memory. The 60-second connection timeout does not impose a maximum response size and does not reliably prevent a peer from consuming substantial memory, disk space, or processing time.

The implementation also ignores the HTTP status, declared content length, MIME type, and actual file signature. Any response body is saved with a .png or .svg extension. As a result, an attacker-controlled endpoint can provide an oversized response or arbitrary content disguised as an image.

File extensions are not security boundaries. Downstream tools may choose a parser based on the extension, MIME sniffing, or file contents, which can expose users to malformed-image attacks or active SVG content.

Attack Path

  1. An attacker controls or influences one of the image URLs.
  2. The referenced server sends an extremely large response, an indefinitely streamed body, or content that is not a valid image.
  3. The script calls resp.read() and attempts to retain the complete response in memory.
  4. The process may exhaust available memory and terminate, affecting the parent agent or nearby workloads.
  5. If the read completes, the entire body is written to disk without a size limit.
  6. Arbitrary content is saved under a trusted .png or .svg filename and may subsequent ...[truncated 697 chars]
Remediation
View remediation

Remediation Suggestions

  • Stream responses in bounded chunks instead of using an unrestricted resp.read().
  • Enforce conservative per-file and aggregate download limits.
  • Reject responses whose declared Content-Length exceeds the limit, while still counting streamed bytes because that header can be absent or false.
  • Accept only successful HTTP status codes and expected MIME types.
  • Verify PNG magic bytes and parse the image with a maintained image library before accepting it.
  • Parse and sanitize SVG as XML. Reject scripts, event-handler attributes, external references, unsafe embedded content, and malformed documents.
  • Write to a temporary file, validate it, then atomically rename it to the final destination.
  • Delete partial files after errors or limit violations.
  • Apply filesystem quotas and process memory limits as defense-in-depth controls.
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 (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The documented behavior materially exceeds the declared purpose by requiring file downloads and local disk writes in addition to diagram generation. That mismatch is dangerous because reviewers and users may approve the skill for harmless generation while overlooking persistent local writes and URL-driven retrieval, which broadens the attack surface to unwanted storage, unsafe content handling, or misuse of downloaded resources.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill explicitly instructs outbound network use to a third-party API but does not declare any tool scope or permissions boundary. This creates an authorization and transparency gap: an agent may invoke network access without clear policy review, increasing the risk of unintended data exfiltration or unauthorized external calls.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger phrases are broad enough to match generic requests such as 'visualize a process' or 'knowledge map,' which can cause unintended skill activation. Overbroad activation is risky because it may send user content to an external service or create local files in situations where the user did not intend to invoke this specific third-party diagram tool.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill sends user-supplied prompts to an external API and then downloads artifacts to local storage without clearly warning the user about either data transfer or file creation. This is dangerous from a privacy and consent perspective because user content may contain sensitive business or personal information, and local copies may persist on disk unexpectedly.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The skill is designed to transmit user input to an external service endpoint, which constitutes data egress to a third party. In this context the transmission is expected functionality, but it remains security-relevant because diagram prompts may contain confidential workflows, project plans, or internal knowledge structures.

Content

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

md
## Step 2 — Call the API

**Base URL:** `https://api.edrawmax.cn/api/ai`

All four endpoints share the same request format:

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The concrete POST example confirms that user prompt content is sent off-platform to the EdrawMax API. Although this is core to the skill's function, it is still a true security concern because external processing can expose proprietary or personal information if users are not informed or if organizational policies prohibit such sharing.

Content

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

All four endpoints share the same request format:

text
POST https://api.edrawmax.cn/api/ai/skills/generate-{type}
Content-Type: application/json

{"prompt": "<user description>", "lang": "cn", "platform": "web"}

External Transmission

Medium
Category
Data Exfiltration
Confidence
87% confidence
Finding

The skill is designed around an external API endpoint, so external transmission is expected in context; however, it still represents a real security and privacy boundary because user prompts and metadata are sent off-platform to a third-party service. In this specific skill, that context makes the transmission more sensitive, not less, because users may assume a simple diagramming request is local while the API also returns remotely hosted artifacts.

Content

Scanner excerpt · references/api-reference.md (reported line 9)May include surrounding context.

Base URL

text
https://api.edrawmax.cn/api/ai
  • Auth: None required

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The documentation states that user_id is automatically extracted from the X-User-ID header and defaults to 0, but it does not clearly warn that user identity data is being implicitly collected and used. In a skill that sends user prompts to a remote third-party API, this creates a privacy and accountability risk because callers may unintentionally transmit identifiers without informed consent or clear data-handling expectations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The API reference describes sending natural-language prompts to api.edrawmax.cn and returning png_url/svg_url artifacts hosted on OSS, but it does not warn that user content leaves the local system and may be stored remotely. This is dangerous because users may include sensitive business data, personal data, or confidential workflows in prompts, and the resulting diagrams may become accessible through remote object storage URLs.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The manifest describes a skill whose purpose is to generate specific diagram types from natural-language prompts using EdrawMax AI APIs. This script instead performs a separate persistence step by downloading remote URLs and saving PNG/SVG files locally, which is not described in the manifest and expands the behavior beyond generation itself.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

Automatically downloading generated assets and storing them locally introduces persistence that is not necessary for all uses and can create privacy, storage, and content-handling risks. Even if the files originate from the service, local writes may surprise users and can retain sensitive diagram content on disk longer than intended.

Content

No source excerpt is available for this finding.

Scope Creep

Low
Category
Excessive Agency
Confidence
70% confidence
Finding

Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Content

Scanner excerpt · license.txt (reported line 15)May include surrounding context.

text
1. Ownership
   The Software is owned by and remains the exclusive property of
   Wondershare EdrawMax AI Team(万兴图示 AI 团队). All intellectual property rights,
   including but not limited to copyrights, patents, trademarks, and
   trade secrets, are reserved by the EdrawMax AI Team.

2. Restrictions

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The shared parameters table sets lang default to "cn", which imposes a specific locale when the user does not choose one. Per SQP-3, forcing a specific language without opt-in can violate language/locale policy unless clearly justified or optionality is emphasized.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The file docstring frames the component's intent as downloading files from response URLs, while the skill-level documentation says the skill generates diagrams from natural language. This is an intent-level divergence in documentation that can mislead reviewers about the true role and scope of the skill component.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The author and copyright strings include Chinese-language text in the file's natural-language metadata, but the script provides no user-facing language choice or opt-in. Under the policy, fixed language presentation can be a locale-policy issue when not explicitly optional or justified.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.