Back to skill

Security audit

ZM IMG2 直接生图执行

Security checks for vulnerabilities and agentic risk

Overview

This image-generation skill includes under-disclosed task-controlled shell execution and broad local file/network handling, so it needs review before installation.

Install only if you trust all task submitters and can run it in a tightly scoped sandbox. Do not feed untrusted queue JSON to image_queue.py, avoid command/mock_command, restrict provider configuration to approved endpoints, and treat prompts, input paths, logs, and generated artifacts as retained local records.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/image_queue.py:193
Finding

Arbitrary Shell Command Execution Through Queue Task Input

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/generate-image.js:15
Finding

Unrestricted Local File Read and Upload as a Reference Image

Content
View full analysis
{if(!value)return; if(Array.isArray(value)){for(const item of value) addValue(item); return;} values.push(value);}; addValue(args.image); addValue(args['input-image']); addValue(args.inputImage); addValue(args.reference); addValue(args['reference-image']); const addMany=(many)=>{if(!many)return; if(Array.isArray(many)){for(const item of many) addMany(item); return;} try{const parsed=JSON.parse(many); if(Array.isArray(parsed)) values.push(...parsed); else values.push(parsed);}catch{values.push(...String(many).split(',').map(s=>s.trim()).filter(Boolean));}}; addMany(args.images); addMany(args['input-images']); addMany(args.inputImages); return values.map(x=>expandHome(String(x)));} ``` ```javascript async function requestEdit({baseUrl,apiKey,model,prompt,size,timeoutMs,images,responseFormat}){const form=new FormData(); form.set('model',model); form.set('prompt',prompt); form.set('size',size); form.set('n','1'); form.set('response_format',responseFormat); for(const imgPath of images){if(!fs.existsSync(imgPath)) throw new Error(`input image not found: ${imgPath}`); const buf=fs.readFileSync(imgPath); const blob=new Blob([buf],{type:mimeFor(imgPath)}); form.append('image',blob,path.basename(imgPath));} return await fetchWithTimeout(baseUrl+'/images/edits',{method:'POST',headers:{Authorization:`Bearer ${apiKey}`},body:form},timeoutMs);} ``` ```javascript const inputImages=parseImages(args); if(inputImages.length>5) throw new Error('too many input images: max 5'); ``` ### Technical Analysis Reference paths are accepted as arbitrary strings and expanded relative to the user's home directory. The only file-level va ...[truncated 1888 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate-image.js:18
Finding

Server-Side Request Forgery Through Unvalidated Image Response URL

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/run.py:73
Finding

Approved Provider and Model Restrictions Are Not Enforced

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (24)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The manifest presents the skill as a direct image-generation tool, but the documentation also exposes queue orchestration, cancellation, subprocess supervision, mock/test command execution, and process-kill behavior. This mismatch can cause reviewers or callers to authorize the skill for a narrower purpose than it actually has, increasing the chance of unintended command execution and operational abuse.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The queue runner explicitly supports task['command'] and task['mock_command'], and when those are strings it executes them via ['bash', '-lc', ...]. That turns an image-generation skill into a general-purpose shell execution facility, enabling arbitrary code execution, file access, data exfiltration, and lateral misuse under the agent's privileges.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill declares no explicit tool scope while its documented operation clearly requires shell execution, filesystem read/write, environment access, and network access. In an agent environment, missing permission boundaries can allow broader-than-expected execution and make review, containment, and policy enforcement much weaker.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest uses Chinese-only display and description text, which suggests the skill is intended to operate in a fixed language without documenting any user opt-in or locale justification. Under the policy, language constraints should either offer user choice or clearly state a justified region-specific scope.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/batch_run.py (reported line 180)May include surrounding context.

python
write_state(state_path, status='running', started_at=started_at, task_started=task_started)

    try:
        proc = subprocess.run(
            cmd,
            cwd=str(WORKSPACE),
            text=True,

Tainted flow: 'WORKSPACE' from os.environ.get (line 5, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/batch_run.py (reported line 180)May include surrounding context.

python
write_state(state_path, status='running', started_at=started_at, task_started=task_started)

    try:
        proc = subprocess.run(
            cmd,
            cwd=str(WORKSPACE),
            text=True,

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The hard-coded diagnosis string uses Chinese text ("批量任务外层等待超时。") with no indication that language choice is configurable or user-selected. This creates a locale/language policy issue because the skill emits a specific language unconditionally rather than offering opt-in or matching user preference.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The batch runner writes the full input configuration to batch_request.json and also records per-task metadata including prompts, input image paths, and command arguments. Because the skill explicitly preserves inputs, outputs, logs, and result JSON, this can persist sensitive user content or arbitrary extra fields far beyond what is needed for execution, increasing data exposure risk if the workspace is shared, synced, or retained long-term.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The implementation materially exceeds the declared skill purpose by acting as a persistent task queue and execution framework with support for arbitrary command dispatch. This capability mismatch is dangerous because operators may trust the skill as image-only while it silently exposes a much broader execution surface, increasing the chance of abuse and reducing effective review.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Arbitrary subprocess execution is exposed as a normal code path without any explicit warning, confirmation, or privilege boundary. In the context of an agent skill expected to perform image generation, that makes accidental or malicious abuse much more likely because callers may not realize they are granting shell execution.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/image_queue.py (reported line 432)May include surrounding context.

python
with self._lock:
            self.state['tasks'][task_id]['_start_ts'] = start_ts
            self.persist()
        proc = subprocess.Popen(cmd, cwd=str(WORKSPACE), text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, start_new_session=True)
        thread_id = threading.get_ident()
        if not self.mark_running(task, worker_id, thread_id, proc, cmd):
            try:

Tainted flow: 'WORKSPACE' from os.environ.get (line 24, credential/environment) → subprocess.Popen (code execution)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/image_queue.py (reported line 432)May include surrounding context.

python
with self._lock:
            self.state['tasks'][task_id]['_start_ts'] = start_ts
            self.persist()
        proc = subprocess.Popen(cmd, cwd=str(WORKSPACE), text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, start_new_session=True)
        thread_id = threading.get_ident()
        if not self.mark_running(task, worker_id, thread_id, proc, cmd):
            try:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script persists the full prompt and input image paths into request.json for every attempt, creating a durable local record of potentially sensitive user data without any minimization, opt-in control, or warning in the code path. In this skill's context, prompts and image references are part of 'formal visual production evidence,' which increases the likelihood that private business data, personal data, or confidential file paths are retained longer than users expect and exposed to other local users, backups, or later collection processes.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/run.py (reported line 166)May include surrounding context.

python
stdout = ''
        stderr = ''
        try:
            proc = subprocess.run(
                cmd,
                text=True,
                stdout=subprocess.PIPE,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script writes raw stdout and stderr from the image-generation subprocess to disk, which may contain provider error payloads, prompts, model outputs, identifiers, local paths, or occasionally secret material returned by wrappers or upstream services. Although some values are sanitized when placed into state.json, these stdout/stderr log files are not sanitized before persistence, so sensitive data can be retained and later disclosed.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The file’s title and field descriptions are entirely in Chinese, with no indication that users may choose another language or that the skill is intentionally limited to a Chinese-language audience. Under the policy, forcing a specific language without opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The entire prompt is written as mandatory Chinese instructions and does not offer any language choice or indicate that the skill is intentionally limited to Chinese-speaking users. This creates a natural-language locale policy issue because it effectively imposes a specific language without user opt-in.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · tests/test_image_queue_minimal.py (reported line 18)May include surrounding context.

python
inp = pathlib.Path(td.name) / 'tasks.json'
    inp.write_text(json.dumps(payload), encoding='utf-8')
    cmd = [sys.executable, str(SCRIPT), 'run', '--state-dir', str(state), *args, '@' + str(inp)]
    cp = subprocess.run(cmd, cwd=str(ROOT), text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=30)
    assert cp.returncode == expect, (cp.returncode, cp.stdout, cp.stderr)
    return json.loads(cp.stdout), state, td

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The defaults section states that output goes to <openclaw-home>/generated-images, implying a standardized artifact location. Later, batch runs are documented as writing under content-factory/live-course-design/img2/batches/, which is a materially different destination and creates a mismatch in the described storage behavior.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The manifest description scopes the skill to executing text-to-image and image-to-image generation while preserving artifacts as production evidence. However, the file also exposes a broader queue-management subsystem with task submission, monitoring, history, duplicate handling, rejection, and cancellation semantics, which goes beyond straightforward direct generation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

This markdown file contains natural-language instructions exclusively in Chinese, and there is no indication that the skill is region-specific or that users may choose another language. Under the policy rule, forcing a specific language without opt-in can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This code writes multiple artifacts to disk, including task metadata, state, stdout/stderr logs, and batch summaries under the workspace, but there is no confirmation prompt, print/log disclosure, or explanatory docstring/comment warning the user that local files will be created and persisted. Because this is a code file, safety-relevant file writes that lack any visible disclosure meet the missing-warning criterion.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The argument parser description says this is a 'Batch runner for happy-img2-direct', while the manifest names the skill 'zm-img2-generation-direct'. This inline documentation does not match the declared skill identity and can mislead operators about what component they are invoking.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

This code file invokes another Python script via subprocess.run, which is a safety-relevant operation under the rule. In this file there is no confirmation, print/log message, docstring, or comment explaining that the helper executes an external process; the operation is only implicit in the implementation.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/generate-image.js:12