Back to skill

Security audit

Excalidraw Creator

Security checks for vulnerabilities and agentic risk

Overview

This skill coherently renders local Excalidraw-style diagram JSON into PNGs, with ordinary setup and supply-chain risks but no evidence of hidden data access, exfiltration, persistence, or destructive behavior.

Install only if you are comfortable running a local Node renderer and setup script that installs npm packages and downloads fonts. On shared machines, avoid running setup.sh with elevated privileges because of its predictable /tmp usage; prefer a version that verifies downloaded font hashes and pins dependencies more tightly.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/setup.sh:42
Finding

Predictable Shared Temporary Paths Allow Symlink-Based File Overwrite

Content
View full analysis
/dev/null || true find cascadia_extract -name "CascadiaCode*.woff2" -not -path "*/static/*" | head -1 | xargs -I{} cp {} "$FONT_DIR/CascadiaCode.woff2" 2>/dev/null || true find cascadia_extract -name "CascadiaCode-Regular.ttf" | head -1 | xargs -I{} cp {} "$FONT_DIR/CascadiaCode.ttf" 2>/dev/null || true rm -rf cascadia.zip cascadia_extract cd "$SCRIPT_DIR" ``` ### Technical Analysis The setup script uses the fixed, globally predictable paths `/tmp/cascadia.zip` and `/tmp/cascadia_extract`. These paths are not created through a secure primitive such as `mktemp`, and the script does not verify that the archive path is a regular file owned by the current user. On systems where `/tmp` is shared among users, a local attacker can create `/tmp/cascadia.zip` as a symbolic link before setup begins. Because `curl -o` follows symbolic links, the downloaded archive can overwrite the link target with the privileges of the user running the setup script. The fixed extraction directory also permits local interference and collisions between concurrent setup processes. An attacker may pre-populate or manipulate that directory while extraction and subsequent `find` operations are in progress. The use of `2>/dev/null || true` suppresses extraction and copy failures, making tampering or corrupted installation state less visible. This behavior is unnecessary for the declared diagram-rendering functionality. Temporary artifacts can be handled in a private per-process directory without requiring elevated privileges or globally predictable paths. ### Attack Path 1. A loca ...[truncated 1429 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
scripts/setup.sh:17
Finding

Downloaded Font Artifacts Are Not Cryptographically Verified

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Known Vulnerable Dependency: form-data==4.0.5 — 1 advisory(ies): CVE-2026-12143 (form-data: CRLF injection in form-data via unescaped multipart field names and f)

High
Category
Supply Chain
Confidence
86% confidence
Finding

The lockfile pins form-data 4.0.5, which is reported as vulnerable to CRLF injection in multipart field names. In this file it is only a transitive dependency of jsdom, so exploitability depends on whether the skill ever constructs multipart requests using attacker-controlled field names through that library path; that makes the issue real but somewhat context-limited here.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ws==8.19.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
90% confidence
Finding

The lockfile includes ws 8.19.0, which is flagged for memory disclosure and memory-exhaustion denial of service issues. Because this is brought in transitively by jsdom, risk depends on whether the skill processes untrusted WebSocket traffic or loads attacker-controlled content that can trigger WebSocket behavior, but the dependency presence is a genuine supply-chain risk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill instructs the agent to invoke a shell command (node <skill_dir>/scripts/render.js ...) but does not declare any permissions or allowed-tools restrictions. That creates an under-scoped skill where code execution capability is implied without explicit policy boundaries, increasing the chance of unintended shell access or misuse if the skill is installed in a broader tool environment.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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/setup.sh (reported line 21)May include surrounding context.

sh
# 3. Download Virgil font (Excalidraw's handwritten font)
if [ ! -f "$FONT_DIR/Virgil.ttf" ]; then
  echo "→ Downloading Virgil font..."
  curl -sL "https://cdn.jsdelivr.net/npm/@excalidraw/excalidraw@0.17.6/dist/excalidraw-assets/Virgil.woff2" \
    -o "$FONT_DIR/Virgil.woff2"
  # Convert woff2 → ttf using fonttools (needed for resvg)
  if command -v python3 &>/dev/null && python3 -c "import fontTools" 2>/dev/null; then

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency uses a caret range instead of an exact version, which allows future installs to resolve to newer package releases than the one originally tested. This increases supply-chain risk because a compromised or breaking upstream patch/minor release could be pulled into the build without explicit review.

Content

Scanner excerpt · scripts/package.json (reported line 7)May include surrounding context.

json
"private": true,
  "type": "module",
  "dependencies": {
    "@resvg/resvg-js": "^2.6.2",
    "jsdom": "^25.0.1",
    "roughjs": "^4.6.6"
  }

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The jsdom dependency is specified with a caret range, so installation may fetch newer compatible releases automatically rather than the exact tested artifact. Because jsdom is a complex parser/runtime-facing library, unexpected upstream changes or a compromised release could increase supply-chain exposure in this skill.

Content

Scanner excerpt · scripts/package.json (reported line 8)May include surrounding context.

json
"type": "module",
  "dependencies": {
    "@resvg/resvg-js": "^2.6.2",
    "jsdom": "^25.0.1",
    "roughjs": "^4.6.6"
  }
}

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The roughjs dependency is also unpinned, allowing semver-compatible updates to be installed automatically. Even though the package is for drawing functionality, unreviewed dependency changes can still introduce malicious code, vulnerable transitive dependencies, or behavioral regressions.

Content

Scanner excerpt · scripts/package.json (reported line 9)May include surrounding context.

json
"dependencies": {
    "@resvg/resvg-js": "^2.6.2",
    "jsdom": "^25.0.1",
    "roughjs": "^4.6.6"
  }
}

Static analysis

No suspicious patterns detected.