T09 · Insecure Skill Coding Practices
- Location
scripts/image_queue.py:193- Finding
Arbitrary Shell Command Execution Through Queue Task Input
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
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.
scripts/image_queue.py:193Arbitrary Shell Command Execution Through Queue Task Input
scripts/generate-image.js:15Unrestricted Local File Read and Upload as a Reference Image
scripts/generate-image.js:18Server-Side Request Forgery Through Unvalidated Image Response URL
scripts/run.py:73Approved Provider and Model Restrictions Are Not Enforced
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.
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.
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.
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.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
write_state(state_path, status='running', started_at=started_at, task_started=task_started)
try:
proc = subprocess.run(
cmd,
cwd=str(WORKSPACE),
text=True,
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.
write_state(state_path, status='running', started_at=started_at, task_started=task_started)
try:
proc = subprocess.run(
cmd,
cwd=str(WORKSPACE),
text=True,
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.
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.
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.
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.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
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:
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.
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:
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.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
stdout = ''
stderr = ''
try:
proc = subprocess.run(
cmd,
text=True,
stdout=subprocess.PIPE,
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.
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.
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.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
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
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.
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.
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.
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.
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.
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.
Detected: suspicious.env_credential_access