Back to skill

Security audit

Tarot Card Art Generator

Security checks for vulnerabilities and agentic risk

Overview

This skill is a small tarot image-generation wrapper with expected network and token use, but users should notice its token-handling and install hardening gaps.

Install only if you are comfortable sending prompts and your Neta token to the Neta/TalesOfAI image API. Prefer a pinned install source, avoid placing real tokens directly in shell history where possible, and rotate the token if it has already been pasted into shared logs or transcripts.

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
tarotcardartgenerator.js:10
Finding

API Token Exposed Through Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: tarotcardartgenerator.js:10-11; documented usage in SKILL.md:17-19 and README.md:23-27
Vulnerability Type: Sensitive credential exposure through process arguments
Risk Level: Medium

Vulnerable Code

javascript
if (args[i] === "--token" && i + 1 < args.length) {
  tokenFlag = args[++i];
}

The documentation explicitly instructs users to provide the credential on the command line:

bash
node tarotcardartgenerator.js "your description here" --token YOUR_TOKEN

Technical Analysis

The program accepts the Neta API token exclusively through the --token command-line option. Command-line arguments are not an appropriate secret-transport mechanism because they may be exposed through:

  • Shell history files.
  • Process inspection utilities while the process is running.
  • Process-monitoring and endpoint-management software.
  • CI/CD command logs and diagnostic output.
  • Terminal session recording or copied command transcripts.

The captured value is later assigned to the x-token HTTP request header. The token is not intentionally printed by the application, but accepting it through process.argv exposes it before the request is made.

Attack Path

  1. A user follows the documented usage instructions and runs the generator with --token YOUR_TOKEN.
  2. The shell records the complete command in its history, or a process-monitoring mechanism captures the process arguments.
  3. An attacker with access to the user's shell history, process metadata, CI logs, or terminal records extracts the token.
  4. The attacker submits requests to the Neta API using the stolen x-token credential.
  5. The attacker retains access until the token expires or is revoked.

This attack requires local access, access to collected operational logs, or another capability that exposes process arguments.

Impact Assessment

Successful exploitation ...[truncated 452 chars]

Remediation
View remediation

Remediation Suggestions

  • Read the token from a protected environment variable, such as NETA_API_TOKEN, rather than requiring it as a command-line argument.
  • Optionally support secure interactive input from stdin with terminal echo disabled.
  • Remove --token YOUR_TOKEN from all usage examples and document secure environment-variable setup instead.
  • If backward compatibility requires retaining --token, display a deprecation warning and clearly explain the process-list and shell-history risk.
  • Ensure errors, debug output, telemetry, and request logging redact the token.
  • Recommend immediate token rotation if a token has already appeared in shell history or CI/CD logs.

Example hardened token loading:

javascript
const TOKEN = process.env.NETA_API_TOKEN;

if (!TOKEN) {
  console.error("Token required. Set the NETA_API_TOKEN environment variable.");
  process.exit(1);
}

Recommended invocation:

bash
NETA_API_TOKEN='token-value' node tarotcardartgenerator.js "your description"

For shared systems, a protected secret manager or non-echoing stdin input is preferable even to an inline environment-variable assignment.

T08 · Insecure Dependencies

Warning
Location
README.md:7
Finding

Unpinned Remote Installation Through npx

Content
View full analysis

Vulnerability Details

File Location: README.md:7-11; equivalent instruction in SKILL.md:32-34
Vulnerability Type: Mutable and unpinned supply-chain installation
Risk Level: Medium

Vulnerable Code

bash
npx skills add omactiengartelle/tarot-card-art-generator

Technical Analysis

The documented installation command invokes the skills package through npx without specifying an audited version. It also identifies the skill by a mutable repository-style name rather than an immutable release, commit identifier, or integrity-verified artifact.

Depending on the local npm configuration and cache state, npx can download and execute a package resolved from the configured npm registry. Because no version is pinned, the code executed by the installation command can differ from the version evaluated during this audit. The installed skill content may likewise change if the referenced upstream source is updated.

This creates a supply-chain trust gap: registry compromise, publisher-account compromise, malicious future releases, or upstream repository compromise could replace the effective installation payload without changing the command shown in the documentation.

No malicious dependency or remote payload was found in the audited project snapshot. The risk arises from the unsafe, mutable installation procedure.

Attack Path

  1. An attacker compromises the package publisher, npm registry resolution path, or upstream skill source.
  2. The attacker publishes or substitutes a malicious version under the same mutable package or skill identifier.
  3. A user follows the documented npx skills add ... command.
  4. npx resolves and executes the currently available unpinned CLI package.
  5. The CLI retrieves or installs the currently available skill content.
  6. Malicious installer or skill code executes with the permissions of the user running the command.

Exploitation depends on compromise or malicio ...[truncated 900 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin the skills CLI to a specific audited version, for example npx skills@X.Y.Z, rather than resolving the latest available release.
  • Pin the installed skill to an immutable version, release tag, or commit hash supported by the installation tool.
  • Publish and verify cryptographic integrity hashes or signed release attestations for distributed artifacts.
  • Use a lockfile-backed installation process where possible.
  • Configure npm to use an explicitly trusted registry and review package provenance before execution.
  • Avoid running installation commands with elevated privileges.
  • Consider installing and inspecting the CLI package before execution rather than allowing npx to fetch and immediately run mutable code.
  • Update both README.md and SKILL.md so all installation examples use the same pinned and integrity-verifiable source.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (8)

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.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill declares only tools: Bash and does not constrain tool/network scope, even though the workflow clearly depends on outbound network access to the Neta API. Without explicit permissions or allowed-tools, an agent may invoke this skill with broader-than-necessary capabilities, increasing the chance of unintended network use or command execution beyond the expected image-generation task.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The invocation guidance, 'Use when someone asks to generate or create tarot card art generator images,' is overly broad and ambiguous. Over-broad trigger conditions can cause an agent to invoke the skill unnecessarily, which increases exposure to the skill's Bash execution and network behavior, including accidental token use or unintended external requests.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding

Using npx skills add omactiengartelle/tarot-card-art-generator without a pinned version allows installation of whatever package version is current at execution time. If the upstream package is updated maliciously, compromised, or simply changed incompatibly, users may fetch and run unreviewed code, creating a supply-chain risk.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

The presence of a hardcoded external API domain indicates deliberate outbound network communication to a third party. External transmission is expected for an image-generation skill, but here it remains security-relevant because the destination conflicts with the stated vendor, increasing the risk of deceptive exfiltration of prompts and credentials.

Content

Scanner excerpt · tarotcardartgenerator.js (reported line 71)May include surrounding context.

js
async function main() {
  console.error(`Generating tarot card art (${size} ${dimensions.width}x${dimensions.height})...`);

  const createRes = await fetch("https://api.talesofai.com/v3/make_image", {
    method: "POST",
    headers,
    body: JSON.stringify(body),

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

The presence of a hardcoded external API domain indicates deliberate outbound network communication to a third party. External transmission is expected for an image-generation skill, but here it remains security-relevant because the destination conflicts with the stated vendor, increasing the risk of deceptive exfiltration of prompts and credentials.

Content

Scanner excerpt · tarotcardartgenerator.js (reported line 71)May include surrounding context.

js
async function main() {
  console.error(`Generating tarot card art (${size} ${dimensions.width}x${dimensions.height})...`);

  const createRes = await fetch("https://api.talesofai.com/v3/make_image", {
    method: "POST",
    headers,
    body: JSON.stringify(body),

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill metadata and CLI messaging claim it uses the Neta AI API, but the code actually sends the user's prompt and token to TalesOfAI endpoints. This is dangerous because it misleads users about the receiving third party, breaking informed consent and potentially exposing credentials and content to an unexpected external service.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The polling request continues sending the authentication header to the same undisclosed third-party domain during task status checks. Repeated authenticated calls increase exposure of credentials and user activity metadata, especially when the real service differs from what the user was told.

Content

Scanner excerpt · tarotcardartgenerator.js (reported line 100)May include surrounding context.

js
await new Promise((r) => setTimeout(r, 2000));

    const pollRes = await fetch(
      `https://api.talesofai.com/v1/artifact/task/${taskUuid}`,
      { headers }
    );

Static analysis

No suspicious patterns detected.