Back to skill

Security audit

Vintage Poster Generator

Security checks for vulnerabilities and agentic risk

Overview

The skill does the advertised image-generation job, but it asks for an API token in a risky way and sends prompts and the token to an external service with incomplete disclosure in the main skill file.

Review before installing. Use a limited-scope token if possible, avoid putting real tokens directly in shell history, and assume prompts and reference IDs are sent to the external Neta/TalesOfAI service. Prefer an immutable or pinned install source when available.

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
vintagepostergenerator.js:4
Finding

API Token Exposure Through Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: vintagepostergenerator.js:4-24; insecure usage is documented in SKILL.md:14-21 and README.md:23-33
Vulnerability Type: Sensitive credential exposure through process arguments and shell history
Risk Level: Medium

Vulnerable Code

javascript
const args = process.argv.slice(2);

// Parse CLI arguments
let prompt = null;
let size = 'portrait';
let tokenFlag = null;
let refUuid = null;

for (let i = 0; i < args.length; i++) {
  if (args[i] === '--token' && args[i + 1]) {
    tokenFlag = args[++i];
  } else if (args[i] === '--size' && args[i + 1]) {
    size = args[++i];
  } else if (args[i] === '--ref' && args[i + 1]) {
    refUuid = args[++i];
  } else if (!args[i].startsWith('--') && prompt === null) {
    prompt = args[i];
  }
}

const TOKEN = tokenFlag;

The documentation explicitly instructs users to place the secret on the command line:

bash
node vintagepostergenerator.js "your prompt" --token YOUR_TOKEN

Technical Analysis

The program obtains the Neta API token directly from process.argv. Command-line arguments are not an appropriate secret transport mechanism because the complete invocation may be retained in shell history, process-monitoring logs, terminal telemetry, debugging output, or operating-system process metadata.

Exposure through process listings depends on the operating system and its process-isolation configuration. Nevertheless, shell-history retention alone creates a persistent plaintext copy in common environments. The implementation provides no safer alternative, such as a protected environment variable, standard-input prompt, or credential store.

The token is subsequently placed in the x-token request header and therefore functions as an authentication credential for the remote service.

Attack Path

  1. A user follows the documented example and invok ...[truncated 1258 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove --token as the recommended credential transport mechanism.
  2. Read the token from a dedicated environment variable, such as NETA_API_TOKEN, and clearly document how to set it without placing it directly in shell history.
  3. For interactive use, accept the token through a hidden standard-input prompt that disables terminal echo.
  4. Where supported, integrate with an operating-system credential store or secret manager.
  5. Retain command-line token support only if backward compatibility is essential, and emit a prominent deprecation warning explaining the exposure risk.
  6. Avoid logging the token or including it in error messages. Ensure request-debugging and telemetry systems redact the x-token header.
  7. Advise users who previously followed the documented command to remove affected history entries and rotate potentially exposed tokens.

A safer non-interactive pattern would be:

javascript
const TOKEN = process.env.NETA_API_TOKEN;

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

Deployment documentation should recommend injecting this variable through a protected secret-management mechanism rather than committing it to a file.

T08 · Insecure Dependencies

Warning
Location
README.md:13
Finding

Unpinned Third-Party Installation Command Creates Supply-Chain Exposure

Content
View full analysis

Vulnerability Details

File Location: README.md:13-17; the same unpinned installation form appears in SKILL.md:32-34
Vulnerability Type: Installation of mutable third-party content without version or integrity pinning
Risk Level: Medium

Vulnerable Code

markdown
**Via npx skills:**
```bash
npx skills add blammectrappora/vintage-poster-generator
text

The equivalent instruction in `SKILL.md` is:

```bash
npx skills add blammectrappora/vintage-poster-generator

Technical Analysis

The documented installation command invokes an npx-resolved tool and requests skill content by a mutable owner/project identifier. It does not pin the installer version, the skill release, an immutable source commit, or an integrity digest.

Consequently, the bytes installed by this command can change after the currently audited files have been reviewed. A compromise of the relevant package distribution channel, publisher account, source account, or mutable release could cause future users to retrieve content different from the audited version.

No malicious dependency or lifecycle script is present in the audited package.json; this finding concerns the unsafe, mutable installation procedure rather than proof that the current package contains a malicious dependency.

Attack Path

  1. An attacker compromises the publisher account, package-distribution channel, mutable project source, or another component used to resolve the unpinned installer or skill identifier.
  2. The attacker publishes a modified installer release or replaces the skill content with a malicious version.
  3. A victim follows the documented npx skills add blammectrappora/vintage-poster-generator command.
  4. The package manager resolves the current mutable version rather than a previously audited immutable artifact.
  5. Attacker-controlled content is downloaded and installed.
  6. If the compromised installer or skill executes code ...[truncated 862 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin the skills installer to a specific audited version instead of allowing npx to resolve the latest mutable release.
  2. Pin the skill itself to an immutable version, release artifact, or full source commit hash where the installation system supports it.
  3. Publish cryptographic checksums or signatures for release artifacts and document a verification step before installation.
  4. Use package-manager lockfiles and integrity metadata where applicable.
  5. Protect publisher and source-control accounts with multi-factor authentication, restricted release permissions, and auditable release workflows.
  6. Avoid recommending elevated execution. Explicitly state that installation must not be run with sudo or an administrator account.
  7. Use reproducible releases and compare published artifacts against the reviewed source.
  8. Document the exact version and digest that correspond to this audit so users can retrieve the same artifact rather than a future mutable version.
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 (12)

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.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The README instructs users to supply a Neta API token and prompt content to an external service but does not clearly warn that both prompts and credentials are being transmitted to a third party. This can lead users to unknowingly send sensitive text, proprietary data, or secrets off-platform, increasing confidentiality and compliance risk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill declares only tools: Bash and does not constrain network-capable behavior with explicit permissions or allowed-tools, even though the workflow clearly sends prompts and tokens to an external API. This creates an authorization and transparency gap: an agent may execute networked code without the manifest clearly disclosing or limiting that capability.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The markdown explains how to pass a Neta API token and submit prompts, but it does not clearly warn that both prompt content and token-authenticated requests are transmitted to an external image-generation service. This omission reduces informed consent and increases the risk of users inadvertently sharing sensitive prompts, proprietary text, or credentials in a third-party workflow.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The invocation guidance says to use the skill when someone asks to generate or create vintage poster generator images, which is broad enough to match generic image-generation requests. Overbroad routing can cause the agent to invoke this external API skill unexpectedly, sending user prompts and possibly tokens to a third party when a narrower or local option would have been more appropriate.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
87% confidence
Finding

The install command uses npx skills add blammectrappora/vintage-poster-generator without a pinned version, so future installs may resolve to changed content. This weakens supply-chain integrity because users can receive unreviewed updates or a compromised package revision without noticing.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file header claims the skill uses the Neta API, but the implementation actually sends requests to api.talesofai.com. This mismatch is dangerous because users may provide prompts and authentication tokens under false assumptions about the receiving service, undermining informed consent, reviewability, and supply-chain trust.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

The hardcoded https://api.talesofai.com endpoint represents outbound data flow to a third-party service. In this skill, that becomes more dangerous because the endpoint conflicts with the stated Neta branding, creating a deceptive data-handling path for user prompts and credentials.

Content

Scanner excerpt · vintagepostergenerator.js (reported line 69)May include surrounding context.

js
};
  }

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

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

The hardcoded https://api.talesofai.com endpoint represents outbound data flow to a third-party service. In this skill, that becomes more dangerous because the endpoint conflicts with the stated Neta branding, creating a deceptive data-handling path for user prompts and credentials.

Content

Scanner excerpt · vintagepostergenerator.js (reported line 69)May include surrounding context.

js
};
  }

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

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The manifest advertises a Neta AI image-generation skill, but the code transmits user prompts and the supplied token to a different external service. In the context of a third-party skill, this is more dangerous than a normal network call because it can misdirect secrets and user data to an undisclosed provider, defeating user expectations and platform review controls.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

The polling request contacts the same external service to retrieve task results, extending the trust boundary to an undisclosed third party. While this call is less sensitive than the creation request, it still confirms ongoing data exchange with a provider different from the one users were told to expect.

Content

Scanner excerpt · vintagepostergenerator.js (reported line 99)May include surrounding context.

js
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    await new Promise(r => setTimeout(r, intervalMs));

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

Static analysis

No suspicious patterns detected.