Back to skill

Security audit

volc-vision

Security checks for vulnerabilities and agentic risk

Overview

This image-analysis skill matches its stated purpose, but it needs Review because it can fetch arbitrary URLs or local images and upload the contents to Volcengine ARK without clear limits or consent.

Review before installing. Use this only if you are comfortable sending selected images and prompts to Volcengine ARK, and avoid sensitive screenshots, documents, IDs, internal images, or untrusted/internal URLs until the skill adds explicit consent, URL allowlisting or private-network blocking, content validation, size limits, redirect limits, and timeouts.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
index.js:28
Finding

Unrestricted Server-Side Request Forgery with External Data Relay

Content
View full analysis
{ const protocol = url.startsWith('https') ? https : http; // 处理 base64 图片 if (url.startsWith('data:')) { const base64Data = url.replace(/^data:image\/\w+;base64,/, ''); resolve(Buffer.from(base64Data, 'base64')); return; } // 处理文件路径 if (!url.startsWith('http://') && !url.startsWith('https://')) { const filePath = path.isAbsolute(url) ? url : path.join(process.cwd(), url); if (fs.existsSync(filePath)) { resolve(fs.readFileSync(filePath)); return; } reject(new Error(`File not found: ${filePath}`)); return; } protocol.get(url, (res) => { if (res.statusCode === 301 || res.statusCode === 302) { downloadImage(res.headers.location).then(resolve).catch(reject); return; } const chunks = []; res.on('data', (chunk) => chunks.push(chunk)); res.on('end', () => resolve(Buffer.concat(chunks))); res.on('error', reject); }).on('error', reject); }); } ``` Retrieved bytes are subsequently encoded and sent to the external ARK API: ```js const imageBuffer = await downloadImage(imagePath); const base64Image = encodeImage(imageBuffer); const imageUrl = `data:${mimeType};base64,${base64Image}`; const requestBody = { model: MODEL, messages: [{ role: 'user', content: [ { type: 'text', text: prompt }, { type: 'image_url', image_url: { url: imageUrl } } ] }], max_tokens: 4096 }; ``` ### Technical Analysis The command-line-controlled `imagePath` may be an arbitrary HTTP or HTTPS URL. The implementation sends a request to that U ...[truncated 2484 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
index.js:49
Finding

Unbounded Network Response Buffering Enables Denial of Service

Content
View full analysis
{ if (res.statusCode === 301 || res.statusCode === 302) { downloadImage(res.headers.location).then(resolve).catch(reject); return; } const chunks = []; res.on('data', (chunk) => chunks.push(chunk)); res.on('end', () => resolve(Buffer.concat(chunks))); res.on('error', reject); }).on('error', reject); ``` The external API response is also buffered without a size limit: ```js const req = https.request(options, (res) => { const chunks = []; res.on('data', (chunk) => chunks.push(chunk)); res.on('end', () => { const response = Buffer.concat(chunks).toString(); try { const json = JSON.parse(response); if (json.error) { reject(new Error(json.error.message)); } else if (json.choices && json.choices[0]) { resolve(json.choices[0].message.content); } else { reject(new Error(`Unexpected response: ${response}`)); } } catch (e) { reject(new Error(`Failed to parse response: ${response}`)); } }); }); ``` ### Technical Analysis Remote image responses are accumulated in an array and concatenated only after the server ends the response. No maximum byte count, `Content-Length` limit, connection timeout, response timeout, or total operation deadline is applied. A server can therefore return an extremely large response or transmit data indefinitely at a low rate. After download, the entire buffer is converted to base64. Base64 representation increases the data size, and JSON serialization creates further in-memory copies before the API request is sent. Memory consumption can consequently be substantially greater than the original response size. Redirects are recursively followe ...[truncated 1561 chars]
Remediation
View remediation
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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation says the skill uses the Volcano Engine ARK API for image understanding, but it does not clearly warn that local images, URLs, or base64 image contents may be transmitted to a third-party external service. This is a significant privacy and data-governance risk, especially for sensitive screenshots, documents, IDs, or internal images that a user may assume are processed locally.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill declares environment-variable requirements and demonstrates executable Node.js usage, but it does not define an explicit tool scope such as permissions or allowed-tools. That creates ambiguity about what the agent may invoke and access, increasing the chance of over-broad execution or unintended secret exposure when the skill is selected.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger examples include very broad, everyday phrases like '看看这张图' and '描述一下', which can match many normal conversations and cause the skill to be invoked unexpectedly. In this skill, accidental invocation is more sensitive because it may send user-provided images to an external vision service without a clear confirmation step.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill reads image data from a local file, URL, or data URI and sends the full image plus user prompt to an external ARK vision API, but the CLI behavior provides no explicit disclosure or consent step before transmitting potentially sensitive content off-host. In a vision-analysis skill this network transfer is expected functionality, but it still creates a real privacy and data-handling risk if users provide private images, internal screenshots, or confidential documents without realizing they are uploaded to a third party.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The example usage and default prompt are hard-coded in Chinese, which imposes a specific language choice on users without offering an alternative or opt-in. This is a natural-language policy concern because the skill does not provide any language selection mechanism or justification for the locale restriction.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The applicability section describes broad scenarios for 'understanding' or 'describing' images but does not clearly define when the skill should or should not be selected. This can lead to non-deterministic routing and mistaken use of the skill in contexts where external image processing is unnecessary or privacy-sensitive.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The script reads an API credential from the ARK_API_KEY environment variable to authenticate outbound requests. Although missing-key handling exists, there is no comment, docstring, or user-facing disclosure explaining that the skill depends on and uses a credential for external service access.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.