Back to skill

Security audit

Render Academic Diagram Images from Code

Security checks for vulnerabilities and agentic risk

Overview

The skill’s diagram-rendering purpose is coherent, but its installer runs unverified internet code and makes privileged system-wide changes.

Review carefully before installing. The rendering workflow itself fits the stated purpose, but do not run install.sh on a sensitive machine unless you are comfortable with sudo package changes, a global npm install, and an unverified remote D2 installer. Prefer manually installing pinned renderer binaries and using a local-only workflow unless you explicitly intend to send diagrams and an API key to a cloud render endpoint.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
Findings (4)

T03 · Remote Payload Retrieval and Execution

Error
Location
install.sh:29
Finding
Unverified Remote D2 Installer Is Downloaded and Executed<![CDATA[ ## Vulnerability Details **File Location**: `install.sh:29-32`; also documented in `README.md:14-16` and `README-zh.md:14-16` **Vulnerability Type**: Unverified remote code execution **Risk Level**: High ### Vulnerable Code ```bash # 2. Install D2 CLI if ! command -v d2 &> /dev/null; then echo "Installing D2..." curl -fsSL https://d2lang.com/install.sh | sh ``` The same unsafe installation command is presented directly to users in both README files: ```bash curl -fsSL https://d2lang.com/install.sh | sh ``` ### Technical Analysis The installer retrieves a mutable shell script from an external URL and immediately passes its response to `sh`. The downloaded content is not version-pinned, inspected, signature-verified, or checked against a known cryptographic digest. HTTPS protects the connection under normal conditions, but it does not guarantee that the upstream script will remain unchanged. A compromised upstream server, release process, domain, DNS path, or trusted TLS infrastructure could cause arbitrary shell commands to be returned and executed. D2 is relevant to the declared diagram-rendering functionality. However, executing an unverified remote script is not the minimum privilege or minimum-trust installation approach required to provide that functionality. ### Attack Path 1. A user follows either README or runs `install.sh`. 2. The installer requests `https://d2lang.com/install.sh`. 3. The upstream endpoint or its delivery infrastructure returns modified shell code. 4. The response is streamed directly into `sh` without review or integrity verification. 5. The malicious commands execute with all privileges available to the user running the installer. 6. The payload can read accessible files, alter user configuration, download additional executables, or establish persistence. ### Impact Assessment Successful exploitation provides arbitrary code execution under the installer user's account. This can expose source code, environm ...[truncated 380 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove all `curl | sh` instructions from the installer and documentation. 2. Pin D2 to an explicitly reviewed release version. 3. Download a versioned release artifact to a local file rather than executing a streamed response. 4. Verify the artifact using a pinned SHA-256 digest or a trusted release signature before installation. 5. Abort installation if verification fails. 6. Install into a project-local or user-local directory whenever possible. 7. Document the source URL, expected checksum, target path, and exact files installed. 8. If an upstream installer must be used, download it first, verify a pinned digest, and invoke the verified local file only after allowing inspection. ]]>

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding
Mutable and Unpinned Third-Party Dependencies<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1-5` and `install.sh:37-41,56-58` **Vulnerability Type**: Unpinned dependency installation and unsafe global package installation **Risk Level**: Medium ### Vulnerable Code `requirements.txt` does not constrain package versions or hashes: ```text httpx pydantic python-dotenv sh pillow ``` The installer also retrieves mutable package versions: ```bash # 3. Install Mermaid CLI (requires Node) if command -v npm &> /dev/null; then if ! command -v mmdc &> /dev/null; then echo "Installing mermaid-cli..." sudo npm install -g @mermaid-js/mermaid-cli else echo "Mermaid CLI already installed." fi fi ``` ```bash # Use the local venv's pip ./.venv/bin/pip install --upgrade pip ./.venv/bin/pip install -r requirements.txt ``` ### Technical Analysis Every Python dependency is specified without an exact version or integrity hash. The npm command similarly installs the package version selected by the registry at installation time. The installer also upgrades pip to a mutable latest version. Consequently, two installations performed at different times can execute and install different third-party code despite using the same audited project revision. Package installation can execute build backends or npm lifecycle scripts. The Mermaid CLI installation is particularly sensitive because it is global and runs through `sudo`. No evidence in the reviewed project establishes that the named packages are themselves malicious. The confirmed weakness is the absence of reproducible, integrity-checked dependency resolution. ### Attack Path 1. An attacker compromises a relevant package, maintainer account, release pipeline, or registry delivery path. 2. A malicious release becomes the version resolved by pip or npm. 3. A user runs `install.sh`. 4. pip installs the unconstrained Python package, or npm runs package installation behavior through `sudo`. 5. Malicious installation ...[truncated 581 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin every direct and transitive Python dependency to reviewed versions. 2. Generate a hash-locked requirements file and install with hash enforcement, such as `pip install --require-hashes`. 3. Avoid automatically upgrading pip during ordinary installation; pin and review the required installer version. 4. Add Mermaid CLI as a project-local Node dependency with an exact version and committed lockfile. 5. Use `npm ci` against the lockfile rather than a mutable global installation. 6. Do not run npm package installation through `sudo`. 7. Review dependency provenance and security advisories before updating locked versions. 8. Use automated dependency scanning while retaining manual review and reproducible builds. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/test_render.py:5
Finding
Bearer Credential Can Be Sent to an Unrestricted Plaintext Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/test_render.py:5-9,20-26` **Vulnerability Type**: Insufficient validation and transport protection for sensitive API credentials **Risk Level**: Medium ### Vulnerable Code ```python # Load ENV load_dotenv() API_URL = os.getenv("EMERGENCE_API_URL", "http://localhost:8000") API_KEY = os.getenv("EMERGENCE_API_KEY", "local_test_key") ``` ```python headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" } try: response = httpx.post(f"{API_URL}/tools/render", json=payload, headers=headers) ``` ### Technical Analysis The test script loads `EMERGENCE_API_URL` from the environment without validating its scheme or destination, then sends `EMERGENCE_API_KEY` as a bearer token. Although the default HTTP endpoint is loopback-only, an environment-provided URL can identify a non-loopback plaintext HTTP endpoint or an attacker-controlled server. The request also transmits diagram source code. The script does not enforce HTTPS for remote destinations, restrict destinations to an allowlist, set an explicit timeout, or visibly constrain redirect behavior. This is not a hard-coded credential: `local_test_key` is only a fallback test value. The risk applies when a real key is loaded from the environment or `.env` file and the endpoint is unsafe or attacker-controlled. ### Attack Path 1. A user has a valid `EMERGENCE_API_KEY` in the environment or a loaded `.env` file. 2. An attacker, compromised shell configuration, automation environment, or user error sets `EMERGENCE_API_URL` to an attacker-controlled URL or a non-loopback HTTP endpoint. 3. The user runs `scripts/test_render.py`. 4. The script sends the bearer credential and diagram content to the configured endpoint. 5. The attacker captures the token and submitted content. 6. The attacker reuses the token against services where it remains valid. ### Impact Assessment The exposed scope is determined by the permissi ...[truncated 367 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse and validate `EMERGENCE_API_URL` before constructing the request. 2. Require HTTPS for every non-loopback destination. 3. Permit plaintext HTTP only for explicit loopback addresses such as `127.0.0.1`, `::1`, and validated `localhost`. 4. Consider restricting remote endpoints to a documented allowlist. 5. Disable redirects or independently validate every redirect destination before forwarding an authorization header. 6. Add an explicit connection and response timeout. 7. Warn users that the API key and diagram source will be transmitted. 8. Prefer a dedicated, narrowly scoped test credential rather than a production API key. 9. Fail closed when the URL is malformed, includes embedded credentials, or uses an unsupported scheme. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
install.sh:16
Finding
Installer Performs Unnecessary and System-Wide Privileged Changes<![CDATA[ ## Vulnerability Details **File Location**: `install.sh:16-20` and `install.sh:37-41` **Vulnerability Type**: Excessive privilege and unnecessary system-wide package installation **Risk Level**: Medium ### Vulnerable Code ```bash # 1. Install System Dependencies (Graphviz) if [[ "$PLATFORM" == "Linux" ]]; then if command -v apt-get &> /dev/null; then echo "Installing graphviz via apt..." sudo apt-get update && sudo apt-get install -y graphviz plantuml default-jre fi ``` ```bash # 3. Install Mermaid CLI (requires Node) if command -v npm &> /dev/null; then if ! command -v mmdc &> /dev/null; then echo "Installing mermaid-cli..." sudo npm install -g @mermaid-js/mermaid-cli ``` ### Technical Analysis The installer automatically invokes `sudo` to modify operating-system packages and the global npm environment. The declared runtime supports Mermaid, D2, and Graphviz, while the reviewed rendering code invokes only `mmdc`, `d2`, and `dot`. It does not invoke PlantUML or Java. Installing `plantuml` and `default-jre` therefore exceeds the dependencies demonstrated by the implementation. The global Mermaid installation also has a broader scope than necessary because it can be installed project-locally and invoked from that controlled environment. The package names are fixed rather than attacker-controlled, so the code does not directly provide a command-injection route. The security issue is violation of least privilege and expansion of the trusted system-wide dependency surface. ### Attack Path 1. A user runs `install.sh`. 2. The script requests administrative authorization through `sudo`. 3. It updates package metadata and installs Graphviz, PlantUML, and a Java runtime system-wide. 4. It later performs a global npm installation through `sudo`. 5. Any compromised package, package lifecycle behavior, or repository-delivered component involved in these operations executes with elevated privileges. 6. Unnecessary ...[truncated 553 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `plantuml` and `default-jre` unless PlantUML becomes an explicitly implemented and documented renderer. 2. Do not invoke `sudo` automatically from the project installer. 3. Check prerequisites and present separate, explicit operating-system installation instructions when administrative access is genuinely required. 4. Install Mermaid CLI as a pinned project-local dependency rather than a global npm package. 5. Allow users or administrators to review and approve privileged operations independently. 6. Separate unprivileged project setup from optional system dependency setup. 7. Clearly document every system-level modification and why it is required. 8. Prefer containers, user-local binary directories, or other isolated environments when practical. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (31)

Tainted flow: 'headers' from os.getenv (line 20, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Content
}
    
    try:
        response = httpx.post(f"{API_URL}/tools/render", json=payload, headers=headers)
        if response.status_code == 200:
            print("✅ Success: Rendering API is online and functional.")
            data = response.json()
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

External Script Fetching

High
Category
Supply Chain
Content
### 1. 系统依赖
- **Graphviz**: `brew install graphviz` (Mac) 或 `apt-get install -y graphviz` (Linux)。
- **D2**: `curl -fsSL https://d2lang.com/install.sh | sh`
- **Mermaid CLI**: `npm install -g @mermaid-js/mermaid-cli`

### 2. 自动化配置
Confidence
98% confidence
Finding
The documentation instructs users to execute a remotely fetched shell script directly via `curl ... | sh`, which bypasses meaningful inspection and executes whatever the remote server returns at install time. In the context of an agent skill that emphasizes autonomy and local execution, this is more dangerous because an autonomous agent or user may run the command non-interactively, enabling supply-chain compromise or remote code execution if the source is malicious or later compromised.

External Script Fetching

High
Category
Supply Chain
Content
### 1. System Dependencies
- **Graphviz**: `brew install graphviz` (Mac) or `apt-get install -y graphviz` (Linux).
- **D2**: `curl -fsSL https://d2lang.com/install.sh | sh`
- **Mermaid CLI**: `npm install -g @mermaid-js/mermaid-cli`

### 2. Auto-Configuration
Confidence
97% confidence
Finding
The installation instructions recommend piping a remotely fetched script directly into sh, which executes unverified code from the network with the user's privileges. This creates a straightforward supply-chain compromise path if the remote server, transport, DNS, or installation script is tampered with, and it is especially risky in a skill intended for autonomous or semi-automated setup.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared description promises a broader diagram-generation system with multiple output formats (Mermaid, D2, Graphviz) plus rendering and persistent history features. The supplied code implements only a small CLI utility that converts JSON node/edge data into Mermaid flowchart syntax. It does not render diagrams, store history, or support D2 or Graphviz. While the Mermaid-related portion is consistent, the actual code is materially narrower than the declared purpose, so this is a description-behavior mismatch.

Chaining Abuse

High
Category
Tool Misuse
Content
if [[ "$PLATFORM" == "Linux" ]]; then
    if command -v apt-get &> /dev/null; then
        echo "Installing graphviz via apt..."
        sudo apt-get update && sudo apt-get install -y graphviz plantuml default-jre
    fi
elif [[ "$PLATFORM" == "Mac" ]]; then
    if command -v brew &> /dev/null; then
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

External Script Fetching

High
Category
Supply Chain
Content
# 2. Install D2 CLI
if ! command -v d2 &> /dev/null; then
    echo "Installing D2..."
    curl -fsSL https://d2lang.com/install.sh | sh
else
    echo "D2 already installed."
fi
Confidence
99% confidence
Finding
This line fetches an external script and executes it immediately, creating a direct remote code execution path during installation. Because this skill is for diagram rendering and persistent run history, such execution is not inherently required and is more dangerous in an agent environment that may process sensitive local data.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The script downloads and immediately executes a remote installer from d2lang.com using curl piped to sh. This gives the remote server full code execution during installation, and if the endpoint, transport, DNS, or upstream content is compromised, the host running the installer can be fully compromised as well.

Chaining Abuse

High
Category
Tool Misuse
Content
# 2. Install D2 CLI
if ! command -v d2 &> /dev/null; then
    echo "Installing D2..."
    curl -fsSL https://d2lang.com/install.sh | sh
else
    echo "D2 already installed."
fi
Confidence
99% confidence
Finding
Piping curl output into sh is a dangerous command chain because it converts remote content directly into executable shell instructions with no validation boundary. In this installer, that means anyone who can influence the remote response can run arbitrary code on the target machine during setup.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The README explicitly states that every rendering attempt is saved in ./runs/, which can capture user-supplied diagram source, compiler errors, paths, tokens, or other sensitive operational data. In an autonomous-agent context, persistent history increases risk because agents may process confidential inputs recursively and retain them without user awareness or retention controls.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill requests or implies powerful capabilities (environment access, file read/write, network, and shell) but does not declare any explicit tool scope or permissions boundary. In an autonomous agent setting, this creates an over-privileged execution path where the skill may invoke sensitive operations without clear least-privilege constraints, increasing the chance of data exposure, filesystem modification, or command execution beyond diagram rendering needs.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The activation phrases are broad enough to match common user language such as 'draw' or 'show me,' which can cause the skill to activate in contexts where diagram rendering was not explicitly intended. In an agent environment with shell and file capabilities, over-triggering increases the risk of unnecessary code generation, file creation, command execution, or inadvertent handling of sensitive user content.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill explicitly stores rendering attempts and artifacts in persistent run directories, but the description does not warn users that their prompts, generated diagrams, metadata, and stderr outputs may be retained on disk. This can expose sensitive architectural details, credentials accidentally included in prompts, or internal system information through persistent local artifacts.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
if [[ "$PLATFORM" == "Linux" ]]; then
    if command -v apt-get &> /dev/null; then
        echo "Installing graphviz via apt..."
        sudo apt-get update && sudo apt-get install -y graphviz plantuml default-jre
    fi
elif [[ "$PLATFORM" == "Mac" ]]; then
    if command -v brew &> /dev/null; then
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
Using curl-pipe-shell without any user warning or integrity verification hides the fact that arbitrary network-fetched code is being executed. In an agent skill installer, this is especially risky because users may assume the script only installs rendering dependencies, while it actually grants a remote party execution on the local system.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
if command -v npm &> /dev/null; then
    if ! command -v mmdc &> /dev/null; then
        echo "Installing mermaid-cli..."
        sudo npm install -g @mermaid-js/mermaid-cli
    else
        echo "Mermaid CLI already installed."
    fi
Confidence
87% confidence
Finding
Using sudo with npm install -g runs package installation scripts with elevated privileges, which can lead to system-wide compromise if a dependency is malicious or the package supply chain is tampered with. Global npm installs are higher risk than isolated local installs because they expand trust to package lifecycle hooks under root.

Description-Behavior Mismatch

Medium
Confidence
89% confidence
Finding
The installer explicitly states that Mermaid rendering will fall back to a cloud API when Node/NPM is unavailable, which can cause diagram contents to be sent off-host. For a 'local-first' skill used by autonomous agents, this creates an unnecessary data exposure path and undermines the privacy/security expectations established by the skill description.

Context-Inappropriate Capability

Medium
Confidence
84% confidence
Finding
The manifest describes high-fidelity diagram generation and local-first rendering, but this implementation achieves that by executing local commands (`mmdc`, `d2`, `dot`) via the `sh` library. Spawning external processes is a materially stronger capability than ordinary in-process rendering and is not explicitly justified by the manifest text.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This code invokes external binaries (`mmdc`, `d2`, and `dot`) to process user-provided diagram content, which is a safety-relevant operation for a code file. Although the docstring says it uses local binaries, there is no visible confirmation prompt or user-facing warning at the execution point about launching subprocesses on local input.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
This README forces a specific language/locale presentation for the skill instructions and does not indicate that users may choose another language. Under the policy, language-specific behavior should offer user choice unless the locale restriction is clearly justified.

Vague Triggers

Low
Confidence
84% confidence
Finding
The manifest description says the skill performs diagram generation from 'natural language descriptions,' but it does not define any specific trigger phrases, scope limits, or exclusion conditions. In a manifest file, this broad wording can make invocation boundaries unclear and increase the chance of unintended matching.

Unpinned Dependencies

Low
Category
Supply Chain
Content
httpx
pydantic
python-dotenv
sh
Confidence
96% confidence
Finding
The dependency 'httpx' is unpinned, so builds may silently resolve to different versions over time. That creates supply-chain and reproducibility risk, and because advisories exist for some httpx versions, it is impossible to verify from this manifest whether deployments are exposed.

Unverifiable Dependency: httpx has 2 known advisory(ies) (CVE-2021-41945 (Improper Input Validation in httpx); CVE-2021-41945 (Encode OSS httpx <=1.0.0.beta0 is affected by improper input validation in `http)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
90% confidence
Finding
Because httpx is not pinned, the manifest cannot prove whether the installed version includes fixes for known advisories. In a rendering skill with possible network retrieval or remote asset access, uncertainty around the HTTP client version creates avoidable exposure and undermines trustworthy deployment review.

Unpinned Dependencies

Low
Category
Supply Chain
Content
httpx
pydantic
python-dotenv
sh
pillow
Confidence
96% confidence
Finding
The dependency 'pydantic' is unpinned, allowing environment-dependent resolution to potentially vulnerable or breaking releases. Since pydantic has multiple known advisories across versions, the lack of version control weakens supply-chain assurance for this skill.

Unverifiable Dependency: pydantic has 4 known advisory(ies) (CVE-2021-29510 (Use of "infinity" as an input to datetime and date fields causes infinite loop i); CVE-2024-3772 (Pydantic regular expression denial of service); CVE-2021-29510 (Pydantic is a data validation and settings management using Python type hinting.) +1 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
91% confidence
Finding
The unpinned pydantic dependency prevents verification that the runtime version is not affected by known CVEs. Since pydantic often processes structured input from agents or users, unresolved version uncertainty can expose parsing or validation paths to known bugs.

Unpinned Dependencies

Low
Category
Supply Chain
Content
httpx
pydantic
python-dotenv
sh
pillow
Confidence
95% confidence
Finding
The dependency 'python-dotenv' is unpinned, which means package resolution may change unexpectedly between installs. This is a supply-chain hygiene issue, and known advisories against some versions make the manifest insufficient to assess actual exposure.

Static analysis

No suspicious patterns detected.