Back to skill

Security audit

Huo15 Comic Character

Security checks for vulnerabilities and agentic risk

Overview

The skill mainly does the advertised image-card generation, but unsafe path handling and under-disclosed network/file behavior need review before installation.

Install only if you are comfortable sending character descriptions to Volcengine Ark and using ARK_API_KEY from the environment. Review or patch the path handling before running it on untrusted script.json files, and constrain output directories and network access in sensitive environments.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/character.py:69
Finding

Untrusted Character IDs Allow Output-Directory Traversal

Content
View full analysis
None: path.parent.mkdir(parents=True, exist_ok=True) r = requests.get(url, stream=True) with open(path, "wb") as f: for chunk in r.iter_content(8192): f.write(chunk) ``` ### Technical Analysis The character identifier `char["id"]` is read directly from the user-selected script JSON and interpolated into an output path without validation. Python's `pathlib` does not automatically constrain a joined path to its intended parent directory. An identifier containing traversal components, such as `../../shared/avatar`, causes the generated paths to resolve outside `out_dir`. An absolute identifier can similarly replace the preceding base path after interpolation and joining. The `download()` function creates missing parent directories and writes the remote response to the resulting path. The code avoids replacing a destination that already exists because of the `out.exists()` check. However, it can still create attacker-selected files at writable locations outside the declared output di ...[truncated 1274 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/character.py:42
Finding

Unvalidated Remote Image URLs Enable Server-Side Request Forgery and Unbounded Downloads

Content
View full analysis
None: path.parent.mkdir(parents=True, exist_ok=True) r = requests.get(url, stream=True) with open(path, "wb") as f: for chunk in r.iter_content(8192): f.write(chunk) ``` ### Technical Analysis A URL returned by the external Ark service is treated as trusted and passed directly to `requests.get()`. The downloader accepts arbitrary schemes supported by the HTTP client, follows redirects by default, and does not restrict the final host or IP address. If the API response, endpoint, DNS path, or an upstream account is compromised, the returned URL could target loopback, private, link-local, or cloud metadata addresses. Redirects could also move an initially acceptable URL to such a destination. The response body is streamed until the server closes the connection. Since there is no timeout or maximum byte count, a remote server can hold the process open indefinitely or cause disk exhaustion. Because `raise_for_status()` is not called and the MIME type is not checked, error pages and arbitrary non-image content can be stored with a `.png` extension. The normal prompt submission to the declared Volcengine API is necessary for the Skill's advertised remote image-generation function. The risk ...[truncated 1594 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/character.py:63
Finding

Budget Enforcement Occurs Only After Billable API Requests

Content
View full analysis
None: """开工前硬熔断.""" if estimated_total > self.cap: suggestions = self.downgrade_suggestions(estimated_total) raise BudgetExceeded(...) ``` ### Technical Analysis The Skill loads a `CostGuard`, but it does not call `preflight()` before generating images. For each image, it calls the paid remote operation first, downloads the result, and only then records the charge. `CostGuard.charge()` raises `BudgetExceeded` when accumulated recorded spending reaches the configured cap. Because that check occurs after the API request, it cannot prevent the request that crosses the limit. If the project state is already at or near the cap, another billable operation is still initiated. The documented cost guard therefore does not act as a strict pre-request authorization boundary. It is an accounting control applied after resource consumption. ### Attack Path 1. A project has recorded spending at or just below its configured cap. 2. The user run ...[truncated 1041 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (21)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Persisting historical cost state and estimating unrelated downstream media costs is not inherently malicious, but it is inconsistent with the declared narrow purpose and introduces silent local statefulness. In a production agent setting, hidden budget controls and on-disk state can affect future runs, leak project metadata, or obscure what the skill is truly doing.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Persisting historical cost state and estimating unrelated downstream media costs is not inherently malicious, but it is inconsistent with the declared narrow purpose and introduces silent local statefulness. In a production agent setting, hidden budget controls and on-disk state can affect future runs, leak project metadata, or obscure what the skill is truly doing.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Persisting historical cost state and estimating unrelated downstream media costs is not inherently malicious, but it is inconsistent with the declared narrow purpose and introduces silent local statefulness. In a production agent setting, hidden budget controls and on-disk state can affect future runs, leak project metadata, or obscure what the skill is truly doing.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Persisting historical cost state and estimating unrelated downstream media costs is not inherently malicious, but it is inconsistent with the declared narrow purpose and introduces silent local statefulness. In a production agent setting, hidden budget controls and on-disk state can affect future runs, leak project metadata, or obscure what the skill is truly doing.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Persisting historical cost state and estimating unrelated downstream media costs is not inherently malicious, but it is inconsistent with the declared narrow purpose and introduces silent local statefulness. In a production agent setting, hidden budget controls and on-disk state can affect future runs, leak project metadata, or obscure what the skill is truly doing.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill advertises executable behavior involving file I/O and network-backed image generation, but it declares no explicit tool scope or permissions. In an agent environment, missing scope boundaries can allow broader-than-expected access to files, environment secrets, or outbound network resources, increasing the blast radius if the implementation or prompts are abused.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/_shared/ark_api.py (reported line 66)May include surrounding context.

python
"size": size,
            "watermark": False,
        }
        resp = requests.post(
            f"{self.base_url}/images/generations",
            headers=self.headers,
            json=body,

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest describes a skill for generating character full-body/half-body/chibi image cards from a script's characters field using Seedream 4.0. This file additionally exposes Seedance video task submission/polling/downloading and Doubao TTS synthesis, which are distinct media-generation capabilities not implied by the stated skill purpose.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/_shared/ark_api.py (reported line 144)May include surrounding context.

python
if seed is not None:
            body["seed"] = seed

        resp = requests.post(
            f"{self.base_url}/contents/generations/tasks",
            headers=self.headers,
            json=body,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The TTS method transmits provided text to an external service and writes returned audio to local storage without any consent, classification, or minimization controls. If callers pass sensitive script content, prompts, or private data, this creates a real confidentiality risk through third-party transmission and local artifact creation.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

This call sends arbitrary input text to an external TTS service, which is a real data-exposure concern when text may contain sensitive scripts, user content, or internal material. In a skill focused on character image cards, the TTS capability is also out of scope, making unexpected transmission less likely to be anticipated by operators and therefore more dangerous.

Content

Scanner excerpt · scripts/_shared/ark_api.py (reported line 207)May include surrounding context.

python
if emotion:
            body["emotion"] = emotion

        resp = requests.post(
            f"{self.base_url}/audio/speech",
            headers=self.headers,
            json=body,

Tainted flow: 'resp' from requests.get (line 158, network input) → pathlib.Path.write_bytes (file write)

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/_shared/ark_api.py (reported line 216)May include surrounding context.

python
resp.raise_for_status()
        out = pathlib.Path(out_path)
        out.parent.mkdir(parents=True, exist_ok=True)
        out.write_bytes(resp.content)
        return out

    # ------------ 工具 ------------

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The helper silently reads arbitrary local file paths and inlines their contents into outbound requests as data URIs. In this skill context, that is more dangerous because a character-image skill may receive user- or workflow-supplied image paths, and local files could be exfiltrated to the remote API without clear consent or path restrictions.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/_shared/config.py (reported line 35)May include surrounding context.

python
# API 端点(2026-04 核对)
ENDPOINTS = {
    "ark_base":      "https://ark.cn-beijing.volces.com/api/v3",
    "kling_base":    "https://api.klingai.com/v1",         # 官方;第三方 piapi.ai/fal.ai 亦可
    "suno_base":     "https://api.sunoapi.org",             # 第三方(Suno 无公开官方 API)
}

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This file contains natural-language docstrings and runtime messages entirely in Chinese, including warning and exception text shown to users. That enforces a specific language/locale without offering a user choice or documenting a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The file's natural-language description and prompt strings are entirely in Chinese, indicating the skill is designed to operate in a fixed language/locale. There is no visible user opt-in, language selection, or documented justification for restricting the skill to Chinese.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script sends character descriptions to an external image-generation service and then downloads remote content without any notice, consent flow, or data-handling safeguards. Because the characters data may contain sensitive or proprietary story information, this can cause unintended external disclosure and creates trust and compliance risks in environments where outbound transmission is restricted.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

download_video creates directories and writes streamed HTTP response data directly to out_path. Although this is expected behavior for a download helper, the function itself has no print/log/comment/docstring warning that it will create files on disk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The only natural-language description in the file is written in Chinese, which can amount to a language policy issue when a skill forces a specific language without user opt-in. The file does not indicate that the locale is region-specific or that users may choose another language.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

This code creates the project directory and writes a .checkpoint.json file, which is a file-system modification covered by the missing user warnings rule for code files. While the behavior is benign and expected for checkpointing, the file contains no confirmation prompt, logging, print statement, or explanatory comment/docstring near the write operation to disclose that state will be persisted on disk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

This file's docstrings and comments are entirely in Chinese, which can reflect a natural-language locale constraint for maintainers or operators. The file does not indicate that language selection is optional or justified as region-specific, so it may conflict with a policy requiring language/locale choice.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.