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## 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
## 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
Content
## 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
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
**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 '{
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
**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 '{
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
**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 '{
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
**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 '{
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
**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 '{
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
```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'])")
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
### 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
```
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
```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
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
-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
```
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
### 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"
```
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Content
# Open on macOS
                    if sys.platform == "darwin":
                        os.system(f'open "{filepath}"')
                except Exception as e:
                    print(f"Download failed: {e}", file=sys.stderr)
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.

Lp3

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.

Missing User Warnings

Medium
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.

External Transmission

Medium
Category
Data Exfiltration
Content
## 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
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.

Session Persistence

Medium
Category
Rogue Agent
Content
### 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
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.

External Transmission

Medium
Category
Data Exfiltration
Content
**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 '{
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.

External Transmission

Medium
Category
Data Exfiltration
Content
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 '{
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.

External Transmission

Medium
Category
Data Exfiltration
Content
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 '{
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.

External Transmission

Medium
Category
Data Exfiltration
Content
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 '{
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.

External Transmission

Medium
Category
Data Exfiltration
Content
```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 '{
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.

External Transmission

Medium
Category
Data Exfiltration
Content
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 '{
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.

Intent-Code Divergence

Medium
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.

Context-Inappropriate Capability

Medium
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.

Missing User Warnings

Medium
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.

Static analysis

No suspicious patterns detected.