Back to skill

Security audit

vinci-tarot

Security checks for vulnerabilities and agentic risk

Overview

The tarot skill is mostly coherent, but its image renderer can fetch arbitrary URLs or read local image paths from input JSON, so it should be reviewed before installation.

Install this only if you are comfortable with a tarot skill that runs local Python and may make network requests for card art. Use a vetted local --images-dir, avoid processing user-supplied or edited reading JSON, run it in a sandbox with restricted filesystem and network access, and prefer pinned local npm tooling if you ever re-export card data.

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
tarot_skill/scripts/generate_spread_image.py:89
Finding

Unrestricted Image Source Handling Enables SSRF and Local File Disclosure

Content
View full analysis
bytes: if "://" in url and not url.startswith("file:"): req = urllib.request.Request(url, headers=BROWSER_HEADERS) with urllib.request.urlopen(req, timeout=TIMEOUT) as r: return r.read() path = url.replace("file:", "").strip() return Path(path).read_bytes() ``` The attacker-controlled value reaches this function through the reading JSON: ```python raw = Path(args.input).read_text(encoding="utf-8") if args.input else sys.stdin.read() reading = json.loads(raw) if not reading.get("ok") or not reading.get("spreadType") or not reading.get("spread"): print("Invalid reading: need ok=true, spreadType, and spread array.", file=sys.stderr) sys.exit(1) spread_type = reading["spreadType"] layout = SPREAD_LAYOUTS.get(spread_type) if not layout or len(layout["slots"]) != len(reading["spread"]): print( f'Layout for "{spread_type}" has {len(layout["slots"]) if layout else 0} slots, ' f"but spread has {len(reading['spread'])} cards.", file=sys.stderr, ) sys.exit(1) cw = layout["canvas_width"] ch = layout["canvas_height"] bg_hex = layout["background_color"].lstrip("#") bg = tuple(int(bg_hex[i : i + 2], 16) for i in (0, 2, 4)) base = Image.new("RGB", (cw, ch), bg) images_dir = Path(args.images_dir) if args.images_dir else None if images_dir is None: default_cards = _ROOT / "cards" _ensure_card_images_once(default_cards) if default_cards.is_dir(): images_dir = default_cards for i, pos in enumerate(reading["spread"]): slot = layout["slots"][i] card_id = pos["card"]["id"] fallback_url = pos["card"].get("image") or get_card_image_url(card_id) url = get_card_url(card_i ...[truncated 3346 chars]
Remediation
View remediation
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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (28)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill’s actual behavior includes image rendering, JSON/file I/O, subprocess-style command execution, and possible network downloads, which is materially broader than a simple conversational tarot reader. This hidden operational breadth increases attack surface and can lead to agents executing code or handling files without users understanding that capability.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill’s actual behavior includes image rendering, JSON/file I/O, subprocess-style command execution, and possible network downloads, which is materially broader than a simple conversational tarot reader. This hidden operational breadth increases attack surface and can lead to agents executing code or handling files without users understanding that capability.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill’s actual behavior includes image rendering, JSON/file I/O, subprocess-style command execution, and possible network downloads, which is materially broader than a simple conversational tarot reader. This hidden operational breadth increases attack surface and can lead to agents executing code or handling files without users understanding that capability.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
rt-cards` or `npx tsx scripts/export_cards_from_tarot_game.ts`; Python deps in `requirements.txt` (Pillow).

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · tarot_skill/scripts/generate_spread_image.py (reported line 51)May include surrounding context.

python
return
    print("First run: downloading card images to", cards_dir, "...", file=sys.stderr)
    cards_dir.mkdir(parents=True, exist_ok=True)
    env = {**os.environ, "PYTHONPATH": str(_ROOT)}
    r = subprocess.run(
        [sys.executable, "-m", "tarot_skill.scripts.download_card_images", "--output-dir", str(cards_dir)],
        cwd=str(_ROOT),

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The install guide instructs users to run npx tsx ... without pinning a specific package version. npx may resolve and execute whatever version is currently available, which can introduce supply-chain risk if a malicious or compromised release is published or if dependency resolution changes over time. In this skill, the command is only for optional card-data export, which lowers exposure somewhat, but it still results in execution of unpinned code on the user's machine.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The README instructs automatic network download of 78 card images on first run, even though remote fetching is not essential to the core tarot-reading logic. This expands the skill's attack surface by introducing external network dependency, possible tracking, and supply-chain or content tampering risk during ordinary use.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill advertises executable capabilities via Python, image generation, filesystem interaction, and possible network fetching, but does not declare any explicit tool/permission scope. That creates an unnecessary trust gap where an agent may grant broader shell, file, or network access than the tarot-reading function actually requires. In this context, the absence of scoped permissions is more dangerous because the instructions explicitly tell the agent to run code and handle files.

Content

No source excerpt is available for this finding.

Unrestricted Tool Access

Medium
Category
Excessive Agency
Confidence
89% confidence
Finding

The skill explicitly instructs the agent to 'run any code', call Python functionality, save JSON, and execute an image-generation script, but it does not constrain what tools or commands are permissible. In an agent environment, that pattern can normalize arbitrary code execution for a simple content skill and widen the path to abuse if the implementation or environment is tampered with.

Content

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

md
- Keep it brief; the goal is to move from distraction to the question and the present, then draw.

4. **Announce the draw, then run it**  
   - **Send a short message to the user that you are drawing now** (e.g. “I’ll draw the cards now.” / “Drawing for you…”) **before** you call `perform_reading` or run any code.  
   - **Only after** that message is sent, call `perform_reading`, save the result as JSON, run the spread-image script, and **send the image** to the user.  
   - Correct order: say you’re drawing → (then) run reading + generate image → send image → (then) write interpretation.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill directs the agent to run a Python image-generation command that may fetch remote card images, creating unnecessary network and code-execution exposure for a nonessential presentation feature. Remote asset retrieval can leak environment metadata, consume untrusted content, or expand the blast radius if the script or fetched resources are compromised.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
91% confidence
Finding

The use of npx tsx without a pinned version introduces supply-chain risk because package resolution may pull a different or malicious version at execution time. Since the skill also instructs running external tooling from a sibling project, this increases the chance of executing unreviewed code in the local environment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This JSON file provides nearly all descriptive content and meanings only under the "zh" locale, while English is limited to card names. That effectively hard-codes a Chinese-language experience without any opt-in, language fallback, or documented region-specific justification.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The meaning selection hard-codes en whenever English text exists, otherwise falling back to Chinese. This imposes a language preference on users without any visible opt-in, choice mechanism, or documented locale constraint, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The card interpretation path uses the same hard-coded language selection pattern, preferring English whenever present. This is a natural-language policy issue because the skill does not let the user choose their language or clearly document a justified locale restriction.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The script automatically downloads external card images on first run, which introduces undeclared network behavior and causes code execution flow to depend on remote resources. In a skill described primarily as tarot reading and interpretation, this broadens the trust boundary and can leak network metadata or create supply-chain and availability risks.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · tarot_skill/scripts/generate_spread_image.py (reported line 52)May include surrounding context.

python
print("First run: downloading card images to", cards_dir, "...", file=sys.stderr)
    cards_dir.mkdir(parents=True, exist_ok=True)
    env = {**os.environ, "PYTHONPATH": str(_ROOT)}
    r = subprocess.run(
        [sys.executable, "-m", "tarot_skill.scripts.download_card_images", "--output-dir", str(cards_dir)],
        cwd=str(_ROOT),
        env=env,

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The use of browser-mimicking headers to retrieve remote images is a red flag because it is specifically designed to bypass server-side access restrictions such as 403 responses. That behavior is unnecessary for a simple tarot-reading skill and increases concern that the script is intentionally evading normal resource-access controls.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script fetches card images from runtime-provided URLs taken from input data or fallback sources, allowing untrusted JSON to trigger outbound requests or local file reads. This creates SSRF-style behavior and unexpected file access because any value containing a scheme or local path is passed to the fetch routine without validation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README says the script will try to download images on first run, but does not present a clear up-front warning that executing the feature causes network activity. Silent or unexpected outbound requests are risky in agent environments because they may violate user expectations, leak environment metadata, or bypass policies for offline-safe skills.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The skill's purpose is to act as a professional tarot reader, but the documentation instructs the agent/operator to run npm/npx export commands from another project ("tarot_game") and arrange repository layout accordingly. That external project interaction is not part of the user-facing tarot-reading purpose and adds an unjustified capability/dependency surface.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: esbuild==0.27.3 — 1 advisory(ies): GHSA-g7r4-m6w7-qqqr (esbuild allows arbitrary file read when running the development server on Window)

Low
Category
Supply Chain
Confidence
93% confidence
Finding

The lockfile pins esbuild to 0.27.3, and that version is associated with GHSA-g7r4-m6w7-qqqr. This advisory affects esbuild's development server on Windows by permitting arbitrary file read, so the issue is real even though it appears only in a dev dependency and requires a specific feature and platform to be in use.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

The devDependency uses a caret range (^4.19.2), which allows newer minor/patch versions to be installed over time. This can introduce supply-chain risk and reduce build reproducibility if an upstream release is compromised or contains breaking behavior, though the dependency appears limited to a development/export script rather than runtime execution in the skill itself.

Content

Scanner excerpt · package.json (reported line 12)May include surrounding context.

json
"keywords": ["tarot", "divination", "skill", "openclaw", "clawhub"],
  "license": "MIT",
  "devDependencies": {
    "tsx": "^4.19.2"
  }
}

Static analysis

No suspicious patterns detected.