XPR Creative

Security checks across malware telemetry and agentic risk

Overview

This skill provides creative delivery tools, but it can publish arbitrary content to public or persistent third-party services without strong consent or visibility controls.

Install only in environments where agents are allowed to send prompts and deliverables to Replicate, Pinata/IPFS, and GitHub. Do not configure the service tokens for workspaces containing secrets, private code, customer data, or unreleased business content unless you also enforce human review before IPFS uploads or public repository creation.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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
Findings (25)

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill advertises networked and environment-sensitive capabilities without declaring permissions or constraints, which reduces transparency and weakens policy enforcement. In practice, this can let an agent invoke external services, fetch remote content, or access runtime configuration in ways users and orchestrators may not expect.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The description frames the skill as generic creative tooling, but the behavior includes public GitHub publication, IPFS uploads, remote URL fetching, PDF generation with embedded remote images, and third-party AI API usage. This mismatch is dangerous because users may authorize a seemingly harmless creative skill without realizing it can exfiltrate data, publish content publicly, or interact with arbitrary external services.

Description-Behavior Mismatch

Medium
Confidence
92% confidence
Finding
The skill description says only 'Creative deliverable tools for AI agents', but the code can publish content to IPFS, create public GitHub repositories, and invoke external AI APIs. That mismatch can mislead operators and users about the privacy and network impact of enabling the skill, increasing the chance of unreviewed data exfiltration or unwanted public publication.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The code reads PINATA_JWT and other credentials from the environment and uses them to publish user content externally. In a generically named creative skill, that broad network/publishing capability is under-scoped and can cause sensitive job data to be transmitted to third parties without sufficiently clear expectation or policy gating.

Vague Triggers

Medium
Confidence
83% confidence
Finding
The invocation guidance is broad and action-oriented, encouraging use of powerful delivery mechanisms without stating when they are appropriate or what safety checks must happen first. In an agent setting, vague triggers increase the chance of overbroad execution, including unsolicited uploads, external content retrieval, or public artifact creation.

Missing User Warnings

High
Confidence
98% confidence
Finding
The skill instructs agents to create public GitHub repositories but does not warn that all uploaded source files become publicly accessible. This creates a direct risk of accidental disclosure of proprietary code, sensitive prompts, credentials, internal documents, or regulated data if the agent packages more than intended.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
JSON and binary deliverables are uploaded to Pinata/IPFS automatically whenever PINATA_JWT is configured, with no user-facing confirmation at transmission time. Because IPFS publication may be persistent and broadly accessible, accidental upload of sensitive or proprietary material can create lasting confidentiality and compliance issues.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The GitHub repository creation path hardcodes `private: false`, so all supplied files are published to a public repository by default. This is dangerous because code, documents, secrets, or proprietary deliverables could be exposed immediately without an explicit warning or privacy choice.

External Transmission

Medium
Category
Data Exfiltration
Content
const jwt = process.env.PINATA_JWT;
  if (!jwt) return null;
  try {
    const resp = await fetch('https://api.pinata.cloud/pinning/pinJSONToIPFS', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${jwt}` },
      body: JSON.stringify({
Confidence
93% confidence
Finding
fetch('https://api.pinata.cloud/pinning/pinJSONToIPFS', { method: 'POST'

External Transmission

Medium
Category
Data Exfiltration
Content
const formData = new FormData();
    formData.append('file', new Blob([new Uint8Array(buffer)], { type: mimeType }), filename);
    formData.append('pinataMetadata', JSON.stringify({ name: filename }));
    const resp = await fetch('https://api.pinata.cloud/pinning/pinFileToIPFS', {
      method: 'POST',
      headers: { Authorization: `Bearer ${jwt}` },
      body: formData,
Confidence
93% confidence
Finding
fetch('https://api.pinata.cloud/pinning/pinFileToIPFS', { method: 'POST'

External Transmission

Medium
Category
Data Exfiltration
Content
'Content-Type': 'application/json', 'X-GitHub-Api-Version': '2022-11-28',
  };
  try {
    const createResp = await fetch('https://api.github.com/user/repos', {
      method: 'POST', headers,
      body: JSON.stringify({ name: repoName, description, private: false, auto_init: true }),
    });
Confidence
97% confidence
Finding
fetch('https://api.github.com/user/repos', { method: 'POST'

External Transmission

Medium
Category
Data Exfiltration
Content
if (!token) return { error: 'REPLICATE_API_TOKEN not set. Add it to .env to enable AI image generation.' };

      try {
        const createResp = await fetch('https://api.replicate.com/v1/models/google/imagen-3/predictions', {
          method: 'POST',
          headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', Prefer: 'wait' },
          body: JSON.stringify({ input: { prompt, aspect_ratio: aspect_ratio || '1:1', output_format: 'png' } }),
Confidence
84% confidence
Finding
fetch('https://api.replicate.com/v1/models/google/imagen-3/predictions', { method: 'POST'

External Transmission

Medium
Category
Data Exfiltration
Content
const jwt = process.env.PINATA_JWT;
  if (!jwt) return null;
  try {
    const resp = await fetch('https://api.pinata.cloud/pinning/pinJSONToIPFS', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${jwt}` },
      body: JSON.stringify({
Confidence
93% confidence
Finding
https://api.pinata.cloud/

External Transmission

Medium
Category
Data Exfiltration
Content
const formData = new FormData();
    formData.append('file', new Blob([new Uint8Array(buffer)], { type: mimeType }), filename);
    formData.append('pinataMetadata', JSON.stringify({ name: filename }));
    const resp = await fetch('https://api.pinata.cloud/pinning/pinFileToIPFS', {
      method: 'POST',
      headers: { Authorization: `Bearer ${jwt}` },
      body: formData,
Confidence
93% confidence
Finding
https://api.pinata.cloud/

External Transmission

Medium
Category
Data Exfiltration
Content
'Content-Type': 'application/json', 'X-GitHub-Api-Version': '2022-11-28',
  };
  try {
    const createResp = await fetch('https://api.github.com/user/repos', {
      method: 'POST', headers,
      body: JSON.stringify({ name: repoName, description, private: false, auto_init: true }),
    });
Confidence
97% confidence
Finding
https://api.github.com/

External Transmission

Medium
Category
Data Exfiltration
Content
if (!createResp.ok) { console.error('[github] Create repo failed:', await createResp.text()); return null; }
    const repo = await createResp.json() as { full_name: string; html_url: string; default_branch: string };

    const refResp = await fetch(`https://api.github.com/repos/${repo.full_name}/git/ref/heads/${repo.default_branch}`, { headers });
    const refData = await refResp.json() as { object: { sha: string } };
    const commitResp = await fetch(`https://api.github.com/repos/${repo.full_name}/git/commits/${refData.object.sha}`, { headers });
    const commitData = await commitResp.json() as { tree: { sha: string } };
Confidence
88% confidence
Finding
https://api.github.com/

External Transmission

Medium
Category
Data Exfiltration
Content
const refResp = await fetch(`https://api.github.com/repos/${repo.full_name}/git/ref/heads/${repo.default_branch}`, { headers });
    const refData = await refResp.json() as { object: { sha: string } };
    const commitResp = await fetch(`https://api.github.com/repos/${repo.full_name}/git/commits/${refData.object.sha}`, { headers });
    const commitData = await commitResp.json() as { tree: { sha: string } };

    const treeItems: Array<{ path: string; mode: string; type: string; sha: string }> = [];
Confidence
88% confidence
Finding
https://api.github.com/

External Transmission

Medium
Category
Data Exfiltration
Content
const treeItems: Array<{ path: string; mode: string; type: string; sha: string }> = [];
    for (const [filePath, fileContent] of Object.entries(files)) {
      const blobResp = await fetch(`https://api.github.com/repos/${repo.full_name}/git/blobs`, {
        method: 'POST', headers, body: JSON.stringify({ content: fileContent, encoding: 'utf-8' }),
      });
      const blobData = await blobResp.json() as { sha: string };
Confidence
99% confidence
Finding
https://api.github.com/

External Transmission

Medium
Category
Data Exfiltration
Content
const blobData = await blobResp.json() as { sha: string };
      treeItems.push({ path: filePath, mode: '100644', type: 'blob', sha: blobData.sha });
    }
    const treeResp = await fetch(`https://api.github.com/repos/${repo.full_name}/git/trees`, {
      method: 'POST', headers, body: JSON.stringify({ base_tree: commitData.tree.sha, tree: treeItems }),
    });
    const treeData = await treeResp.json() as { sha: string };
Confidence
87% confidence
Finding
https://api.github.com/

External Transmission

Medium
Category
Data Exfiltration
Content
});
    const treeData = await treeResp.json() as { sha: string };

    const newCommitResp = await fetch(`https://api.github.com/repos/${repo.full_name}/git/commits`, {
      method: 'POST', headers,
      body: JSON.stringify({ message: `Job #${jobId} deliverable`, tree: treeData.sha, parents: [refData.object.sha] }),
    });
Confidence
90% confidence
Finding
https://api.github.com/

External Transmission

Medium
Category
Data Exfiltration
Content
body: JSON.stringify({ message: `Job #${jobId} deliverable`, tree: treeData.sha, parents: [refData.object.sha] }),
    });
    const newCommitData = await newCommitResp.json() as { sha: string };
    await fetch(`https://api.github.com/repos/${repo.full_name}/git/refs/heads/${repo.default_branch}`, {
      method: 'PATCH', headers, body: JSON.stringify({ sha: newCommitData.sha }),
    });
Confidence
90% confidence
Finding
https://api.github.com/

External Transmission

Medium
Category
Data Exfiltration
Content
if (!token) return { error: 'REPLICATE_API_TOKEN not set. Add it to .env to enable AI image generation.' };

      try {
        const createResp = await fetch('https://api.replicate.com/v1/models/google/imagen-3/predictions', {
          method: 'POST',
          headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', Prefer: 'wait' },
          body: JSON.stringify({ input: { prompt, aspect_ratio: aspect_ratio || '1:1', output_format: 'png' } }),
Confidence
84% confidence
Finding
https://api.replicate.com/

External Transmission

Medium
Category
Data Exfiltration
Content
const deadline = Date.now() + 60000;
          while (result.status !== 'succeeded' && result.status !== 'failed' && Date.now() < deadline) {
            await new Promise(r => setTimeout(r, 1000));
            const pollResp = await fetch(result.urls?.get || `https://api.replicate.com/v1/predictions/${result.id}`, {
              headers: { Authorization: `Bearer ${token}` },
            });
            result = await pollResp.json();
Confidence
80% confidence
Finding
https://api.replicate.com/

External Transmission

Medium
Category
Data Exfiltration
Content
}

        const url = model.includes(':')
          ? 'https://api.replicate.com/v1/predictions'
          : `https://api.replicate.com/v1/models/${model}/predictions`;
        const body: Record<string, any> = { input };
        if (model.includes(':')) body.version = model.split(':')[1];
Confidence
84% confidence
Finding
https://api.replicate.com/

External Transmission

Medium
Category
Data Exfiltration
Content
const deadline = Date.now() + 300000;
        while (result.status !== 'succeeded' && result.status !== 'failed' && Date.now() < deadline) {
          await new Promise(r => setTimeout(r, 3000));
          const pollResp = await fetch(result.urls?.get || `https://api.replicate.com/v1/predictions/${result.id}`, {
            headers: { Authorization: `Bearer ${token}` },
          });
          result = await pollResp.json();
Confidence
80% confidence
Finding
https://api.replicate.com/

VirusTotal

65/65 vendors flagged this skill as clean.

View on VirusTotal