Back to skill

Security audit

bizyair-skill

Security checks for vulnerabilities and agentic risk

Overview

The skill has a real BizyAir purpose, but it can spend account balance, upload local files, and lets untrusted search output influence agent behavior without strong safeguards.

Review carefully before installing. Use a limited BizyAir API key, keep unrelated secrets out of the environment when running batch jobs, do not submit sensitive local files, and require explicit user confirmation before any paid run or media upload. Treat search results and model descriptions as untrusted display text.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (4)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:71
Finding

Remote Tool Output Can Hijack Agent Instructions

Content
View full analysis
120: text = text[:120] + "..." lines.append(f"- **简介**:{text}") ``` ### Technical Analysis The Skill explicitly instructs the Agent to recognize an “agent / LLM instructions” marker in `reply_markdown` and obey the associated instructions. This improperly delegates the Agent's control plane to tool output. Candidate names, descriptions, cover URLs, and other metadata originate from remote BizyAir API responses. Although the scripts format these values, they do not classify them as untrusted data, escape Markdown control content, remove instruction markers, or prevent multiline metadata from imitating the privileged marker. The vulnerability is therefore not merely reflected content. The Skill defines a behavior that elevates specially formatted remote content into Agent instructions. This violates the separation between trusted Skill instructions and untrusted API data. ### Attack Path 1. An attacker publishes or compromises a BizyAir application, workflow, or ModelZoo listing. 2. ...[truncated 1263 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/cli.py:190
Finding

Paid ModelZoo Tasks Can Be Submitted Without an Enforced Confirmation Gate

Content
View full analysis
--param key=value [--image path ...] [--audio path ...] [--video path ...]") sys.exit(1) # ... media_overrides: dict[str, list[str]] = {} if images: media_overrides["images"] = [_api.upload_input_file(key, p) for p in images] if audios: media_overrides["audios"] = [_api.upload_input_file(key, p) for p in audios] if videos: media_overrides["videos"] = [_api.upload_input_file(key, p) for p in videos] detail_result = modelzoo.get_detail(key, endpoint) detail_data = (detail_result.get("data") or {}).get("data") or detail_result.get("data") or {} payload = modelzoo.build_task_payload(detail_data, params, media_overrides=media_overrides) create_result = modelzoo.create_task(key, endpoint, payload) ``` ### Technical Analysis The declared Skill policy states that every execution consumes the user's real balance and requires an explicit execution signal. However, the `modelzoo-run` implementation has no `--confirm-run` check, confirmation token, interactive challenge, or equivalent state transition. Once the command is invoked, it can first upload local media and then immediately call the paid task-creation endpoint. The safety boundary therefore exists only in natural-language instructions and is not enforced by the code performing the consequential action. This is particularly dangerous in an Agent environment, where an incorrect plan, ambiguous user request, or prompt-injection attack can cause command invocation without meaningful ...[truncated 1056 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/api.py:323
Finding

Upload Destination Is Constructed from Unvalidated Server-Controlled Host Components

Content
View full analysis
None: file_info = token_inner['file'] storage = token_inner['storage'] object_key = file_info['object_key'] bucket = storage['bucket'] endpoint = storage['endpoint'] access_key_id = file_info['access_key_id'] access_key_secret = file_info['access_key_secret'] security_token = file_info['security_token'] file_bytes = Path(file_path).read_bytes() # ... signature = base64.b64encode( hmac.new( access_key_secret.encode('utf-8'), string_to_sign.encode('utf-8'), hashlib.sha1, ).digest() ).decode('utf-8') upload_url = f'https://{bucket}.{endpoint}/{object_key}' req = urllib.request.Request(upload_url, data=file_bytes, method='PUT') req.add_header('x-oss-security-token', security_token) req.add_header('Authorization', f'OSS {access_key_id}:{signature}') with urllib.request.urlopen(req, timeout=300) as resp: ... ``` ### Technical Analysis The upload host is assembled from `bucket` and `endpoint` values returned by the upload-token API. Neither component is checked against an expected OSS domain allowlist. The code then sends: - The complete local file body. - A temporary access-key identifier. - A security token. - An OSS authorization signature. The Base64 operation itself is legitimate HMAC request signing and is not covert exfiltration. The vulnerability is that the resulting signed request and sensitive content can be transmitted to a destination selected by an unvalidated response. `urllib.request.urlopen` also follows redirects by default, and no post-redirect destination validation is performed. Thus, even a permitted initial ...[truncated 1125 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/api.py:583
Finding

Unrestricted Download of Server-Provided Output URLs Enables SSRF and Resource Exhaustion

Content
View full analysis
str: import shutil as _shutil with urllib.request.urlopen(url, timeout=300) as resp: final_url = resp.geturl() or url content_type = resp.headers.get('Content-Type') out = resolve_download_output_path( output_path, content_type=content_type, source_url=final_url, preferred_ext=preferred_ext, ) out.parent.mkdir(parents=True, exist_ok=True) with open(out, 'wb') as f: _shutil.copyfileobj(resp, f, length=8 * 1024 * 1024) return str(out.resolve()) def download_outputs(outputs: list[dict[str, Any]], output_path: str | None) -> list[str]: saved_paths: list[str] = [] total = len(outputs) for (index, item) in enumerate(outputs, start=1): object_url = item.get('object_url') if not object_url: raise ValueError(f'output #{index} missing object_url') target_path = resolve_indexed_output_path( output_path, index=index, total=total, preferred_ext=item.get('output_ext'), ) saved_paths.append( download_file( object_url, target_path, preferred_ext=item.get('output_ext'), ) ) return saved_paths ``` ### Technical Analysis The code retrieves `object_url` values returned by the remote task-output API without validating: - URL scheme. - Initial hostname. - DNS resolution. - Loopback, private, link-local, or metadata-service address ranges. - Redirect destinations. - Response size. - Expected media type. The `length` argument supplied to `shutil.copyfileobj` is only a buff ...[truncated 1494 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (48)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description is broadly about BizyAir media generation and AI app execution/search. The supplied code chunk is not performing generation itself; its primary purpose is batch management infrastructure: prefill cards for multiple tasks, asynchronous queued execution, worker spawning, status tracking, and policy enforcement. It also specifically disallows search-flow slugs in batch mode, which contrasts with the description mentioning app search as a trigger. While this batch functionality supports BizyAir app execution, it is a materially different and undeclared primary capability in this chunk, so the description does not accurately represent what the code actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The declared description frames this skill as a BizyAir media generation/application-execution integration. However, this code is a support module for argument/card parsing and run-readiness logic. It extracts fields from card text, infers defaults like aspect ratio/duration/seed, applies compiled values to argparse args, checks whether the user has authorized execution, and optionally loads prior-run parameters from runtime state for 'same as last time' behavior. These are orchestration/helper behaviors, not the declared BizyAir-facing generation/search/execution capabilities. While such parsing could support a BizyAir workflow, the supplied chunk itself materially differs from the declared primary purpose and includes state inheritance behavior not reflected in the description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This code chunk is purely low-level infrastructure for resolving paths and reading configuration, using environment variables and local filesystem locations. It does not perform or expose the declared end-user functionality of generating media, executing AI apps, handling BizyAir links/IDs, or searching BizyAir apps. While such path utilities could support a larger BizyAir skill, the actual behavior in this chunk is materially different from the declared purpose, so this chunk does not accurately represent the description.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
88% confidence
Finding

Each batch child process inherits the full ambient environment, which may expose secrets to every per-task subprocess regardless of necessity. Because this code can fan out many tasks concurrently, any compromise or unintended logging in child execution multiplies the opportunity for credential leakage across processes.

Content

Scanner excerpt · scripts/batch.py (reported line 267)May include surrounding context.

python
while next_index < len(tasks) or active:
            while next_index < len(tasks) and len(active) < concurrency:
                task = tasks[next_index]
                child_env = dict(os.environ)
                child_env[RUNTIME_STATE_DISABLED_ENV] = '1'
                (proc, log_handle) = launch_logged_process(build_batch_child_command(task), Path(task['log_path']), env=child_env)
                task['pid'] = proc.pid

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
88% confidence
Finding

The code clones the full parent environment into the worker process, which can unnecessarily propagate unrelated secrets such as cloud credentials, tokens, or proxy settings into a child that does not need them. In an agent/skill context that launches secondary processes and handles remote-generation workflows, broad environment inheritance increases blast radius if the child process, its logs, or downstream components are compromised.

Content

Scanner excerpt · scripts/batch.py (reported line 395)May include surrounding context.

python
payload = {'mode': 'batch_run', 'version': 2, 'task_count': len(payload_tasks), 'requested_concurrency': requested_concurrency, 'effective_concurrency': effective_concurrency, 'configured_max_concurrency': policy['max_concurrency'], 'system_max_concurrency': policy['system_max_concurrency'], 'configured_max_tasks': policy['max_tasks'], 'system_max_tasks': policy['system_max_tasks'], 'batch_dir': str(batch_dir.resolve()), 'status_path': str(status_path.resolve()), 'supervisor_log': str(supervisor_log.resolve()), 'scheduler_status': 'queued', 'tasks': payload_tasks}
    write_batch_status_file(status_path, payload)
    worker_file.write_text(json.dumps(payload, ensure_ascii=False, indent=2) + '\n', encoding='utf-8')
    worker_env = dict(os.environ)
    if base_args.api_key:
        worker_env['BIZYAIR_API_KEY'] = base_args.api_key
    worker_env[RUNTIME_STATE_DISABLED_ENV] = '1'

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/remote.py (reported line 324)May include surrounding context.

python
field_value = field.get('field_value')
    if logical_name == 'prompt':
        if prompt:
            return prompt
    elif logical_name == 'negative_prompt':
        if negative_prompt:
            return negative_prompt

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill advertises operational capabilities that imply shell, network, filesystem, and environment access, but it does not declare an explicit tool scope such as permissions or allowed-tools. That ambiguity weakens least-privilege controls and can let a host agent grant broader access than necessary, increasing the blast radius if prompts are manipulated or references are compromised.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The activation conditions are broad enough to trigger on common user requests such as generic image/video generation or mention of links/IDs, which can cause the skill to activate outside narrowly intended contexts. Over-broad triggering increases the chance that a high-capability skill with shell/network access is invoked unnecessarily, exposing users to unintended actions or data handling.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The instruction defines the assistant persona entirely in Chinese and directs how it should speak, but there is no indication that the user can choose another language or that the skill is intentionally limited to a Chinese-only audience. Under the language/locale policy, forcing a specific language without opt-in is a policy concern.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The skill explicitly supports querying wallet/API key/account information but does not require strong user-facing warnings or redaction rules for sensitive outputs. In a conversational environment, this can lead to accidental disclosure of secrets, balances, or usage history to the user transcript, logs, or unintended recipients.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Line L70 explicitly states '中文优先,英文技术词作补充', which imposes a language preference as a requirement rather than offering a user choice. This is a natural-language policy issue because the file applies a locale/language constraint without opt-in or documented justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The language-selection section instructs the agent to convert user Chinese into English for certain model families and recommends fixed languages per model type. This can violate locale/language policy because it imposes a language choice derived from the tool/model rather than offering the user a choice or requiring opt-in.

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 · references/04-modelzoo-tasks.md (reported line 27)May include surrounding context.

列表

bash
curl -sS -X POST "${X_BASE}/modelzoo/list?current=1&page_size=20&sort=Auto" \
  -H "lang: zh" -H "Content-Type: application/json" \
  -d '{"tags":[],"categories":[],"show_deprecated":false}'

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The examples explicitly force lang: zh, and the document itself is written as prescriptive operational guidance rather than an optional locale example. Under the policy, forcing a specific language/locale without user opt-in is a natural-language policy violation unless the constraint is clearly justified as region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This line repeats the same locale-forcing behavior for the detail API call, reinforcing that the skill expects a fixed language setting rather than a user-selected one. Because no alternative locale handling or opt-in is provided, it conflicts with the language/locale policy.

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 · references/04-modelzoo-tasks.md (reported line 59)May include surrounding context.

价格

bash
curl -sS "${X_BASE}/modelzoo/price_table/${ENDPOINT}" -H "lang: zh"

优先用 simple_price_text 直接展示(如 "100金币/次"、"5金币/张")。

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The task creation command includes -H "lang: zh" as part of the standard invocation, implying the skill should operate in Chinese by default for all users. The file does not provide a user choice or a documented justification for enforcing that locale.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The status-check example again hard-codes lang: zh, showing a consistent locale requirement across operations. Since the file does not offer the user a language choice or explain a necessary regional restriction, this is a policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This line extends the fixed Chinese locale behavior to call-record retrieval, indicating the skill uniformly forces one language setting. The absence of user choice or a clearly justified locale limitation makes this a policy violation under the stated rule.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown file contains a natural-language policy issue because it prescribes a specific locale for all requests using lang: zh. The guidance does not mention that users can choose another language or that the locale restriction is required for a documented region-specific reason.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The entire skill guidance, trigger phrases, and execution confirmations are specified only in Chinese, with no indication that users may choose another language or that the skill is intentionally limited to a Chinese-only context. This creates a natural-language policy concern because it effectively imposes a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The upload_input_file pipeline reads a local file, requests an upload token, uploads the file to OSS, and commits it to a remote service, but there is no confirmation prompt, print/log disclosure, or warning comment/docstring aimed at the user about transmitting local file contents off-host. Because this code handles user-provided files and sends them to external infrastructure, it meets the safety-critical network/data-transfer criterion for missing warnings in code files.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

download_file retrieves remote content via HTTP and writes it to a local path, creating parent directories as needed, but provides no confirmation, print/log disclosure, or warning comment for the file-write side effect. This is a safety-relevant local file write operation under the rule, and the code does not surface that behavior to the user here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This Python file contains primary user-facing documentation and multiple output messages in Chinese only, establishing a fixed language for interaction. The policy explicitly forbids forcing a specific language without user opt-in, and this file does not offer any language or locale selection.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code file contains user-facing natural-language strings and documentation exclusively in Chinese, including operational messages and replies. That can violate a language/locale policy when the skill forces a specific language experience without user opt-in or a documented regional constraint.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/app.py:55

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/batch.py:123

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/remote.py:518

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/search.py:298