Back to skill

Security audit

Generate Image

Security checks for vulnerabilities and agentic risk

Overview

This image-generation skill has a coherent purpose, but it lets article metadata steer credential-bearing image requests to arbitrary endpoints.

Install only if you trust the article drafts being processed and the configured image endpoint. Avoid using this with untrusted Markdown frontmatter or sensitive drafts until endpoint overrides are restricted and subprocess environment variables are minimized.

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
runtime.py:139
Finding

Article Frontmatter Can Redirect Credential-Bearing Image Generation Requests

Content
View full analysis
dict[str, Any]: env = os.environ.copy() if env_overrides: env.update({key: value for key, value in env_overrides.items() if str(value or "").strip()}) result = subprocess.run( args, check=False, capture_output=True, text=True, cwd=str(cwd) if cwd else None, env=env, ) ``` ```python def resolve_image_backend( *, article_path: Path, image_provider: str | None = None, image_api_base: str | None = None, image_model: str | None = None, ) -> dict[str, str]: defaults = default_image_backend() frontmatter = load_article_frontmatter(article_path) frontmatter_provider = clean_optional_value(frontmatter.get("image_provider")) frontmatter_api_base = clean_optional_value(frontmatter.get("image_api_base")) frontmatter_model = clean_optional_value(frontmatter.get("image_model")) requested_provider = clean_optional_value(image_provider) requested_api_base = clean_optional_value(image_api_base) requested_model = clean_optional_value(image_model) provider = requested_provider or frontmatter_provider or defaults["provider"] api_base = requested_api_base or frontmatter_api_base or defaults["apiBase"] model = requested_model or frontmatter_model or defaults["model"] ``` ```python image_backend = resolve_image_backend( article_path=article_path, image_provider=image_provider, image_api_base=image_api_base, image_model=image_model, ) command = [ "md2wechat", "generate_image", "--preset", preset, ...[truncated 3494 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
runtime.py:66
Finding

Binary Download Helper Permits Local File Copy and Unrestricted Network Retrieval

Content
View full analysis
None: ensure_parent(output_path) value = str(url or "").strip() if not value: raise RuntimeError("下载图片失败:缺少可用地址。") parsed = urlparse(value) if parsed.scheme in {"", "file"}: local_value = unquote(parsed.path) if parsed.scheme == "file" else value local_path = Path(local_value).expanduser() if local_path.exists() and local_path.is_file(): output_path.write_bytes(local_path.read_bytes()) return request = urllib.request.Request(value, headers={"User-Agent": "content-factory/1.0"}) try: with urllib.request.urlopen(request, timeout=60) as response: output_path.write_bytes(response.read()) except urllib.error.URLError as error: raise RuntimeError(f"下载图片失败:{error}") from error ``` ### Technical Analysis `download_binary` treats values with no URL scheme and `file:` URLs as local paths. It expands user-home notation and copies any readable regular file to the caller-selected output path. There is no restriction requiring the source to reside in an approved generated-assets directory. For network resources, the helper passes the supplied value to `urllib.request.urlopen` without enforcing HTTPS, restricting hosts, checking resolved addresses, validating redirects, verifying that the response is an image, or imposing a maximum response size. Calling `response.read()` without a limit loads the complete response into memory before writing it. The audited project contains no call site for this helper, so direct exploitability within the four-file artifact is contingent on another runtime component invoking it with attacker-influenced input. Nevertheless, the function itself exposes an unsa ...[truncated 1921 chars]
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (9)

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · runtime.py (reported line 36)May include surrounding context.

python
cwd: Path | None = None,
    env_overrides: dict[str, str] | None = None,
) -> dict[str, Any]:
    env = os.environ.copy()
    if env_overrides:
        env.update({key: value for key, value in env_overrides.items() if str(value or "").strip()})
    result = subprocess.run(

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README states that the skill will call an external image generation capability, but it does not clearly warn that article-derived content may be transmitted to a third-party service. In a content pipeline, drafts can contain unpublished, proprietary, or sensitive information, so missing disclosure increases the risk of inadvertent data exposure and unsafe use in regulated or confidential environments.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill declares broad operational behavior that includes reading article drafts, writing PNG outputs, invoking a shared runtime, and using a remote image API, but it does not define any explicit tool scope or permission boundaries. That makes the effective authority ambiguous and increases the risk that a runner grants unnecessary file, network, shell, or environment access beyond what image generation actually requires.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

This helper executes an external command via subprocess.run and propagates environment overrides, but the file provides no confirmation prompt, visible logging, or explanatory comment/docstring about that action. Subprocess execution is a safety-relevant operation under the rule and should have some user disclosure unless clearly covered by the skill description.

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 · runtime.py (reported line 39)May include surrounding context.

python
env = os.environ.copy()
    if env_overrides:
        env.update({key: value for key, value in env_overrides.items() if str(value or "").strip()})
    result = subprocess.run(
        args,
        check=False,
        capture_output=True,

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

download_binary accepts arbitrary URLs and also treats empty-scheme or file: values as local filesystem paths, then copies their bytes to an output path. In an agent skill, this creates a file-read and exfiltration primitive and also enables SSRF-like outbound fetching unrelated to the stated purpose of generating article companion images.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The function downloads data from a URL and writes it to the filesystem, but there is no confirmation prompt, user-facing log/print, or explanatory comment/docstring describing that behavior. For code files, file writes and network calls should have some visible disclosure unless already clearly documented elsewhere, which is not evident in this file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

该技能说明文档完全以中文撰写,没有提供多语言选项、英文摘要,或说明该技能仅面向中文团队/场景。若组织要求避免在未说明情况下强制单一语言,这种默认中文限定可能造成可用性和语言政策问题。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The raised error messages are hardcoded in Chinese, which imposes a specific language on users without any opt-in or locale selection mechanism visible in this file. The policy allows locale constraints only when users are given a choice or the restriction is clearly documented and justified.

Content

No source excerpt is available for this finding.