Back to skill

Security audit

arch-diagram

Security checks for vulnerabilities and agentic risk

Overview

This skill appears intended to generate local architecture diagrams, but it has review-worthy weaknesses that can read files outside the target repo through symlinks and generate HTML that can run injected scripts.

Install only if you trust the repositories you will scan and are comfortable sending source contents into the agent workflow. Avoid running it on repos that may contain symlinks, secrets, or untrusted code comments, and treat generated HTML reports as active web pages rather than inert documents.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
Findings (4)

T01 · Skill Instruction Hijacking

Error
Location
references/prompts.md:8
Finding
Untrusted Repository Content Can Hijack Model Instructions<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:66-72`; `references/prompts.md:8-31` **Vulnerability Type**: Prompt injection through untrusted repository contents **Risk Level**: High ### Vulnerable Code `SKILL.md:66-72`: ```markdown 将扫描结果的 `files` 数组分批处理: - **每批最多 30 个文件**,或预估总内容不超过 60k tokens - 对每批,按 `references/prompts.md` 中的「Stage 1」prompt 模板,构造请求: - 将文件列表格式化为 `=== 文件: path ===\n<内容>` 的形式 - 让 Claude(自己)生成一个 JSON 对象 `{"文件路径": "摘要"}` - 合并所有批次的摘要,得到完整的 `code_summary` 字典 ``` `references/prompts.md:8-31`: ```text 你是一名资深软件工程师。请阅读以下代码文件列表,为每个文件生成一句话摘要(不超过30字),概括其业务功能。 只输出一个 JSON 对象,格式为 {"文件路径": "一句话摘要", ...},不要任何多余内容。 注意: - 摘要要体现业务语义(如"处理用户登录逻辑"),而非技术细节(如"定义了3个类") - 最多提及关键类名或方法名 - 不要超过30字 $FILES ``` The `$FILES` value is populated as follows: ```text === 文件: path/to/file1.py === <文件内容> === 文件: path/to/file2.java === <文件内容> ``` ### Technical Analysis The Skill directly inserts attacker-controlled source-file contents into an Agent prompt. The prompt does not establish that repository content is untrusted data and does not instruct the model to ignore commands, role changes, output overrides, or tool-use requests found inside source files. Comments, strings, documentation blocks, or other text in a scanned repository can therefore contain instructions that compete with the Stage 1 prompt. If followed, those instructions can alter the generated summary JSON. The resulting summaries are then trusted by Stage 2 and Stage 3, allowing the injected instructions to influence architecture nodes, file associations, relationship data, and Mermaid content. The output requirement to return JSON is not a security boundary. An attacker can ask the model to return syntactically valid but misleading or payload-bearing JSON. ### Attack Path 1. An attacker places instruction-like content inside a supported source file, such as a `.py`, `.js`, or `.ts` file. 2. `scan_repo.py` reads that file and returns its complete contents. 3. The Skill inserts ...[truncated 1101 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Explicitly state in every model prompt that repository content is untrusted data and that instructions found inside files must never be followed. 2. Enclose each file in a strongly delimited structured representation that separates trusted instructions from untrusted content. 3. Use separate message roles or structured tool payloads where supported instead of concatenating raw content into the instruction text. 4. Validate Stage 1 output against the scanner result: - Require exactly one summary for every scanned path. - Reject unknown or additional paths. - Reject missing paths. - Enforce string type and length limits. 5. Treat all Stage 1 output as untrusted when constructing Stage 2 and Stage 3 prompts. 6. Add adversarial tests containing source comments such as output overrides, role changes, fake system messages, and requests to omit files. 7. Consider using deterministic local parsing for basic metadata and limiting model processing to the minimum content necessary. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/scan_repo.py:96
Finding
Repository Symlinks Can Expose Files Outside the Repository Root<![CDATA[ ## Vulnerability Details **File Location**: `scripts/scan_repo.py:96-124` **Vulnerability Type**: Out-of-root file read through symbolic links **Risk Level**: High ### Vulnerable Code ```python for dirpath, dirnames, filenames in os.walk(root): # 过滤忽略目录(就地修改 dirnames 以阻止 os.walk 递归进去) dirnames[:] = [d for d in dirnames if d not in IGNORE_DIRS and not d.startswith(".")] for filename in sorted(filenames): ext = filename.rsplit(".", 1)[-1].lower() if "." in filename else "" if ext not in CODE_FILE_EXTENSIONS: continue full_path = Path(dirpath) / filename # 相对于 repo_path 的父目录(保留项目名作为前缀,与原项目一致) try: rel_path = full_path.relative_to(root.parent).as_posix() except ValueError: rel_path = full_path.relative_to(root).as_posix() try: content = full_path.read_text(encoding="utf-8") except UnicodeDecodeError: try: content = full_path.read_text(encoding="gbk", errors="ignore") except Exception: content = "" except Exception: content = "" ``` ### Technical Analysis The scanner validates files according to the extension of the repository directory entry but does not reject symbolic links. `Path.read_text()` follows a symbolic link and reads its target. The code never resolves `full_path` and verifies that the resolved target remains within `root`. Consequently, a repository entry named with a supported extension can point to any readable file outside the repository. For example, a repository could contain `external_secret.py` as a symlink to a sensitive file in the user's home directory. The scanner would accept the `.py` extension and read the target. The calculated relative path does not mitigate the issue because it is based on the unresolved directory entry rather than the actual target. ### Attack Path 1. An attacker prepares a repository containing a sy ...[truncated 1291 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Reject symbolic links before reading: ```python if full_path.is_symlink(): continue ``` 2. Resolve each candidate and enforce repository containment: ```python resolved = full_path.resolve(strict=True) if not resolved.is_relative_to(root): continue ``` 3. On Python versions without `Path.is_relative_to()`, use a safe `relative_to(root)` check and reject `ValueError`. 4. Apply the containment check to every file immediately before opening it. 5. Where supported, use operating-system facilities such as `O_NOFOLLOW` to reduce time-of-check/time-of-use symlink races. 6. Consider rejecting hard-linked files when the threat model requires strict ownership of repository contents. 7. Report skipped symlinks and out-of-root targets without displaying their contents. 8. Add tests for: - Absolute symlink targets. - Relative symlinks containing `..`. - Symlink chains. - Symlinks replaced between validation and opening. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/build_html.py:62
Finding
Unsafe HTML Template Substitution Enables Script Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/build_html.py:62-78`; `assets/arch_diagram_static.html:606-622` **Vulnerability Type**: Generated HTML and JavaScript injection **Risk Level**: High ### Vulnerable Code `scripts/build_html.py:62-78`: ```python template = template_path.read_text(encoding="utf-8") template = template.replace("<!--REPO_NAME-->", repo_name) template = template.replace( "<!--MINDMAP_DATA_JSON-->", json.dumps(mindmap_str, ensure_ascii=False) ) template = template.replace( "<!--FLOWCHART_DATA_JSON-->", json.dumps(flowchart_data, ensure_ascii=False) ) template = template.replace( "<!--EDGES_DATA_JSON-->", json.dumps(edges_data, ensure_ascii=False) ) template = template.replace( "<!--REPO_META_JSON-->", json.dumps(meta, ensure_ascii=False) ) ``` `assets/arch_diagram_static.html:606-622`: ```html <script> // 代码仓名称 const REPO_NAME = "<!--REPO_NAME-->"; // 主架构思维导图(plantuml mindmap 文本) const MINDMAP_DATA = <!--MINDMAP_DATA_JSON-->; // 预生成的子架构 Mermaid 数据 // 格式: { "<nodeKey>": "<mermaid code>", ... } const FLOWCHART_DATA = <!--FLOWCHART_DATA_JSON-->; // 节点间调用关系(只允许上层→下层) // 格式: [{"from": "节点名A", "to": "节点名B", "label": "调用"}, ...] const EDGES_DATA = <!--EDGES_DATA_JSON-->; // 仓库元信息(由 scan_repo.py --stats-output 生成) // 格式: { "repo_name": "...", "description": "...", "file_count": 42, // "total_loc": 3800, "tech_stack": [{"lang":"Python","count":20,"loc":1500},...] } const REPO_META = <!--REPO_META_JSON-->; </script> ``` ### Technical Analysis `repo_name` is inserted directly into both HTML and an executable JavaScript string without context-sensitive escaping. A quote in the value can terminate the JavaScript string and introduce executable syntax. The remaining values are processed with `json.dumps()`, which protects JSON string delimiters but does not make a value safe for direct placement inside an HTML `<script>` element. ...[truncated 1903 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not interpolate untrusted data directly into executable script blocks. 2. Put serialized data in non-executable `<script type="application/json">` elements and read it through `textContent`. 3. Before embedding JSON in HTML, escape at least `<`, `>`, `&`, and the Unicode line-separator characters. For example, encode `<` as `\u003c`. 4. Serialize `repo_name` using a context-aware JavaScript serializer rather than placing it inside literal quotation marks. 5. HTML-escape the repository name when inserting it into the `<title>` element. 6. Prefer a well-maintained template engine with automatic context-aware escaping. 7. Add a restrictive Content Security Policy. Remove inline scripts or authorize reviewed scripts with hashes or nonces. 8. Validate all generated fields against strict schemas and reasonable length limits. 9. Test payloads containing: - Quotes and backslashes. - `</script>`. - HTML tags. - Unicode line separators. - Strings propagated from mindmap, Mermaid, metadata, and edge fields. ]]>

T08 · Insecure Dependencies

Warning
Location
assets/arch_diagram_static.html:625
Finding
Generated Reports Execute an Integrity-Unprotected Third-Party CDN Script<![CDATA[ ## Vulnerability Details **File Location**: `assets/arch_diagram_static.html:625` **Vulnerability Type**: Unsafe runtime dependency loading **Risk Level**: Medium ### Vulnerable Code ```html <script src="https://cdn.bootcdn.net/ajax/libs/mermaid/10.9.1/mermaid.min.js"></script> ``` ### Technical Analysis Every generated report loads and executes Mermaid JavaScript from a third-party CDN at runtime. Although the URL specifies a version, the script element does not provide a Subresource Integrity hash. The browser therefore has no cryptographic mechanism to verify that the received script is the exact reviewed Mermaid artifact. The page also lacks a restrictive Content Security Policy in the reviewed template. A compromised CDN, malicious upstream replacement, DNS or network redirection under a weakened trust environment, or CDN account compromise could cause arbitrary JavaScript to execute when a report is opened. This behavior also conflicts with the documented expectation that the generated file is an independent static HTML page, because rendering requires an external network dependency. ### Attack Path 1. The user generates an architecture report. 2. The user opens the report while connected to a network. 3. The browser requests `mermaid.min.js` from the configured third-party CDN. 4. The CDN resource or delivery path supplies modified JavaScript. 5. Because no integrity hash is present, the browser accepts and executes the modified resource. 6. The malicious dependency runs with the same page privileges as the report's own JavaScript. ### Impact Assessment A compromised dependency can execute arbitrary browser-side JavaScript in every generated report that loads it. This can allow: - Manipulation of report contents. - Collection of report metadata and architecture information. - Outbound exfiltration requests. - Phishing or malicious UI injection. - Exploitation of privileges associated with a trusted hosting origin if the report is se ...[truncated 236 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Bundle a reviewed Mermaid distribution inside the Skill and embed or copy it into generated reports. 2. Pin the dependency to an exact reviewed artifact and record its cryptographic checksum. 3. If remote loading is unavoidable, add a correct Subresource Integrity value and `crossorigin="anonymous"`: ```html <script src="https://trusted.example/mermaid.min.js" integrity="sha384-REVIEWED_HASH" crossorigin="anonymous"></script> ``` 4. Use a restrictive Content Security Policy that permits scripts only from explicitly approved sources and preferably disallows inline scripts. 5. Establish a dependency-update process that verifies release provenance, hashes, security advisories, and license information. 6. Add an offline test confirming that the generated report works without network access. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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 (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
声明描述的是一个端到端的仓库架构可视化技能:扫描仓库、分析代码、产出图数据并生成 HTML。实际代码只是后处理/渲染步骤:读取现成的 mindmap 文本和若干 JSON 文件,替换 HTML 模板占位符,输出静态网页。从权限和资源访问看,它只访问指定输入文件和模板文件,没有自动扫描当前目录的逻辑,也没有仓库解析、架构理解或图生成逻辑。因此该代码片段与声明的主要能力明显不一致;它最多覆盖了“最终输出 HTML 文件”的最后一步。

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
声明描述的是一个端到端的“代码仓架构可视化生成器”,最终产物应是独立静态 HTML 页面,包含架构图/思维导图/模块流程图。而实际代码只是前置数据收集脚本:扫描代码文件、读取内容、计算 LOC 和技术栈统计,并输出 JSON 供后续处理。它没有任何 HTML 生成、浏览器页面构建、图表/流程图渲染、架构推理或可视化逻辑。虽然“扫描代码仓”与声明中的前置步骤部分相关,但该代码块的实际主要功能与声明的主要交付物明显不一致,因此应判定为描述与行为不匹配。

Ae1

High
Category
analysis-evasion
Content
- `assets/arch_diagram_static.html` — HTML 模板
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Hidden Instructions

High
Category
Prompt Injection
Content
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>架构可视化图 - <!--REPO_NAME--></title>
    <style>
        * {
            margin: 0;
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill instructs the agent to read from the repository, write cache/output files, and invoke local scripts, but it does not declare any explicit tool scope or permissions boundary. In an agent environment, this increases the chance of over-broad file access or unintended writes because users and policy layers cannot clearly constrain what the skill is allowed to touch.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill description does not clearly warn that it will scan the entire current repository and read source contents. In a code-assistant context, this matters because repositories often contain secrets, proprietary code, or unrelated sensitive files, and a user may trigger broad ingestion without understanding the scope.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The natural-language description and operating instructions are written entirely in Chinese and do not indicate that language is configurable or intentionally limited to a Chinese-only audience. Under the policy, forcing a specific language without user opt-in is a locale/language constraint that should be documented or made optional.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The root HTML tag sets `lang="zh-CN"`, and the user-facing UI text throughout the page is also hard-coded in Chinese. For a general-purpose architecture visualization page, this imposes a specific language/locale without any opt-in or justification, which matches the natural-language locale policy violation criteria.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The static HTML unconditionally loads Mermaid from a third-party CDN, which introduces an external network trust dependency into a tool advertised as a standalone local visualization page. If the CDN is unavailable, blocked, or serves compromised content, the generated page can fail open or execute attacker-controlled JavaScript in the browser context.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The Stage 2 prompt explicitly instructs the model to '使用中文', which imposes a specific language choice on all users. This is a natural-language policy concern because the file does not provide user opt-in, alternatives, or a documented justification for requiring Chinese output.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The Stage 2a prompt again requires output in Chinese via '使用中文' with no opt-in or fallback language. Requiring a fixed language across users can violate language/locale policy when not explicitly justified.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The Stage 2b prompt mandates Chinese output using '使用中文' while giving no user choice and no rationale for the locale constraint. This is a repeated policy issue in natural-language instructions.

Natural-Language Policy Violations

Medium
Confidence
98% confidence
Finding
The Stage 3 prompt specifies '使用简体中文', which is an explicit locale requirement. Because the file does not offer a language choice or explain why Simplified Chinese is required, this creates a language/locale policy violation.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The script serializes and prints the full contents of every discovered code file to stdout, which can expose secrets, proprietary source, or unrelated sensitive material present in the scanned tree. In the context of a skill that claims to generate an architecture diagram, exporting raw source is an over-collection/data-exposure risk because downstream components receive far more data than is necessary for the stated purpose.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The manifest describes a root-only, current-directory-based workflow, but this script requires an explicit repo_path argument and will scan whatever directory the caller supplies. That is a semantic mismatch in operating scope and invocation model, even though the underlying task is still repository scanning.

Missing User Warnings

Low
Confidence
89% confidence
Finding
The skill writes cache, temporary, and final output files, including predictable paths under cache/, output/, and /tmp, but the description does not prominently disclose this. Undocumented writes can expose summarized code content, metadata, or generated diagrams to other local users or later processes, especially on shared systems.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
This code file contains natural-language strings that require Chinese comprehension for usage, parameters, and output interpretation. Under the policy, forcing a specific language without opt-in is a locale/language policy issue when no alternative language or justification is provided.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The module docstring, usage text, and output descriptions are entirely in Chinese, and the CLI argument descriptions later in the file also assume Chinese-language users. Under the language/locale policy rule, this is a natural-language constraint without any opt-in, alternative locale, or justification that the skill is region-specific.

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
Natural-language strings in the module docstring specify behavior and usage entirely in Chinese, including the stated output contract, and the CLI descriptions later continue this pattern. For a general-purpose repository scanning script, this imposes a specific language/locale without user opt-in or a documented justification, which matches the policy-violation category.

Static analysis

No suspicious patterns detected.