Back to skill

Security audit

ark-video-storyboard

Security checks for vulnerabilities and agentic risk

Overview

The skill broadly matches a video-generation workflow, but it needs review because it uses an Ark API key, downloads and stores media locally, can send files externally, and has weak safeguards around those actions.

Review this before installing. Use a limited Ark API key, avoid sensitive reference images or prompts, confirm exactly where files will be saved and sent, and do not let it auto-send media to Feishu unless the destination is explicit. The ethnicity default should be removed or overridden, and the downloader/API scripts should be hardened before use in a shared or monitored environment.

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

Warning
Location
scripts/submit_segment.py:36
Finding

Ark API Credential Exposed Through Process Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/submit_segment.py:36-50
Vulnerability Type: Sensitive credential exposure through subprocess arguments
Risk Level: Medium

Vulnerable Code

python
def submit(payload: dict, api_key: str | None = None) -> dict:
    headers = ["-H", "Content-Type: application/json"]
    if api_key:
        headers += ["-H", f"Authorization: Bearer {api_key}"]
    cmd = [
        "curl", "-sS", API_URL,
        *headers,
        "-d", json.dumps(payload, ensure_ascii=False),
    ]
    try:
        p = subprocess.run(cmd, capture_output=True, text=True, check=False)
        if p.returncode != 0:
            return {"ok": False, "error": p.stderr.strip() or "curl failed"}
        return json.loads(p.stdout)
    except Exception as e:
        return {"ok": False, "error": str(e)}

The same pattern is also present in scripts/get_task_result.py:15-22:

python
def get_task(task_id: str, api_key: str | None = None) -> dict:
    headers = ["-H", "Content-Type: application/json"]
    if api_key:
        headers += ["-H", f"Authorization: Bearer {api_key}"]
    cmd = ["curl", "-sS", f"{API_BASE}/{task_id}", *headers]
    try:
        p = subprocess.run(cmd, capture_output=True, text=True, check=False)

Technical Analysis

Both functions interpolate the Ark API key into a curl command-line argument and then launch curl with subprocess.run. Although the subprocess is invoked without a shell, which prevents conventional shell metacharacter injection, the bearer credential remains present in the child process argument vector.

Depending on operating-system process visibility, container configuration, endpoint monitoring, audit logging, crash reporting, or process telemetry, another local process or administrative monitoring component may capture the full curl command line. This can disclose the bearer token.

Transmitting the credential t ...[truncated 1433 chars]

Remediation
View remediation

Remediation Suggestions

  • Replace the curl subprocess with a Python HTTPS client and place the Authorization header in the client's in-memory request structure.
  • Preserve normal TLS certificate and hostname verification.
  • If curl must be retained, supply sensitive configuration through a protected non-command-line channel, such as standard input with curl --config -, while ensuring the input is never logged.
  • Never include authorization headers in errors, debug output, task results, or telemetry.
  • Store configuration files containing API keys with restrictive permissions.
  • Fail explicitly when no credential is available rather than sending an unauthenticated request and returning an ambiguous API response.
  • Rotate the Ark API key after remediation if process arguments may already have been collected by monitoring systems.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/download_video.py:24
Finding

Unrestricted Redirected Download and Output-Path Escape

Content
View full analysis

Vulnerability Details

File Location: scripts/download_video.py:24-56
Vulnerability Type: Unvalidated remote URL and path traversal in file download
Risk Level: Medium

Vulnerable Code

python
def download(url: str, output_path: str | None = None, create_dated_dir: bool = True, output_dir: Path | None = None) -> str:
    """
    Download video to the specified path.

    Args:
        url: Video URL
        output_path: Output file path
        create_dated_dir: Whether to create a dated directory
        output_dir: Explicit output directory
    """
    if output_dir is not None:
        out_dir = Path(output_dir)
    elif create_dated_dir:
        out_dir = get_output_dir()
    else:
        out_dir = Path(DEFAULT_OUTPUT_DIR)

    out_dir.mkdir(parents=True, exist_ok=True)

    if output_path:
        out = out_dir / output_path
    else:
        out = out_dir / "video.mp4"

    cmd = ["curl", "-L", "-sS", url, "-o", str(out)]
    p = subprocess.run(cmd, capture_output=True, text=True, check=False)
    if p.returncode != 0:
        raise RuntimeError(p.stderr.strip() or "curl download failed")
    return str(out)

Technical Analysis

The download function accepts an arbitrary URL and invokes curl with -L, which follows redirects. It does not restrict the initial URL scheme or hostname and does not validate redirect destinations. A caller can therefore cause the executing host to make requests to unintended external or internal destinations.

The output filename is joined directly to the selected directory without canonicalization or containment validation. A value containing ../ can escape the media directory. With pathlib, an absolute output_path also replaces the preceding base directory entirely. Consequently, the function can write or overwrite any location writable by the user running the Skill.

The function also does not enforce a maximum respons ...[truncated 2312 chars]

Remediation
View remediation

Remediation Suggestions

  • Require HTTPS and reject all unsupported URL schemes.
  • Allowlist the expected Ark media-download hostnames.
  • Validate every redirect destination instead of following redirects without restriction.
  • Disable redirects unless they are required by the provider; if required, impose a small redirect limit.
  • Resolve the final output path with Path.resolve() and verify that it remains beneath the resolved approved output directory.
  • Reject absolute output filenames and any path containing traversal components such as ...
  • Prefer accepting only a simple filename generated internally rather than an arbitrary path.
  • Avoid unintended overwrites by using exclusive file creation or requiring explicit overwrite authorization.
  • Enable HTTP error handling, for example curl's --fail-with-body behavior or equivalent client-library checks.
  • Enforce a maximum download size, connection timeout, total timeout, and expected video content type.
  • Download to a temporary file inside the approved directory and atomically rename it only after validation succeeds.
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (33)

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The supplied code chunk implements only a narrow subset of the declared description: storyboard skeleton generation from a scene description. It does not process reference images, does not confirm anything with the user, and does not submit video generation tasks to Volcengine Ark or access external services at all. Because the declared purpose presents a broader end-to-end workflow with optional API task submission, while the actual code is just a local storyboard builder CLI, this is a meaningful description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This code chunk does not implement the declared storyboard/prompt-generation or Ark video task-submission workflow. Its actual purpose is simply to download a file from a URL and save it locally. That is a materially different primary behavior from the declared skill description. While downloading a generated video could be a supporting step in a larger video pipeline, the supplied code alone exposes undeclared network/file-download and local file-writing behavior and lacks the core declared capabilities such as script confirmation, storyboard creation, prompt generation, or API task submission.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Yes, there is a mismatch. The declared description presents a high-level creative workflow skill for generating storyboards/prompts and optionally submitting video-generation jobs. The supplied code chunk does not implement any of those core functions. Instead, it performs a narrower operational task: repeatedly querying an existing Ark task result and returning completion status/video URL. While polling could be a supporting part of a larger video workflow, this specific behavior is materially different from the declared primary purpose and introduces an undeclared capability/status-check function.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The code chunk only executes the backend multi-segment generation pipeline from a preexisting storyboard file. It reads storyboard JSON from disk, derives segment durations, submits segment prompts plus optional image references to the video API, polls task status, and may download resulting videos. The declared description includes upstream creative workflow behavior—generating a storyboard/prompts from a scene or images and confirming the script with the user—which is not present in this code. While optional submission to the Ark API is consistent with part of the description, the actual primary behavior here is narrower and more execution-oriented than declared. Additionally, polling and downloading are extra operational capabilities not explicitly described, though they are related to the same workflow.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Defaulting all human characters to East Asian unless the user specifies otherwise is an unjustified protected-attribute assumption embedded as a hard rule. This can systematically inject demographic bias into outputs, misrepresent user intent, and create discriminatory or exclusionary behavior across normal uses of the skill.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Defaulting all unspecified human characters to a specific ethnicity without user opt-in introduces systematic sensitive-trait bias into generated content. In a storyboard and video prompt pipeline, this can affect many scenes and outputs at scale, making the issue more dangerous because it silently shapes creative results and may exclude or misrepresent people.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The storyboard generator enforces an ethnicity rule for all human characters, causing every generated storyboard to inherit a race-based constraint regardless of user intent. In this skill's context, which automates prompt creation for video generation, that bias can systematically shape outputs at scale and create discriminatory, exclusionary, or policy-violating content.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill documentation instructs use of environment variables, file reads, and shell commands, but the manifest does not declare any tool scope or allowed-tools boundaries. This creates an authorization gap where a runtime may grant broader capabilities than users expect, especially because the skill reads API keys, accesses local files, and runs ffmpeg/shell operations.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill instructs sending generated files over Feishu, which extends beyond local storyboard generation into external exfiltration/messaging behavior. Even if intended for delivery, pushing local media to a messaging channel increases data-leak risk, especially when file contents, recipient/channel choice, and approval boundaries are not tightly constrained.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
71% confidence
Finding

The skill requires maintaining continuity across segments and additionally instructs writing processing details to a persistent local workflow file, which implies session-derived content may be stored and reused over time. Persistent storage of user prompts, character descriptions, and output paths can create privacy and data-retention risks if not disclosed, minimized, or access-controlled.

Content

Scanner excerpt · SKILL.md (reported line 140)May include surrounding context.

md
- Default all human characters to **East Asian / 东方亚洲人** unless the user explicitly specifies otherwise.
- All segments must belong to the **same video**, not unrelated clips.
- Maintain continuity for character appearance, wardrobe, environment, props, lighting logic, and emotional progression.
- Write the planning fields in Chinese unless the user requests another language.
- Write the final generation prompts in English unless the user explicitly wants Chinese prompts.
- Prefer cinematic, visual, action-oriented prompts over abstract descriptions.
- Do not silently retry failed API submissions in the background without telling the user.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The reference materially expands the skill from optional remote video task submission into automatic local downloading and persistent filesystem storage. That creates side effects beyond the stated user-facing purpose, increasing the chance of unexpected local writes, storage consumption, and handling of untrusted remote content without clear user consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The markdown directs the skill to automatically download videos from a returned URL and write them under ~/.openclaw/media without a clear warning or explicit opt-in. Downloading remote content and persisting it locally is a meaningful side effect that can expose the user to unwanted disk usage, unsafe content handling, and hidden persistence.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

Creating timestamped directories under ~/.openclaw/media for each task introduces persistent local artifacts that survive the session. That persistence may retain sensitive or unexpected media outputs on disk, especially when users may think the skill only generates prompts or submits cloud tasks.

Content

Scanner excerpt · references/api.md (reported line 82)May include surrounding context.

The script automatically creates the dated directory. Use --dir to specify a shared output directory for all segments so they end up in the same folder (important when submitting multiple segments in parallel):

bash
# First create the shared directory (once per task)
OUTDIR=$(date +%Y%m%d%H%M%S)
mkdir -p ~/.openclaw/media/$OUTDIR

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

Creating timestamped directories under ~/.openclaw/media for each task introduces persistent local artifacts that survive the session. That persistence may retain sensitive or unexpected media outputs on disk, especially when users may think the skill only generates prompts or submits cloud tasks.

Content

Scanner excerpt · references/api.md (reported line 82)May include surrounding context.

The script automatically creates the dated directory. Use --dir to specify a shared output directory for all segments so they end up in the same folder (important when submitting multiple segments in parallel):

bash
# First create the shared directory (once per task)
OUTDIR=$(date +%YmdHMS)
mkdir -p ~/.openclaw/media/$OUTDIR

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The rule injects a sensitive demographic attribute when the user did not ask for one, causing the system to make identity decisions beyond the skill’s stated storyboard/video-generation purpose. In a generative media workflow, this can systematically bias outputs and produce unwanted or discriminatory representations across prompts and segments.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Hard-coding an ethnicity for unspecified human characters is an unjustified inference of a sensitive trait and creates biased behavior in generated prompts. Because this skill is designed to turn ideas into media generation instructions, the rule can propagate stereotype-laden defaults into every downstream storyboard and video request.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The schema hard-codes a default ethnicity for all human characters without any user request, necessity, or documented safety reason. In a storyboard-generation skill, this creates biased outputs by default and can systematically override user intent or exclude other identities, making the generation behavior discriminatory rather than neutral.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Enforcing a default ethnicity for all human characters without opt-in is a policy and fairness flaw because it bakes a protected-attribute assumption into normal operation. In this skill context, the schema directly shapes generated creative outputs, so the bias is likely to propagate consistently across all storyboard and prompt generation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Mandating Chinese for several planning fields without user choice is a restrictive language policy that can reduce accessibility, cause misunderstandings, and conflict with user expectations or downstream systems expecting another language. While not as severe as the ethnicity default, it is still an unjustified hard-coded constraint that may lead to exclusion or operational failure.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The output-style rule reinforces a fixed Chinese-only requirement for planning fields, further cementing a non-optional language constraint throughout the skill. In a storyboard workflow, this can create avoidable usability and interoperability issues, especially for non-Chinese-speaking users or tools processing the generated content.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code hard-codes a demographic default, stating that all human characters are East Asian unless explicitly overridden. This introduces biased and unjustified identity assignment into generated content, which can lead to discriminatory outputs, user harm, and downstream compliance or reputational issues in a content-generation workflow.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This Python file contains natural-language comments, docstrings, and CLI help text in Chinese, including the default output directory comment and function documentation, without any indication that the skill is intended only for Chinese-speaking users. The policy requires avoiding language/locale constraints unless the user is given a choice or the restriction is explicitly justified.

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/download_video.py (reported line 55)May include surrounding context.

python
headers += ["-H", f"Authorization: Bearer {api_key}"]
    cmd = ["curl", "-sS", f"{API_BASE}/{task_id}", *headers]
    try:
        p = subprocess.run(cmd, capture_output=True, text=True, check=False)
        if p.returncode != 0:
            return {"ok": False, "error": p.stderr.strip() or "curl failed"}
        return json.loads(p.stdout)

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/get_task_result.py (reported line 21)May include surrounding context.

python
headers += ["-H", f"Authorization: Bearer {api_key}"]
    cmd = ["curl", "-sS", f"{API_BASE}/{task_id}", *headers]
    try:
        p = subprocess.run(cmd, capture_output=True, text=True, check=False)
        if p.returncode != 0:
            return {"ok": False, "error": p.stderr.strip() or "curl failed"}
        return json.loads(p.stdout)

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/submit_segment.py (reported line 46)May include surrounding context.

python
headers += ["-H", f"Authorization: Bearer {api_key}"]
    cmd = ["curl", "-sS", f"{API_BASE}/{task_id}", *headers]
    try:
        p = subprocess.run(cmd, capture_output=True, text=True, check=False)
        if p.returncode != 0:
            return {"ok": False, "error": p.stderr.strip() or "curl failed"}
        return json.loads(p.stdout)