Back to skill

Security audit

tandian-image-skills

Security checks for vulnerabilities and agentic risk

Overview

The skill performs the advertised cloud image-editing workflow, but it gives user-controlled paths and URLs enough reach to upload arbitrary readable files, fetch internal URLs, or overwrite writable files.

Review before installing. Use only non-sensitive images you are authorized to send to Replicate/SeedVR2, avoid private business interiors or identifiable people without consent, do not pass arbitrary local paths or internal URLs, and run it in a sandbox limited to dedicated input and output folders.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (3)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/replicate_cli.js:91
Finding

Unrestricted Local File Read and Upload to Replicate

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/replicate_cli.js:73
Finding

Server-Side Request Forgery Through Unrestricted Image URLs

Content
View full analysis
name).join(', ')}`) } return { url: selected, label: `preset:${key}`, source: 'preset' } } const [randomKey, randomUrl] = pickRandomItem(presetEntries) return { url: randomUrl, label: `preset:${randomKey}`, source: 'preset-random' } } async function fileOrUrlToDataUrl(input) { if (!input) throw new Error('no input') try { if (isRemoteUrl(input)) { const resp = await fetch(input) if (!resp.ok) throw new Error(`Failed to fetch template: ${resp.status}`) const ab = await resp.arrayBuffer() const b64 = Buffer.from(ab).toString('base64') const mime = resp.headers.get('content-type') || 'image/png' return `data:${mime};base64,${b64}` } else { const abs = path.resolve(process.cwd(), input) const buf = await fs.readFile(abs) const mime = getMimeType(abs) return `data:${mime};base64,${buf.toString('base64')}` } } catch (err) { throw err } } ``` Both scene and template ...[truncated 2264 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/replicate_cli.js:174
Finding

Arbitrary File Overwrite Through Unrestricted Output Path

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

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill clearly relies on environment secrets (REPLICATE_API_TOKEN) and network access to remote services and URLs, yet it declares no explicit tool scope or permission boundaries. This can cause the agent runtime to grant broader-than-necessary capabilities by default, making secret access and outbound requests insufficiently constrained in a workflow that accepts user-influenced URLs and file paths.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill instructs users to send local scene images and optional model image URLs to third-party services (Replicate and SeedVR2) and to write generated outputs locally, but it provides no explicit privacy notice, consent requirement, or data-handling warning. Because the content involves real-world store scenes and person images, users may unknowingly transmit sensitive personal, commercial, or copyrighted material to external processors.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

The hard-coded Replicate API endpoint confirms that image data is intentionally sent to an external service. In an image-processing skill focused on local-life/store photography and model compositing, this is particularly sensitive because photos may contain biometric data, identifiable interiors, branding, or customer information.

Content

Scanner excerpt · scripts/replicate_cli.js (reported line 125)May include surrounding context.

js
quality: 'low',
  }

  const res = await fetch('https://api.replicate.com/v1/models/openai/gpt-image-2/predictions', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
    body: JSON.stringify({ input }),

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

The hard-coded Replicate API endpoint confirms that image data is intentionally sent to an external service. In an image-processing skill focused on local-life/store photography and model compositing, this is particularly sensitive because photos may contain biometric data, identifiable interiors, branding, or customer information.

Content

Scanner excerpt · scripts/replicate_cli.js (reported line 125)May include surrounding context.

js
quality: 'low',
  }

  const res = await fetch('https://api.replicate.com/v1/models/openai/gpt-image-2/predictions', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
    body: JSON.stringify({ input }),

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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/replicate_cli.js (reported line 138)May include surrounding context.

js
}

async function getPrediction(id, token) {
  const res = await fetch(`https://api.replicate.com/v1/predictions/${id}`, {
    headers: { Authorization: `Bearer ${token}` },
  })
  if (!res.ok) {

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

The endpoint usage at this line represents an external processing step for upscaling and therefore a genuine data-transfer risk in this skill. Because the skill defaults to using remote template URLs and accepts remote/user-supplied inputs, the overall workflow increases the likelihood that personal or copyrighted imagery is transmitted to third parties without strong provenance or privacy controls.

Content

Scanner excerpt · scripts/replicate_cli.js (reported line 149)May include surrounding context.

js
}

async function createUpscalePrediction(token, mediaUrl) {
  const res = await fetch('https://api.replicate.com/v1/predictions', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
    body: JSON.stringify({

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

The endpoint usage at this line represents an external processing step for upscaling and therefore a genuine data-transfer risk in this skill. Because the skill defaults to using remote template URLs and accepts remote/user-supplied inputs, the overall workflow increases the likelihood that personal or copyrighted imagery is transmitted to third parties without strong provenance or privacy controls.

Content

Scanner excerpt · scripts/replicate_cli.js (reported line 149)May include surrounding context.

js
}

async function createUpscalePrediction(token, mediaUrl) {
  const res = await fetch('https://api.replicate.com/v1/predictions', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
    body: JSON.stringify({

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The embedded default prompt is entirely in Chinese and imposes a specific language/locale choice by default. There is no indication that the skill is region-specific, nor any option disclosure that language can be chosen by the user before this default is applied.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script defines a default prompt entirely in Chinese, which implicitly forces a specific language/locale when the user does not supply their own prompt. The file does not present this as an opt-in or document a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The script automatically chooses an output file path under the skill directory and passes it to the downstream CLI for writing. While it prints the output path later, there is no explicit warning, confirmation, or comment/docstring disclosing that the command will create a new file on disk.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access, suspicious.potential_exfiltration

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/replicate_cli.js:192

File read combined with network send (possible exfiltration).

Warn
Code
suspicious.potential_exfiltration
Location
scripts/replicate_cli.js:103