Back to skill

Security audit

YMind Chat Visualizer

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real chat-visualization tool, but it handles sensitive chats and generated webpages in ways that create meaningful review-level security risk.

Install only if you are comfortable with the skill saving full chat transcripts locally and generating HTML that may contact third-party CDNs. Avoid using it on sensitive chats, credentials, private business data, or untrusted shared-chat links until the HTML escaping, index rendering, helper discovery, and dependency pinning issues are fixed. Prefer paste mode with non-sensitive content and review/delete ~/ymind-ws outputs after use.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/templates/ymindmap.html:676
Finding

Stored Script Injection in Generated Graph Pages

Content
View full analysis
str: """Inject graph data (and optional chat messages) into the HTML template.""" title = "" if "meta" in graph_json and graph_json["meta"]: title = graph_json["meta"].get("title", "") html = template.replace("{{TITLE}}", title or "Untitled") html = html.replace("{{GRAPH_JSON}}", json.dumps(graph_json, ensure_ascii=False)) chat_json_str = json.dumps(chat_messages, ensure_ascii=False) if chat_messages is not None else "null" html = html.replace("{{CHAT_JSON}}", chat_json_str) return html ``` The resulting values are inserted directly into executable HTML: ```html ` terminates the script element even if it appears inside a JavaScript or JSON string. Consequently, a graph title, node field, summary, source field, or raw chat message containing a payload such as: ```html ``` can terminate the intended script and create a new executable script element. The title substitution is independently unsafe because it is inserted into the `` element wi ...[truncated 2618 chars]
Remediation
View remediation
` element. 2. Store data in non-executable JSON elements: ```html ``` 3. Before substitution, perform HTML-safe JSON serialization by escaping at least `<`, `>`, `&`, U+2028, and U+2029: ```python def html_safe_json(value): return ( json.dumps(value, ensure_ascii=False) .replace("&", "\\u0026") .replace("<", "\\u003c") .replace(">", "\\u003e") .replace("\u2028", "\\u2028") .replace("\u2029", "\\u2029") ) ``` 4. Parse the non-executable JSON explicitly: ```javascript const __YMIND_DATA__ = JSON.parse(document.getElementById('ymind-data').textContent); ``` 5. HTML-escape the title before inserting it into ``, or set `document.title` through a trusted static bootstrap script using parsed data. 6. Add a restrictive Content Security Policy. Prefer a local, hashed bootstrap script and disallow inline execution: ```html <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; connect-src 'none'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'"> ``` 7. Avoid serving the whole run directory solely to capture a screenshot. Serve only the required HTML and static assets through a handler that denies directory listing and access to JSON source files. 8. Add regression tests using payloads containing `</script>`, ``, HTML attributes, Unicode separators, and ampersands. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/templates/workspace-index.html:15
Finding

Stored Script and HTML Injection in the Workspace Index

Content
View full analysis
const INDEX_DATA = {{SESSIONS_JSON}}; ``` Session values are subsequently concatenated into `innerHTML`: ```javascript function buildCard(run) { const prov = getProvider(run.provider); const date = parseDate(run.created_at); const thumbSrc = `./${run.run_dir}/graph.png`; const graphHref = `./${run.run_dir}/graph.html`; const title = run.title ?? ''; const hasTitle = title.trim().length > 0; const card = document.createElement('div'); card.className = 'session-card'; card.dataset.provider = run.provider ?? ''; card.style.setProperty('--card-rgb', prov.rgb); card.style.setProperty('--card-rgb2', '189,0,255'); card.style.cursor = 'pointer'; card.addEventListener('click', (e) => { if (!e.target.closest('.source-link')) window.open(graphHref, '_blank'); }); card.innerHTML = `
${hasTitle ? title : 'Graph'} ...
${hasTitle ? title : i18n.untitled}
... ...[truncated 3219 chars]
Remediation
View remediation
` element or load a static `index.json` file. 2. Replace the card's `innerHTML` construction with DOM APIs: - Assign visible values using `textContent`. - Assign image URLs using `img.src`. - Assign links using `anchor.href` only after validation. - Use `addEventListener()` instead of inline event-handler attributes. 3. Validate source URLs with `urllib.parse` during metadata creation and again in JavaScript before use. Permit only `https:` URLs and exact approved provider hosts. 4. Treat `run_dir` as an identifier, not a path. Enforce a strict format such as: ```text ^[0-9]{8}-[0-9]{6}_[a-z0-9_-]+$ ``` 5. Add a restrictive Content Security Policy that blocks inline scripts and inline event handlers. 6. Sanitize legacy metadata before rebuilding an index, because existing `meta.json` files may already contain unsafe values. 7. Add tests for quotes, angle brackets, event-handler markup, `javascript:` URLs, `data:` URLs, and `` sequences in every metadata field. ]]>

T03 · Remote Payload Retrieval and Execution

Warning
Location
scripts/templates/ymindmap.html:9
Finding

Unpinned Third-Party JavaScript Is Executed During Rendering

Content
View full analysis
``` ### Technical Analysis The generated visualization executes JavaScript fetched at runtime from third-party CDN domains. The URLs do not identify immutable artifact versions and do not include Subresource Integrity hashes. In particular, `d3.v7.min.js` identifies a major release rather than an immutable file digest, while the html2canvas URL contains no version at all. The effective code can therefore change after the Skill package has been reviewed. This also conflicts with the renderer's description of producing a “self-contained HTML visualization.” The generated page remains dependent on external services and makes network connections whenever it is opened. The screenshot workflow automatically loads these scripts in Playwright through the temporary HTTP server. If a CDN, its DNS path, publisher account, or upstream deployment is compromised, attacker-controlled JavaScript would execute in every generated graph page. This remote code would share the page's origin and could read the embedded graph and raw conversation displayed in the split view. ### Attack Path 1. An attacker compromises a referenced CDN resource, its publishing process, or a mutable upstream artifact. 2. The ...[truncated 1054 chars]
Remediation
View remediation
``` 4. Configure a Content Security Policy that permits scripts only from `'self'` after vendoring. 5. Remove external font dependencies or bundle the required fonts locally. At minimum, document that opening generated output contacts Google Fonts. 6. Make screenshots deterministic and offline-capable, and fail safely if a bundled dependency is unavailable rather than silently fetching mutable code. 7. Record dependency versions and cryptographic hashes in the repository so reviewed artifacts can be reproduced. ]]>

T08 · Insecure Dependencies

Note
Location
requirements.txt:7
Finding

Python Dependencies Are Not Reproducibly Pinned

Content
View full analysis
=2.28 # fetch-chat.py only playwright>=1.40 # fetch-chat.py (Gemini/Claude) + render-html.py (screenshot) ``` ### Technical Analysis Both dependencies use minimum-version constraints without upper bounds, exact versions, lockfile entries, or artifact hashes. A future installation may therefore resolve to substantially different code from the versions originally reviewed. This does not demonstrate that either named package is currently malicious. Both names correspond to the expected packages used by the source code. The risk is that installation is not reproducible and automatically trusts future package releases and whichever artifacts the package index supplies. Playwright is especially security-sensitive because it installs and controls a browser executable. Changes in Playwright, its browser-install process, or transitive dependencies can materially alter local execution behavior. ### Attack Path 1. A future upstream release, publisher account, distribution artifact, or dependency is compromised. 2. The user follows the documented command to install dependencies. 3. The package resolver selects the latest version satisfying the broad `>=` constraint. 4. The unreviewed package code executes during installation, browser setup, import, or normal Skill operation. 5. The compromised dependency acts with the privileges of the user running the installation or Skill. ### Impact Assessment A compromised Python package or browser installation component could potentially execute code with the current user's operating-system privileges. That could exceed browser-only scope and affect files and credentials accessible to that user. The likelihood is lower than the direct HTML injection findings because exploitation depends on a package-distribution or ups ...[truncated 127 chars]
Remediation
View remediation
playwright== ``` 2. Generate a lockfile containing all transitive dependencies. 3. Use hash checking, such as pip requirements generated with `--generate-hashes`, and install with `pip --require-hashes`. 4. Pin and document the exact Chromium revision installed by Playwright. 5. Perform dependency updates through an explicit review process rather than resolving the latest compatible versions during normal setup. 6. Run automated vulnerability and provenance checks against the lockfile. 7. Install dependencies in an isolated virtual environment with only the permissions needed for the Skill. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • 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 (30)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documented purpose is chat visualization, but the skill also performs version-check/update logic by locating and executing a separate script from local skill directories. Hidden or under-disclosed behavior is dangerous because users and policy engines may authorize the skill for one purpose while it performs unrelated network and local-execution actions.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The documented purpose is chat visualization, but the skill also performs version-check/update logic by locating and executing a separate script from local skill directories. Hidden or under-disclosed behavior is dangerous because users and policy engines may authorize the skill for one purpose while it performs unrelated network and local-execution actions.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documented purpose is chat visualization, but the skill also performs version-check/update logic by locating and executing a separate script from local skill directories. Hidden or under-disclosed behavior is dangerous because users and policy engines may authorize the skill for one purpose while it performs unrelated network and local-execution actions.

Content

No source excerpt is available for this finding.

Agent Config Directory Access

High
Category
Agent Snooping
Confidence
95% confidence
Finding

The version-check step searches agent configuration directories across multiple clients and then executes the first matching check-version.py it finds. Accessing these directories exposes installation layout information, and executing a discovered script by path is especially risky because a malicious or tampered local file in any searched location could gain code execution under the agent's privileges.

Content

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

Run once at the start of each skill session. First locate the script (works regardless of which client installed the skill):

bash
find ~/.codex/skills ~/.claude/skills ~/.openclaw/skills ~/skills -maxdepth 3 -name "check-version.py" 2>/dev/null | head -1

Then run it with python3 <found_path>.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README describes automatic fetching and local persistence of full chat data, including raw_chat.json, but does not clearly warn users at the point of use that sensitive conversation contents will be written to disk in recoverable form. In the context of a chat-visualization skill, users may process highly sensitive AI conversations, so insufficient disclosure increases the risk of accidental local data exposure, backup leakage, or unintended sharing of generated artifacts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README advertises automatic fetching of public chat URLs and states that fetched conversation data is saved locally, including raw_chat.json, but it does not present a strong, explicit warning that sensitive or personal content may be written to disk in cleartext. In this skill context, users are likely to process AI chat transcripts that may contain credentials, business data, or private reasoning, so silent persistence materially increases confidentiality risk.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill invokes shell commands, reads from agent/client configuration directories, writes transcript and workspace files, and may access the network, yet it declares no explicit tool scope or permissions boundaries. That creates unnecessary ambient authority: an agent may grant broader capabilities than users expect, increasing the blast radius if the skill or its helper scripts behave unexpectedly.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The invocation language is broad enough to match common requests like summarization, analysis, or understanding a chat, which can cause the skill to trigger in situations where users did not intend transcript fetching, storage, or rendering. Overbroad activation increases the chance of unnecessary data collection and execution of file/network operations on sensitive conversations.

Content

No source excerpt is available for this finding.

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
90% confidence
Finding

Enumerating ~/.codex/skills, ~/.claude/skills, ~/.openclaw/skills, and ~/skills reveals which agent clients and skill ecosystems are installed on the host. That information can aid fingerprinting, targeted follow-on attacks, or privacy-invasive environment profiling, and it is unrelated to the core task of visualizing a chat transcript.

Content

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

Run once at the start of each skill session. First locate the script (works regardless of which client installed the skill):

bash
find ~/.codex/skills ~/.claude/skills ~/.openclaw/skills ~/skills -maxdepth 3 -name "check-version.py" 2>/dev/null | head -1

Then run it with python3 <found_path>.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill instructs the agent to fetch shared chat URLs, scrape content with Playwright, and persist transcripts to raw_chat.json/meta.json without a clear privacy warning or explicit consent checkpoint. Conversation transcripts can contain sensitive personal, business, or credential-like data, so silent collection and storage materially increases confidentiality risk.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/check-version.py (reported line 22)May include surrounding context.

python
try:
    resp = urllib.request.urlopen(
        "https://api.github.com/repos/yslenjoy/chat-visualizer-ymind/releases/latest",
        timeout=3,
    )
    data = json.loads(resp.read())

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The Claude and DeepSeek paths include deliberate anti-bot evasion behavior: launching a headed browser, disabling AutomationControlled, and overriding navigator.webdriver. That goes beyond ordinary retrieval and is risky because it is specifically designed to bypass provider access controls, which can violate platform protections and normalize stealthy browser automation techniques inside a reusable skill.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/fetch-chat.py (reported line 467)May include surrounding context.

python
"Referer": url,
        "Origin": "https://www.doubao.com",
    }
    resp = requests.post(api_url, params=params, json={"share_id": share_id, "need_bot": False},
                         headers=headers, timeout=timeout)
    resp.raise_for_status()
    data = resp.json()

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The function automatically reads a sibling raw_chat.json file and embeds its full message contents into the generated HTML without requiring explicit user opt-in or even a prominent warning. In this skill's context, users are likely handling AI conversation exports that may contain sensitive prompts, private data, or internal reasoning, so silent inclusion creates a real confidentiality risk if the HTML is shared or published.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The template loads third-party scripts and fonts from external domains, including executable JavaScript from d3js.org and html2canvas.hertzen.com. Because this skill processes sensitive chat transcripts, opening the rendered HTML can leak usage metadata and potentially transcript-derived content to third parties, and a compromised CDN could execute arbitrary code in the page context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code automatically enables split mode and displays all injected chat messages in the UI when CHAT_MESSAGES is present. Although the behavior is visible once rendered, the file contains no confirmation, warning comment, or other disclosure that conversation content will be shown alongside the graph, which can expose sensitive user text unexpectedly.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The header presents English as the primary content and links to a Chinese translation, which imposes a language choice in the skill documentation rather than offering an in-skill language preference or neutral selection flow. Under the stated policy, language constraints should be opt-in or clearly justified.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
93% confidence
Finding

The dependency specification uses a lower-bound only constraint (requests>=2.28), which makes the installed version non-deterministic and prevents verifying whether a vulnerable release may be resolved or selected in different environments. In a skill that may fetch user-supplied public chat share links, requests processes untrusted URLs, so known issues such as credential leakage or request-handling flaws are more relevant than they would be in a purely offline tool.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code performs an outbound HTTP request to the GitHub API to check for the latest release, which transmits environment-derived context such as the skill's use and the caller's network metadata. While the module docstring documents output behavior, it does not disclose the external network access itself, and there is no user-facing log, prompt, or warning around the request.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The default HTTP headers hard-code "Accept-Language: en-US,en;q=0.9", which imposes an English locale preference on all outbound requests. The file does not offer a user opt-in or explain why English is required for these fetch operations, so this is a natural-language locale policy concern rather than a technical bug.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The docstring for the ChatGPT fallback says 'no cookies saved', but the function does not contain any explicit controls or checks related to cookie persistence. While Playwright's ephemeral session may make persistence unlikely here, the documentation makes a stronger assurance than the code itself guarantees.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The headed browser context is created with locale="en-US", which forces a specific locale for Claude and DeepSeek page fetches. Because the script does not give users a language choice or explain a justified regional requirement, this is a policy-level locale restriction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script derives isZh from navigator.language and then hard-sets both the document language and UI locale to zh-CN or en-US. This creates a language/locale policy issue because users are not given an explicit opt-in or alternative if they prefer another language or regional format.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.