Back to skill

Security audit

KMind Markdown 转导图(中文)

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly does what it says, but its local browser rendering service can expose or overwrite document data during a render without authentication.

Install only if you are comfortable with a Node-based skill launching a local Chromium browser and briefly running a local 127.0.0.1 render server. Avoid using it for highly sensitive Markdown until the render endpoints have per-session authentication and request-size limits.

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
scripts/vendor/cli.mjs:9716
Finding
Unauthenticated Local Rendering Endpoints Expose Document Data and Permit Output Corruption<![CDATA[ ## Vulnerability Details **File Location**: `scripts/vendor/cli.mjs:9716-9758` **Vulnerability Type**: Unauthenticated loopback HTTP endpoints **Risk Level**: Medium ### Vulnerable Code ```js server.on("request", async (req, res) => { try { const requestUrl = new URL(req.url ?? "/", "http://127.0.0.1"); if (req.method === "GET" && requestUrl.pathname === "/favicon.ico") { res.writeHead(204, noStoreHeaders()); res.end(); return; } if (req.method === "GET" && requestUrl.pathname === "/") { sendText(res, 200, buildHtmlPage(), "text/html; charset=utf-8"); return; } if (req.method === "GET" && requestUrl.pathname === "/renderer.js") { sendText(res, 200, rendererJs, "text/javascript; charset=utf-8"); return; } if (req.method === "GET" && requestUrl.pathname === "/job") { sendJson(res, 200, payload); return; } if (req.method === "POST" && requestUrl.pathname === "/result") { const bytes = await readRequestBytes(req); const mimeType = String(req.headers["content-type"] ?? "").trim() || (payload.format === "svg" ? "image/svg+xml" : "image/png"); await mkdir2(path4.dirname(outputPath), { recursive: true }); await writeFile2(outputPath, bytes); const done = { schema: "kmind-cli-render-session@v1", status: "done", format: payload.format, outputPath, byteLength: bytes.byteLength, mimeType }; sendJson(res, 200, done); settleResult?.({ kind: "success", done }); return; } if (req.method === "POST" && requestUrl.pathname === "/failure") { const bytes = await readRequestBytes(req); const message = Buffer.from(bytes).toString("utf8").trim() || "Browser render failed."; sendJson(res, 200, { ok: true }); settleResult?.({ kind: "failure", error: new CliUserError(message, 1) }); return; } send ...[truncated 3088 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Generate a cryptographically random capability token for each render session, for example using `crypto.randomBytes(32)`. 2. Include the token in the launched browser URL or deliver it through another protected per-session mechanism. 3. Require the token on `/job`, `/result`, and `/failure`, and compare it using a timing-safe comparison where appropriate. 4. Reject requests with unexpected `Host`, `Origin`, or `Sec-Fetch-Site` values. Treat these checks as defense in depth rather than a replacement for authentication. 5. Accept only one authenticated result and disable all job endpoints immediately after the session settles. 6. Validate the submitted result against the requested format: - Require and verify the PNG signature for PNG output. - Parse and validate SVG output, rejecting scripts, event-handler attributes, external references, and other active content if portable SVG is expected. 7. Do not trust the request-supplied `Content-Type`; derive the stored type from the requested output format. 8. Minimize `/job` contents to data strictly required by the renderer. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/vendor/cli.mjs:9635
Finding
Unbounded HTTP Request Buffering Enables Local Denial of Service<![CDATA[ ## Vulnerability Details **File Location**: `scripts/vendor/cli.mjs:9635-9646` **Vulnerability Type**: Unbounded request-body buffering **Risk Level**: Low ### Vulnerable Code ```js async function readRequestBytes(req) { const chunks = []; for await (const chunk of req) { if (typeof chunk === "string") { chunks.push(Buffer.from(chunk)); continue; } chunks.push(Buffer.from(chunk)); } return Buffer.concat(chunks); } ``` The unbounded helper is used by both result-processing endpoints: ```js if (req.method === "POST" && requestUrl.pathname === "/result") { const bytes = await readRequestBytes(req); const mimeType = String(req.headers["content-type"] ?? "").trim() || (payload.format === "svg" ? "image/svg+xml" : "image/png"); await mkdir2(path4.dirname(outputPath), { recursive: true }); await writeFile2(outputPath, bytes); // ... } if (req.method === "POST" && requestUrl.pathname === "/failure") { const bytes = await readRequestBytes(req); const message = Buffer.from(bytes).toString("utf8").trim() || "Browser render failed."; // ... } ``` ### Technical Analysis `readRequestBytes` accumulates every incoming chunk in an array and then creates an additional concatenated buffer. There is no maximum body size, no validated `Content-Length`, and no endpoint-specific limit. A client that can reach the loopback server can send a very large body or maintain a slowly streamed request. This can consume memory until the Node.js process becomes unresponsive or terminates. A large `/result` request can also produce an unexpectedly large file at the predetermined output path. The render-session timeout does not adequately mitigate this condition because an active asynchronous request handler can continue consuming input, and there is no explicit per-request timeout or abort logic. ### Attack Path 1. A user starts a render session, causing the Skill to listen on an ephemeral loopback port. 2. A maliciou ...[truncated 1028 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Enforce endpoint-specific request limits while streaming: - Use a small limit, such as several kilobytes, for `/failure`. - Use a documented and conservative image-size limit for `/result`. 2. Reject requests whose declared `Content-Length` exceeds the applicable limit. 3. Track the actual number of streamed bytes and immediately destroy or abort the request once the limit is exceeded; do not rely solely on `Content-Length`. 4. Configure request, header, and inactivity timeouts on the HTTP server. 5. Require the per-session authentication token recommended for the unauthenticated endpoint finding. 6. Validate image dimensions and decoded output size where feasible, not only the encoded request length. 7. Consider streaming valid result data to a temporary file with a strict limit, then atomically renaming it after successful format validation. 8. Delete partial temporary files when validation, authentication, or size checks fail. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (28)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Unlike the other TP4 variants, this one explicitly notes potential loading/insertion of external scripts and stylesheets alongside browser DOM/runtime infrastructure. In a user-invocable skill that launches a browser renderer, any remote script/style loading would violate the stated 'offline' model and could expose user content or execute untrusted code within the rendering flow.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Unlike the other TP4 variants, this one explicitly notes potential loading/insertion of external scripts and stylesheets alongside browser DOM/runtime infrastructure. In a user-invocable skill that launches a browser renderer, any remote script/style loading would violate the stated 'offline' model and could expose user content or execute untrusted code within the rendering flow.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Unlike the other TP4 variants, this one explicitly notes potential loading/insertion of external scripts and stylesheets alongside browser DOM/runtime infrastructure. In a user-invocable skill that launches a browser renderer, any remote script/style loading would violate the stated 'offline' model and could expose user content or execute untrusted code within the rendering flow.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Unlike the other TP4 variants, this one explicitly notes potential loading/insertion of external scripts and stylesheets alongside browser DOM/runtime infrastructure. In a user-invocable skill that launches a browser renderer, any remote script/style loading would violate the stated 'offline' model and could expose user content or execute untrusted code within the rendering flow.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Unlike the other TP4 variants, this one explicitly notes potential loading/insertion of external scripts and stylesheets alongside browser DOM/runtime infrastructure. In a user-invocable skill that launches a browser renderer, any remote script/style loading would violate the stated 'offline' model and could expose user content or execute untrusted code within the rendering flow.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Unlike the other TP4 variants, this one explicitly notes potential loading/insertion of external scripts and stylesheets alongside browser DOM/runtime infrastructure. In a user-invocable skill that launches a browser renderer, any remote script/style loading would violate the stated 'offline' model and could expose user content or execute untrusted code within the rendering flow.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Unlike the other TP4 variants, this one explicitly notes potential loading/insertion of external scripts and stylesheets alongside browser DOM/runtime infrastructure. In a user-invocable skill that launches a browser renderer, any remote script/style loading would violate the stated 'offline' model and could expose user content or execute untrusted code within the rendering flow.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Unlike the other TP4 variants, this one explicitly notes potential loading/insertion of external scripts and stylesheets alongside browser DOM/runtime infrastructure. In a user-invocable skill that launches a browser renderer, any remote script/style loading would violate the stated 'offline' model and could expose user content or execute untrusted code within the rendering flow.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Unlike the other TP4 variants, this one explicitly notes potential loading/insertion of external scripts and stylesheets alongside browser DOM/runtime infrastructure. In a user-invocable skill that launches a browser renderer, any remote script/style loading would violate the stated 'offline' model and could expose user content or execute untrusted code within the rendering flow.

Context-Inappropriate Capability

High
Confidence
96% confidence
Finding
The auto-render path probes the local environment for browser installations, inspects environment variables, and spawns browser executables. That behavior exceeds the stated scope of simple Markdown conversion and grants the skill host-level process execution and environment discovery capabilities that could be abused or cause unexpected side effects.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The render flow starts a localhost HTTP server, serves dynamic render jobs, accepts POSTed output bytes, and can auto-launch a local browser process. For a Markdown-to-mindmap conversion skill, this is a substantially stronger execution capability than expected and increases attack surface through local service exposure and browser/process orchestration.

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Content
ved a `memo` component. Instead of forwardRef(memo(...)), use memo(forwardRef(...))."
        ) : "function" !== typeof render3 ? console.error(
          "forwardRef requires a render function but was given %s.",
          null === render3 ? "null" : typeof render3
        ) : 0 !== render3.length && 2 !== render3.length && console.error(
          "forwardRef render functions accept exactly two parameters: props and ref. %s",
          1 === render3.length ? "Did you forget to use the ref parameter?" : "Any additional parameter will be undefined."
        );
        null != render3 && null != render3.defaultProps && console.error(
          "forwardRef render functions do not support defaultProps. Did you accidentally pass a React component?"
        );
        var elementType = { $$typeof: REACT_FORWARD_REF_TYPE, render: render3 }, ownName;
        Object.defineProperty(elementType, "displayName", {
          enumerable: false,
          configurable: true,
          get: function()
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Natural-Language Policy Violations

Medium
Confidence
83% confidence
Finding
The file title and description are entirely in Chinese, and the referenced skill name includes a `-cn` locale marker, indicating a Chinese-only orientation. Under the policy rule, forcing a specific language without explicit user opt-in or a clearly documented locale-specific justification can be a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The README repeatedly describes the skill as a Chinese-localized or Chinese-oriented variant intended for Chinese-speaking workflows and prompts. Under the policy, forcing a specific language or locale without explicit user choice can be a natural-language policy violation unless the constraint is clearly justified as region-specific compliance or optional.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The README states this is a Chinese-localized version aimed at Chinese workflows and Chinese agent prompts, and notes that the skill identity, default prompts, and copy are biased toward Chinese usage scenarios. Under the stated policy, forcing a specific language or locale without user opt-in is a natural-language policy violation.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill explicitly requires Node and browser access and instructs the agent to execute a local script, but it does not declare any tool scope such as allowed-tools or permissions. That creates an authority gap where a user-invocable skill can read local input, spawn shell commands, and potentially reach browser/network-capable code without transparent restriction, increasing the blast radius if the underlying script is compromised or behaves unexpectedly.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The skill name, description, and default prompt explicitly define the skill as Chinese-only (including the Chinese label and invocation name suffix 'cn') without indicating that users can choose another language. This is a natural-language policy concern because it imposes a locale/language constraint without opt-in or documented justification in the file.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The bundled CLI exposes capabilities well beyond the declared skill purpose of converting Markdown outlines to a KMind mindmap image: it can inspect projects, search document contents, and export embedded project data as JSON/Markdown/ZIP. In a skill context, this broadens the effective data-access surface and can be used to extract contents from KMind project SVGs supplied by users, which is a meaningful capability mismatch even if the code is not overtly malicious.

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.

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.

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.

Description-Behavior Mismatch

Medium
Confidence
92% confidence
Finding
清单描述将技能定位为把 Markdown 标题大纲转换成 KMind 导图并导出 SVG/PNG,但该浏览器渲染作业代码实际打包了完整的富文本/公式/代码高亮/链接/评论/子图/主题设计与交互式编辑器能力。虽然这些能力可能属于上游 KMind 应用的一部分,但相对于该技能声明的狭窄用途,它们明显超出了“转换并导出”这一描述。

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This file contains numerous natural-language UI strings embedded directly in Chinese inside components such as the node inspector, rather than resolving them through the i18n system used elsewhere in the same file. That creates a locale policy violation because the skill effectively forces a specific language for some users without opt-in or language selection.

Context-Inappropriate Capability

Medium
Confidence
97% confidence
Finding
The renderer fetches work from /job and posts results or errors to /result and /failure, introducing network I/O in a component whose stated purpose is local format conversion. If an attacker can influence the local HTTP service or browser environment, rendered document contents and metadata can be exfiltrated or the renderer can be driven by untrusted remote jobs without explicit user awareness.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
Remote render-job data is automatically fetched, rendered, and uploaded with no user-facing disclosure in this code path. In the context of a document-to-image conversion skill, silent remote orchestration is risky because documents being converted may contain sensitive text, formulas, notes, or embedded content that users reasonably expect to stay local.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/kmind-render.mjs:10

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/vendor/cli.mjs:6647