Back to skill

Security audit

多单品搭配融图 Image Fusion

Security checks for vulnerabilities and agentic risk

Overview

The skill largely matches its advertised image-fusion purpose, but its helper script can fetch arbitrary image URLs and upload the fetched content to external providers without enough safeguards.

Install only if you are comfortable sending prompts and source images to the selected generation provider. Avoid using untrusted image URLs with this skill; prefer local vetted image files, and run it in an environment without access to internal services or unrelated credentials.

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

Error
Location
scripts/lib/providers.mjs:24
Finding
Unrestricted Remote Image Fetching Enables SSRF and Data Exfiltration<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lib/providers.mjs:24-43`, with provider call sites at `scripts/lib/providers.mjs:147-151` and `scripts/lib/providers.mjs:201-209` **Vulnerability Type**: Server-Side Request Forgery and unintended external disclosure **Risk Level**: High ### Vulnerable Code ```js const isUrl = (s) => /^https?:\/\//i.test(s) const MIME = { '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.png': 'image/png', '.webp': 'image/webp', '.gif': 'image/gif', } const mimeOf = (p) => MIME[path.extname(p).toLowerCase()] || 'image/jpeg' async function asBase64(p) { if (isUrl(p)) { const r = await fetch(p) if (!r.ok) throw new Error(`拉取参考图失败 ${r.status}: ${p}`) return Buffer.from(await r.arrayBuffer()).toString('base64') } return (await readFile(p)).toString('base64') } const asDataUri = async (p) => isUrl(p) ? p : `data:${mimeOf(p)};base64,${await asBase64(p)}` ``` The OpenAI provider independently fetches remote image URLs: ```js for (const p of req.images) { const buf = isUrl(p) ? Buffer.from(await (await fetch(p)).arrayBuffer()) : await readFile(p) fd.append('image[]', new Blob([buf], { type: mimeOf(p) }), path.basename(p)) } ``` The Gemini provider fetches and forwards the retrieved data: ```js const key = env.GEMINI_API_KEY || env.GOOGLE_API_KEY const parts = [{ text: req.prompt }] for (const p of req.images || []) { parts.push({ inline_data: { mime_type: mimeOf(p), data: await asBase64(p) } }) } const j = await postJson( `https://generativelanguage.googleapis.com/v1beta/models/${gemini.model()}:generateContent`, { contents: [{ parts }] }, { 'x-goog-api-key': key }, req.timeoutMs, ) ``` ### Technical Analysis The `--images` interface accepts any string beginning with `http://` or `https://` and passes it directly to `fetch()`. The implementation does not: - Restrict remote images to trusted or user-approved hosts. - Resolve and reject loopback, private, link-local, or r ...[truncated 2963 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Reject remote URLs by default and require an explicit option such as `--allow-remote-images`. 2. Prefer downloading only from a narrowly defined allowlist of trusted asset hosts. 3. Before connecting, resolve every hostname and reject all loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 ranges. 4. Disable redirects or validate the resolved destination again after every redirect. 5. Explicitly block well-known metadata endpoints, including link-local metadata addresses and provider-specific metadata hostnames. 6. Permit only HTTPS unless a documented local workflow explicitly requires HTTP. 7. Enforce strict connect, response, and total-operation timeouts. 8. Stream downloads with a conservative maximum byte limit instead of buffering unbounded responses with `arrayBuffer()`. 9. Verify both the response `Content-Type` and the downloaded file's magic bytes against an allowlist of supported image formats. 10. Require user confirmation before uploading face images, product images, or remotely retrieved content to a third-party provider. 11. Document the destination provider and data-retention implications before transmission. 12. Add automated tests for loopback URLs, private IPv4 and IPv6 ranges, DNS rebinding, redirects to private addresses, metadata endpoints, non-image responses, and oversized files. ]]>

T08 · Insecure Dependencies

Note
Location
references/provider-cli.md:68
Finding
Documented npx Execution Lacks Package Integrity Verification<![CDATA[ ## Vulnerability Details **File Location**: `references/provider-cli.md:68` **Vulnerability Type**: Third-party package supply-chain exposure **Risk Level**: Low ### Vulnerable Code ```bash npx @dlazy/cli@1.2.3 <command> ``` ### Technical Analysis The documentation recommends using `npx` to download and execute `@dlazy/cli` from the npm ecosystem. Pinning version `1.2.3` reduces unintentional version drift, but the project does not provide a lockfile, cryptographic checksum, signature verification procedure, or vendored reviewed artifact for this command. Executing a freshly downloaded package places trust in the npm registry, the package publisher account, the selected package release, and its transitive dependency graph. If any of these are compromised, package or lifecycle code may execute with the permissions of the invoking user. This instruction does not execute automatically when the Skill is loaded. The risk is activated only if a user or Agent follows the documented command. ### Attack Path 1. An attacker compromises the package publisher, registry delivery path, referenced package release, or one of its install-time dependencies. 2. A user follows the documented `npx @dlazy/cli@1.2.3 <command>` instruction. 3. `npx` obtains the package and required dependencies from the configured npm registry or cache. 4. Package code or applicable lifecycle behavior executes under the invoking user's account. 5. Malicious code can access files, environment variables, credentials, and network resources available to that account. The fixed version makes opportunistic replacement less likely than an unpinned command, but it does not independently verify the integrity or provenance of the downloaded artifact. ### Impact Assessment A compromised package could execute arbitrary code with the current user's privileges. Potential access includes: - Files readable or writable by the user. - Provider API keys present in environment variables or local con ...[truncated 358 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prefer a locally declared dependency installed through a committed lockfile rather than downloading executable code at invocation time. 2. Record and verify package integrity hashes through the package manager's lockfile. 3. Verify npm package provenance or signatures where supported. 4. Review and pin all transitive dependencies used by the CLI. 5. Use a private or controlled registry mirror for production deployments. 6. Disable unnecessary lifecycle scripts during installation where compatible with the package. 7. Publish a checksum or signed release artifact and document a verification procedure. 8. Run the CLI in a restricted environment with only the files, environment variables, and network access required for image generation. 9. Avoid exposing unrelated credentials to the CLI process. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (25)

Ae1

High
Category
analysis-evasion
Content
node scripts/gen.mjs --task image-fusion \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/gen.mjs --task image-fusion \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Skill Enumeration

Medium
Category
Agent Snooping
Content
一次给**最多 8 张单品图**,融合成同一个模特身上的**一整套 Look**。

和 [flat-lay](https://github.com/dlazy-ai/ecommerce-skills/blob/main/skills/flat-lay/skill.md) 的「多件上身」(只支持上装+下装两张)不同,本技能是**任意品类的自由组合**:毛衣 + 阔腿裤 + 帽子 + 项链 + 包 + 鞋,一次出一张完整搭配图。

---
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The template guidance hard-codes `青年亚洲女模特` as the model description, which imposes a specific ethnicity in the skill's recommended output. This is a natural-language policy concern because the file does not present this as optional user-selected styling or document a region-specific requirement.

Skill Enumeration

Medium
Category
Agent Snooping
Content
| 两件单品颜色互串 | 色彩相近 | 追加「颜色不得互相污染」句,写死每件的色名 |
| 外套把内搭全挡住 | 未写层次 | 追加层次排序句,要求露出内搭领口与前襟 |
| 整组图风格不统一 | 每次 prompt 都改了背景/光线 | 固定第四节四项描述逐字不变 |
| 单品数量超过 8 | 超出能力 | 拆成两套 Look,或先用 [image-fusion](./skill.md) 出主体、再用 [wear-everything](https://github.com/dlazy-ai/ecommerce-skills/blob/main/skills/wear-everything/skill.md) 单独加配饰 |

---
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The document is primarily written in Chinese, but it includes a prominent mandatory instruction in English: "CRITICAL INSTRUCTION FOR AGENT: Run the `dlazy seedream-5.0` command to get results." This imposes a language choice for agent-facing behavior without offering a language/locale option or explaining a justified locale constraint.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The entire reference is written in Chinese and includes prescriptive agent instructions in Chinese, with no indication that users may choose another language or locale. This creates a natural-language policy concern because it effectively constrains interaction language without explicit opt-in or documented regional justification.

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.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This code exposes CLI help text and operational messages only in Chinese, which imposes a locale/language choice on all users. The policy allows fixed locale only when explicitly justified or when users are given a choice, neither of which is present here.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The manifest describes a narrowly scoped skill for fusing multiple clothing item images into a single outfit photo on one model. This provider abstraction explicitly supports generic generation requests with `video:boolean`, `text:boolean`, returns `texts`, and routes to providers that can emit videos or text, which is broader than the declared image-fusion behavior.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This module reads local image files and fetches remote images, then sends prompt and image content to third-party APIs such as OpenAI, Gemini, fal, Replicate, and Ark. The file contains no confirmation prompt, print/log disclosure, or explicit warning comment near these transmissions, so a user invoking higher-level functionality may not be informed that their data is being sent off-system.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The OpenAI provider explicitly switches to a general image-generation endpoint when no input images are supplied, which materially expands the skill beyond its stated multi-image fusion purpose. In a skill advertised as preserving fidelity across supplied items, this hidden fallback can cause unintended content generation and policy/scope bypass through prompt-only usage.

External Transmission

Medium
Category
Data Exfiltration
Content
model: () => env.GEN_MODEL_OPENAI || 'gpt-image-1',
  describe(req) {
    const ep = req.images?.length ? 'images/edits' : 'images/generations'
    return `POST https://api.openai.com/v1/${ep}  model=${openai.model()} size=${mapSize(req.size)} n=${req.batch}`
  },
  async run(req) {
    const key = env.OPENAI_API_KEY
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
model: () => env.GEN_MODEL_OPENAI || 'gpt-image-1',
  describe(req) {
    const ep = req.images?.length ? 'images/edits' : 'images/generations'
    return `POST https://api.openai.com/v1/${ep}  model=${openai.model()} size=${mapSize(req.size)} n=${req.batch}`
  },
  async run(req) {
    const key = env.OPENAI_API_KEY
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
: await readFile(p)
        fd.append('image[]', new Blob([buf], { type: mimeOf(p) }), path.basename(p))
      }
      r = await fetch('https://api.openai.com/v1/images/edits', {
        method: 'POST', headers: { authorization: `Bearer ${key}` }, body: fd,
      })
    } else {
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
method: 'POST', headers: { authorization: `Bearer ${key}` }, body: fd,
      })
    } else {
      r = await fetch('https://api.openai.com/v1/images/generations', {
        method: 'POST',
        headers: { authorization: `Bearer ${key}`, 'content-type': 'application/json' },
        body: JSON.stringify({
Confidence
85% confidence
Finding
This duplicate finding points to the same prompt-only general generation path. Because the skill is described as multi-image fusion, allowing pure text generation makes the capability broader and potentially policy-evasive in a way users and operators may not expect.

External Transmission

Medium
Category
Data Exfiltration
Content
method: 'POST', headers: { authorization: `Bearer ${key}` }, body: fd,
      })
    } else {
      r = await fetch('https://api.openai.com/v1/images/generations', {
        method: 'POST',
        headers: { authorization: `Bearer ${key}`, 'content-type': 'application/json' },
        body: JSON.stringify({
Confidence
85% confidence
Finding
This duplicate finding points to the same prompt-only general generation path. Because the skill is described as multi-image fusion, allowing pure text generation makes the capability broader and potentially policy-evasive in a way users and operators may not expect.

External Transmission

Medium
Category
Data Exfiltration
Content
model: (req) =>
    env.GEN_MODEL_REPLICATE ||
    (req?.images?.length ? 'black-forest-labs/flux-kontext-pro' : 'black-forest-labs/flux-dev'),
  describe(req) { return `POST https://api.replicate.com/v1/models/${replicate.model(req)}/predictions` },
  async run(req) {
    const input = { prompt: req.prompt, num_outputs: req.batch }
    if (req.images?.length) input.input_image = await asDataUri(req.images[0])
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
model: (req) =>
    env.GEN_MODEL_REPLICATE ||
    (req?.images?.length ? 'black-forest-labs/flux-kontext-pro' : 'black-forest-labs/flux-dev'),
  describe(req) { return `POST https://api.replicate.com/v1/models/${replicate.model(req)}/predictions` },
  async run(req) {
    const input = { prompt: req.prompt, num_outputs: req.batch }
    if (req.images?.length) input.input_image = await asDataUri(req.images[0])
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
This JSON file contains a natural-language note in Chinese describing the model configuration, which indicates the skill content is presented in a specific language with no visible opt-in or alternative. Under the policy, forcing a specific language or locale without user choice is a reportable natural-language policy violation.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
This file contains user-facing natural language in Chinese, including the header comment and later CLI messages, with no option to select another language or indication that the tool is intentionally region-specific. That can violate a language/locale policy when skills are expected to avoid forcing a specific language without user opt-in.

Natural-Language Policy Violations

Low
Confidence
96% confidence
Finding
The CLI emits help, warnings, and error messages only in Chinese, which forces a specific language for users interacting with the script. There is no opt-in, fallback, or documented justification for the locale restriction.

Context-Inappropriate Capability

Low
Confidence
93% confidence
Finding
The helper fetches arbitrary attacker-controlled HTTP(S) URLs and then processes the responses as image inputs, creating an SSRF-style primitive. This can be abused to make the host contact internal services or unexpected external targets, and may also enable retrieval of sensitive network-reachable resources depending on deployment.

Missing User Warnings

Low
Confidence
80% confidence
Finding
The module spawns an external `dlazy` process to fulfill requests, which is a safety-relevant operation under the code-file criteria. Although the code comments describe provider routing, there is no visible confirmation, logging, or user-facing warning in this file that an external CLI will be executed.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/lib/providers.mjs:104

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/gen.mjs:118

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/lib/providers.mjs:21