Back to skill

Security audit

Seedance Video Generation

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its video-generation purpose, but it sends media to external services and has a macOS downloader bug that could run unintended shell commands.

Install only if you are comfortable sending prompts, image files, image URLs, and generated videos to external providers. Avoid using sensitive or private media, require explicit approval before any Feishu sharing, and avoid the macOS --download auto-open path until the os.system call is replaced with a non-shell subprocess call and task IDs/paths are validated.

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

T09 · Insecure Skill Coding Practices

Error
Location
seedance.py:212
Finding

Shell Command Injection Through an API-Controlled Task Identifier

Content
View full analysis

Vulnerability Details

File Location: seedance.py, lines 212-230
Vulnerability Type: Shell command injection
Risk Level: High
Affected Platform: macOS, when video downloading is enabled

Vulnerable Code

python
filename = f"seedance_{task_id}_{int(time.time())}.mp4"
filepath = download_path / filename

print(f"\nDownloading video to {filepath}...")
try:
    urllib.request.urlretrieve(video_url, str(filepath))
    print(f"Saved to: {filepath}")

    # Open on macOS
    if sys.platform == "darwin":
        os.system(f'open "{filepath}"')
except Exception as e:
    print(f"Download failed: {e}", file=sys.stderr)

Technical Analysis

The task_id value is incorporated into a local filename without validation. For newly created tasks, this value originates from the remote Ark API response. It can also enter the same code path through the positional task identifier accepted by the wait command.

The resulting filepath is interpolated into a command string passed to os.system(). Although the path is enclosed in double quotes, embedded double quotes and shell metacharacters are not escaped. Because os.system() invokes a command shell, a malicious task identifier can terminate the quoted argument and append an additional shell command.

Exploitation requires the polling request for the crafted task identifier to produce a successful task response with a downloadable video URL. This could occur if the trusted remote API were compromised, returned attacker-controlled task metadata, or an attacker could otherwise control a compatible API response. The vulnerable shell call is macOS-specific and is reached only after the video download succeeds.

Attack Path

  1. The attacker causes the application to process a task identifier containing a quote and shell metacharacters.
  2. The corresponding task-status request returns a successful result and a valid downloadable video_url.

...[truncated 1270 chars]

Remediation
View remediation

Remediation Suggestions

  1. Eliminate shell interpretation by replacing os.system() with an argument-vector subprocess call:

    python
    import subprocess
    
    if sys.platform == "darwin":
        subprocess.run(
            ["open", str(filepath)],
            check=False,
            shell=False,
        )
    
  2. Validate task identifiers before using them in filenames. Apply a strict allowlist matching the documented identifier format, for example:

    python
    import re
    
    if not re.fullmatch(r"[A-Za-z0-9_-]{1,128}", task_id):
        raise ValueError("Invalid task identifier")
    
  3. Decouple remote identifiers from filesystem names. Prefer a locally generated UUID as the filename and retain the remote task identifier only as metadata.

  4. Resolve the final destination and verify that it remains within the requested download directory before writing:

    python
    download_root = Path(download_dir).expanduser().resolve()
    filepath = (download_root / safe_filename).resolve()
    
    if download_root not in filepath.parents:
        raise ValueError("Download path escapes the destination directory")
    
  5. Restrict downloaded video URLs to expected schemes and, where supported by the API contract, trusted hosts. Reject local-file schemes and unexpected redirects.

  6. Add regression tests using task identifiers containing quotes, semicolons, command substitutions, control characters, and path separators. Verify that these inputs are rejected and never reach a shell.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (29)

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

md
## Execution (Recommended: Python CLI Tool)

A Python CLI tool is provided at `~/.claude/skills/seedance-video/seedance.py` for robust execution with proper error handling, automatic retries, and local image base64 conversion. **Prefer using this tool over raw curl commands.**

### Quick Examples with Python CLI

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

With image URL:

bash
TASK_RESULT=$(curl -s -X POST "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ARK_API_KEY" \
  -d '{

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

With image URL:

bash
TASK_RESULT=$(curl -s -X POST "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ARK_API_KEY" \
  -d '{

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

With image URL:

bash
TASK_RESULT=$(curl -s -X POST "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ARK_API_KEY" \
  -d '{

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

With image URL:

bash
TASK_RESULT=$(curl -s -X POST "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ARK_API_KEY" \
  -d '{

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

With image URL:

bash
TASK_RESULT=$(curl -s -X POST "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ARK_API_KEY" \
  -d '{

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

bash
echo "Waiting for video generation to complete..."
while true; do
  STATUS_RESULT=$(curl -s -X GET "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks/${TASK_ID}" \
    -H "Authorization: Bearer $ARK_API_KEY")

  STATUS=$(echo "$STATUS_RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin)['status'])")

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

Query Task Status

bash
curl -s -X GET "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks/${TASK_ID}" \
  -H "Authorization: Bearer $ARK_API_KEY" | python3 -m json.tool

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

bash
# List all tasks (paginated)
curl -s -X GET "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks?page_num=1&page_size=10" \
  -H "Authorization: Bearer $ARK_API_KEY" | python3 -m json.tool

# Filter by status

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

-H "Authorization: Bearer $ARK_API_KEY" | python3 -m json.tool

Filter by status

curl -s -X GET "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks?page_num=1&page_size=10&filter.status=succeeded"
-H "Authorization: Bearer $ARK_API_KEY" | python3 -m json.tool

text

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

Cancel or Delete Task

bash
curl -s -X DELETE "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks/${TASK_ID}" \
  -H "Authorization: Bearer $ARK_API_KEY"

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
94% confidence
Finding

The code invokes a shell via os.system() using a command string that includes a file path influenced by user input through --download. Although the filename itself is generated, shell metacharacters in the download directory path can break out of quoting or alter command behavior, leading to local command execution on macOS when a task completes. In a tool whose stated purpose is video generation and task management, automatically launching a local file is unnecessary and increases attack surface.

Content

Scanner excerpt · seedance.py (reported line 230)May include surrounding context.

python
# Open on macOS
                    if sys.platform == "darwin":
                        os.system(f'open "{filepath}"')
                except Exception as e:
                    print(f"Download failed: {e}", file=sys.stderr)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill clearly instructs use of shell, environment variables, and outbound network access, but it does not declare tool scope or permissions metadata. That makes the operational capabilities implicit, which increases the chance an agent or reviewer will invoke sensitive actions without clear governance or user consent boundaries.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill sends user prompts and potentially local image contents to a third-party API, but the documentation does not prominently warn users that their data leaves the local environment. This creates a privacy and data-handling risk, especially if users provide sensitive prompts or private local images assuming local-only processing.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

The Python CLI is explicitly designed to send prompts and possibly local image data to an external Volcengine API. This is expected for the skill's function, but it is still a real external transmission risk because sensitive user content and locally sourced files may be uploaded to a third party.

Content

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

md
## Execution (Recommended: Python CLI Tool)

A Python CLI tool is provided at `~/.claude/skills/seedance-video/seedance.py` for robust execution with proper error handling, automatic retries, and local image base64 conversion. **Prefer using this tool over raw curl commands.**

### Quick Examples with Python CLI

Session Persistence

Medium
Category
Rogue Agent
Confidence
87% confidence
Finding

The examples encourage create/wait/download workflows and later task lookup by ID, which means task state persists across time and may be revisited or reused. In this context that is functional rather than covert, but it still involves persistence of externally stored generation jobs and downloadable artifacts that users may not fully expect.

Content

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

Quick Examples with Python CLI

bash
# Text-to-video (create + wait + download)
python3 ~/.claude/skills/seedance-video/seedance.py create --prompt "小猫对着镜头打哈欠" --wait --download ~/Desktop

# Image-to-video from local file

External Transmission

Medium
Category
Data Exfiltration
Confidence
97% confidence
Finding

This curl example uploads prompt text and an image URL to a third-party service. While core to the skill, it still creates a privacy and data-sharing risk because user-supplied content is transmitted off-platform and may be retained or logged externally.

Content

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

With image URL:

bash
TASK_RESULT=$(curl -s -X POST "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ARK_API_KEY" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
99% confidence
Finding

This example base64-encodes a local image file and uploads its full contents to the external API. That crosses a stronger trust boundary than URL-only inputs because it reads local files and transmits their raw data, which may include private or regulated content.

Content

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

md
IMG_BASE64=$(base64 < "$IMG_PATH" | tr -d '\n')
IMG_DATA_URL="data:image/${IMG_EXT_LOWER};base64,${IMG_BASE64}"

TASK_RESULT=$(curl -s -X POST "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ARK_API_KEY" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
97% confidence
Finding

This example transmits a prompt plus first and last frame image URLs to the external API. It is expected behavior, but still a real exposure of user-provided media references and generation intent to a third-party processor.

Content

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

Requires two images. Supported by: Seedance 1.5 Pro, 1.0 Pro, 1.0 Lite I2V.

bash
TASK_RESULT=$(curl -s -X POST "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ARK_API_KEY" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
97% confidence
Finding

Reference-image generation sends prompt text and one or more reference images to the remote provider. Because the feature may involve multiple images and identity/style references, the privacy and IP sensitivity can be higher than simple text-only generation.

Content

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

Provide 1-4 reference images. Use [图1], [图2] in prompt to reference specific images.

bash
TASK_RESULT=$(curl -s -X POST "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ARK_API_KEY" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

Draft generation sends user content to the external API for processing just like full generation. The draft/final workflow may lead users to submit content repeatedly, increasing aggregate exposure if the data-sharing implications are not clearly explained.

Content

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

bash
# Step 1: Create draft
DRAFT_RESULT=$(curl -s -X POST "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ARK_API_KEY" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

The final-from-draft request sends a draft task reference back to the provider, continuing reliance on externally stored task state. This is a real trust-boundary crossing because generated assets and metadata remain managed by the third-party service.

Content

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

md
DRAFT_TASK_ID=$(echo "$DRAFT_RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")

# Step 2: After draft succeeds, generate final video from draft
FINAL_RESULT=$(curl -s -X POST "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ARK_API_KEY" \
  -d '{

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The file presents Feishu delivery as something you can do 'with this skill' even though the described actions are actually carried out by a different message tool. This can mislead an autonomous agent or user about the skill's true capabilities and trust boundary, making it easier to trigger cross-tool actions that were not expected under the seedance-video skill's stated purpose.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The document expands a video-generation skill into guidance for sending files via Feishu, including use of Feishu access tokens and external API endpoints. This broadens the operational scope from content generation to data transmission and credential-dependent messaging, increasing the chance that an agent will perform unintended outbound actions or handle sensitive credentials without clear authorization boundaries.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation instructs uploading a locally generated video to Feishu/CDN and sending it to a chat, but it does not warn that the file leaves the local environment and is stored by a third party. In an agent setting, omission of this disclosure can cause unintended exfiltration of user-generated or sensitive media, especially when local workspace files may contain private content.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.