Back to skill

Security audit

Excalidraw Canvas

Security checks for vulnerabilities and agentic risk

Overview

This diagramming skill uses a hosted renderer as advertised, with privacy and temporary-file caveats users should understand before using it for sensitive diagrams.

Install only if you are comfortable sending diagram text, labels, structure, and other element data to the hosted renderer. Do not use it for confidential architecture, credentials, incident details, or private business workflows unless that external service is acceptable, and treat the returned edit URL as a shareable access link. A safer version would use unique temporary files and offer local or self-hosted rendering for sensitive diagrams.

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

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:19
Finding

Predictable Temporary File Path Permits Symlink-Based File Clobbering

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, line 19; repeated at line 84
Vulnerability Type: Unsafe temporary-file handling
Risk Level: Medium

Vulnerable code at line 19:

bash
# Save PNG
echo "$RESULT" | python3 -c "import json,sys,base64; d=json.load(sys.stdin); open('/tmp/diagram.png','wb').write(base64.b64decode(d['png']))"

Repeated vulnerable code at line 84:

bash
echo "$RESULT" | python3 -c "import json,sys,base64; d=json.load(sys.stdin); open('/tmp/diagram.png','wb').write(base64.b64decode(d['png'])); print(d['editUrl'])"

Technical Analysis

The documented workflow writes rendered image data to the fixed, globally predictable path /tmp/diagram.png. Python's standard open() operation follows symbolic links and opens the destination with truncation when using wb mode.

On a multi-user system, another local process can create /tmp/diagram.png as a symbolic link to a file writable by the account running the Skill. When the workflow executes, the linked target is truncated and replaced with bytes returned by the remote rendering service. Separate concurrent Skill invocations can also overwrite or read one another's output because they share the same filename.

The base64 operation does not constitute decoded-command execution: it only converts the API's png field into bytes and writes those bytes to a file. No decoded content is executed. Likewise, the reviewed file does not contain a curl | bash pipeline or other remote-script execution. The security issue is limited to unsafe handling of the output file.

Attack Path

  1. A local attacker with access to the shared /tmp directory predicts the documented output path.
  2. Before the Skill runs, the attacker creates /tmp/diagram.png as a symbolic link to a target file writable by the Skill's operating-system account.
  3. The Skill submits diagram data to the hosted rendering API and receives a base64-encode ...[truncated 1416 chars]
Remediation
View remediation

Remediation Suggestions

Replace the fixed pathname with an exclusively created, unpredictable temporary file. Python's tempfile module is preferred:

bash
OUTPUT_PATH=$(echo "$RESULT" | python3 -c "
import base64
import json
import os
import sys
import tempfile

data = json.load(sys.stdin)
png = base64.b64decode(data['png'], validate=True)

with tempfile.NamedTemporaryFile(
    mode='wb',
    prefix='excalidraw-',
    suffix='.png',
    delete=False,
    dir='/tmp'
) as output:
    output.write(png)
    print(output.name)
")

Additional hardening measures should include:

  1. Create files atomically and exclusively rather than checking whether a path exists before opening it.
  2. Use a private temporary directory created with tempfile.TemporaryDirectory() or mktemp -d, with permissions restricted to the current account.
  3. Return the generated unique path to the message-sending step instead of assuming /tmp/diagram.png.
  4. Remove the temporary artifact after it has been sent, preferably in a cleanup handler.
  5. Validate the base64 response with validate=True and impose a reasonable decoded-size limit to prevent malformed or excessively large responses.
  6. Apply the same correction to both occurrences at lines 19 and 84.
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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (8)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill instructs the agent to render diagrams through a hosted API but does not warn that all diagram content is transmitted to a third-party service. Because diagrams may contain architecture details, credentials, incident data, or internal workflows, this omission can lead to unintended data exfiltration.

Content

No source excerpt is available for this finding.

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

Render

bash
RESULT=$(curl -s -m 60 -X POST https://excalidraw-mcp.up.railway.app/api/render \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"elements": [...]}')

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill says an edit URL is always generated and should always be shared, but does not warn that possession of that URL may grant access to view or modify the diagram. If the diagram contains sensitive information, indiscriminate sharing of the edit link can leak data or allow unauthorized changes.

Content

No source excerpt is available for this finding.

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

Full Example

bash
RESULT=$(curl -s -m 60 -X POST https://excalidraw-mcp.up.railway.app/api/render \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"elements": [

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The activation description is very broad ('use whenever you need to draw... diagram anything'), which can cause the skill to trigger for many ordinary requests without clearly signaling that content will be sent to a third-party rendering service. In context, that increases the chance that sensitive user content is routed externally without informed consent.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

This command sends user-provided diagram elements to an external domain over the network. In a diagramming skill, that behavior is expected, but it is still a real data-transfer risk because the content may contain sensitive business or personal information.

Content

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

Render

bash
RESULT=$(curl -s -m 60 -X POST https://excalidraw-mcp.up.railway.app/api/render \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"elements": [...]}')

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The instructions write the returned PNG to /tmp/diagram.png without warning that generated content is stored on the local filesystem. Local file writes can expose sensitive diagrams to other processes, later steps, or users on shared systems if lifecycle and permissions are not controlled.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

The full example repeats the same pattern of posting diagram contents to a third-party rendering endpoint. The contextual legitimacy of rendering does not remove the security concern; it confirms that external transmission is part of normal operation and therefore must be governed by consent and data-handling controls.

Content

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

Full Example

bash
RESULT=$(curl -s -m 60 -X POST https://excalidraw-mcp.up.railway.app/api/render \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"elements": [

Static analysis

No suspicious patterns detected.