Back to skill

Security audit

Doubao Seedream & Seedance API Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill matches its AI media-generation purpose, but it needs Review because its install and configuration paths can execute unaudited remote code or expose API keys to untrusted endpoints.

Install only after reviewing the installer source from a fixed release or commit, and avoid running the documented one-click install from a mutable branch. Use a scoped Volcengine API key, prefer a temporary environment variable or a secret manager, verify that no project .volcengine/config.yaml overrides base_url, and keep generated downloads inside a dedicated output directory.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
toolkit/api_client.py:40
Finding

Volcengine API Key Disclosure Through an Unrestricted Base URL

Content
View full analysis
None: """Load configuration from environment variables.""" env_mappings = { "ARK_API_KEY": "api_key", "VOLCENGINE_BASE_URL": "base_url", "VOLCENGINE_TIMEOUT": "timeout", "VOLCENGINE_MAX_RETRIES": "max_retries", "VOLCENGINE_OUTPUT_DIR": "output_dir", } for env_var, config_key in env_mappings.items(): value = os.getenv(env_var) if value is not None: if config_key == "timeout": value = int(value) elif config_key == "max_retries": value = int(value) self._config[config_key] = value ``` ```python # toolkit/api_client.py:40-60 self.base_url = self.config.get_base_url() self.timeout = self.config.get_timeout() self.max_retries = self.config.get("max_retries", 3) self.api_key = self.config.get_api_key() if not self.api_key: raise AuthenticationError( message="API key not configured", context={"hint": "Set ARK_API_KEY environment variable or configure i ...[truncated 2264 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
toolkit/task_query.py:73
Finding

Arbitrary URL Retrieval Enables SSRF and Unsafe Result Downloads

Content
View full analysis
Path: output_path = Path(output_path) output_path.parent.mkdir(parents=True, exist_ok=True) try: with httpx.Client(timeout=60.0) as client: response = client.get(url, follow_redirects=True) response.raise_for_status() with open(output_path, 'wb') as f: for chunk in response.iter_bytes(chunk_size=chunk_size): f.write(chunk) return output_path except httpx.HTTPError as e: raise NetworkError( message=f"Failed to download file from {url}", original_error=str(e) ) except IOError as e: raise FileError( message=f"Failed to write file to {output_path}", file_path=str(output_path), original_error=str(e) ) ``` ```python # toolkit/task_query.py:73-102 def download_result(self, task_id: str, output_path: str) -> str: status = self.get_task_status(task_id) if status["status"] != "succeeded": raise ValueError(f"Task status is {status['status']}, cannot download") content = status.get("content", {}) video_url = content.get("video_url") if not video_url: raise ValueError("No video URL found in task result") import httpx response = httpx.get(video_url, follow_redirects=True) with open(output_path, "wb") as f: f.write(response.content) return output_path ``` ```python # toolkit/validator.py:113-133 @staticmethod def validate_url( ...[truncated 2960 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
toolkit/state_manager.py:23
Finding

Sensitive Task State Is Persisted Without Enforced File Permissions or Symlink Protection

Content
View full analysis
Any: """Load JSON from file or return default.""" if file_path.exists(): try: with open(file_path, 'r') as f: return json.load(f) except Exception: return default return default def _save_json(self, file_path: Path, data: Any) -> None: """Save data to JSON file.""" with open(file_path, 'w') as f: json.dump(data, f, indent=2, default=str) ``` ```python # toolkit/task_manager.py:73-89 task_info = TaskInfo( id=task_id, type=task_type, status=TaskStatus.QUEUED, params=params, created_at=now, updated_at=now ) self.state_manager.save_task_state(task_id, task_info.model_dump()) self.state_manager.add_history_entry( f"create_{task_type.value}", {"task_id": task_id} ) ``` ### Technical Analysis The state directory is created without explicitly applying owner-only permissions, and JSON state files are written without explicitly setting mode `0600`. Their effective permissions therefore depend on the process umask and any pre-existing filesystem objects. The sto ...[truncated 1672 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unpinned and Unhashed Dependencies Create Supply-Chain and Reproducibility Risk

Content
View full analysis
=5.0.0 PyYAML>=6.0 Pydantic>=2.0.0 httpx>=0.27.0 Pillow>=10.0.0 pytest>=7.4.0 pytest-cov>=4.1.0 ``` ```bash # SKILL.md:118-126 # Clone git clone https://github.com/Lychee-AI-Team/seedream-skill.git cd seedream-skill # Install dependencies pip install -r volcengine-api/requirements.txt ``` ### Technical Analysis Every dependency uses an open-ended lower-bound constraint. Installation can therefore select any future release satisfying the constraint, including versions that have not been audited with this project. No lock file or package hashes are supplied to verify artifact integrity. Development-only packages such as `pytest` and `pytest-cov` are included in the same requirements file as runtime dependencies, increasing the number of installed packages and transitive components. The documented installation command references `volcengine-api/requirements.txt`, which is not present in the supplied directory structure. This inconsistency can lead users to locate or substitute a different requirements file, further reducing installation integrity. No specific malicious dependency was identified in the artifact. The confirmed issue is unsafe and non-reproducible dependency management. ### Attack Path 1. A user follows the installation procedure and runs pip against the requirements. 2. Pip resolves the latest package releases satisfying the unbounded constraints. 3. A future compromised, malicious, or incompatible package release is selected without a corresponding project review. 4. Package installation hooks or imported dependency code execute with the installing user's privileges. 5. A malicious dependency can access files, environment variables, API keys, and network re ...[truncated 443 chars]
Remediation
View remediation

T03 · Remote Payload Retrieval and Execution

Warning
Location
SKILL.md:94
Finding

Recommended Installation Executes an Unreviewed Mutable Remote Script

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (43)

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

The documentation instructs users to write an API key into a project-local .env file. While common in development, this creates a realistic secret exposure risk if the repository is later committed, shared, included in build context, or read by other local tooling; the skill itself later warns against committing secrets, which confirms sensitivity. In this context, storing long-lived credentials in a plaintext project file is less safe than ephemeral environment variables or a proper secrets manager.

Content

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

md
cd seedream-skill

# Configure
echo "ARK_API_KEY=your-api-key" > .env

# Run
docker compose up --build

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

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

Use Case | |--------|----------|----------| | Environment Variables | ⭐⭐⭐⭐⭐ | Recommended - All scenarios | | Secret Management | ⭐⭐⭐⭐⭐ | Production environments | | Config File (600 permissions) | ⭐⭐⭐ | Local development |

🔑 Environment Variable Setup

bash
# Temporary (current session)
export ARK_API_KEY="your-api-key"

# Permanent (add to shell config)
echo 'export ARK_API_KEY="your-api-key"' >> ~/.bashrc
source ~/.bashrc

# Verify (should show first 4 characters)
echo $ARK_API_KEY | head -c 4

🔐 Config File Security

bash
# Create config
mkdir -p ~/.volcengine
cat > ~/.volcengine/config.yaml << 'EOF'
api_key: "your-api-key"
base_url: "https://ark.cn-beijing.volces.com/api/v3"
EOF

# Set permissions (CRITICAL!)
chmod 700 ~/.volcengine
chmod 600 ~/.volcengine/config.yaml

❌ Prohibited Actions

Don't Do ThisWhy?
❌ Commit API Key to GitPublicly accessible
❌ Log API KeyMay l

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · toolkit/config.py (reported line 251)May include surrounding context.

python
self._config[key] = value
    
    def get_api_key(self) -> Optional[str]:
        """Get API key from configuration."""
        return self.get("api_key")
    
    def get_masked_api_key(self) -> str:

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

This finding reflects persistence of a sensitive credential in a user home directory config file. Although presented as a convenience feature, storing the API key in plaintext under ~/.volcengine/config.yaml creates persistent local secret exposure that can be abused by other processes, backups, misconfigured permissions, or accidental disclosure. The skill context makes this somewhat less suspicious because it is framed as configuration guidance, but it remains a genuine security weakness compared with ephemeral environment variables or OS-backed secret stores.

Content

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

./scripts/configure.sh

Method 3: Config File

mkdir -p ~/.volcengine echo 'api_key: "your-api-key"' > ~/.volcengine/config.yaml chmod 600 ~/.volcengine/config.yaml # Important!

text

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

Method 3: Config File

mkdir -p ~/.volcengine echo 'api_key: "your-api-key"' > ~/.volcengine/config.yaml chmod 600 ~/.volcengine/config.yaml # Important!

text

### Verify Installation

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

Method 3: Config File

mkdir -p ~/.volcengine echo 'api_key: "your-api-key"' > ~/.volcengine/config.yaml chmod 600 ~/.volcengine/config.yaml # Important!

text

### Verify Installation

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

This snippet creates a persistent config file containing the API key in plaintext and therefore introduces the same credential persistence risk as the earlier RA2 finding. Persistent secrets in home-directory config files are commonly exposed through backups, dotfile sync tools, endpoint compromise, or accidental sharing, making this a real issue even though the documentation also suggests protective permissions.

Content

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

🔐 Config File Security

bash
# Create config
mkdir -p ~/.volcengine
cat > ~/.volcengine/config.yaml << 'EOF'
api_key: "your-api-key"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

EOF

Set permissions (CRITICAL!)

chmod 700 ~/.volcengine chmod 600 ~/.volcengine/config.yaml

text

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The help trigger phrase explicitly tells users to say "help" for interactive assistance, which is a very common everyday term. In agent environments, such broad triggers can collide with normal conversation and unintentionally invoke the skill, causing accidental actions or confusing context switches. The surrounding skill context increases the risk slightly because the skill can manage tasks and access configured credentials indirectly through its normal operation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This test file asserts that generated guides must contain Chinese strings such as "火山引擎API助手", "生成图像", and "生成视频". That hard-codes a specific language expectation in the skill behavior, which matches the policy category for language/locale constraints without visible user opt-in or documented justification in this file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The test asserts the presence of the Chinese phrase "图片生成成功", reinforcing that output must be in Chinese. As written, this encodes a mandatory language choice in natural-language expectations rather than validating behavior conditioned on user preference or a documented regional scope.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

These assertions require Chinese phrases like "视频生成成功" and "继续创作" or "提取视频帧". This is another natural-language policy issue because the tests encode a fixed language requirement with no evidence of user choice or explicit locale justification in the file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The assertion for "图像分析完成" continues the pattern of enforcing Chinese output only. This suggests the skill behavior is tied to a single language without opt-in, which falls under the language/locale policy concerns requested for review.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
80% confidence
Finding

The test checks for the Chinese term "视频" in suggestions, again encoding a fixed-language expectation. Without evidence in this file that the skill is intentionally region-scoped or that users can choose language, this is a policy concern rather than a harmless localization detail.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · toolkit/config.py (reported line 23)May include surrounding context.

python
# Sensitive keys that should be masked in logs/displays
SENSITIVE_KEYS = {"api_key", "ARK_API_KEY", "password", "secret", "token"}

# Secure file permissions for config files (read/write for owner only)
SECURE_FILE_MODE = 0o600
SECURE_DIR_MODE = 0o700

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · toolkit/config.py (reported line 88)May include surrounding context.

python
if not is_secure:
            warning = (
                f"Config file {file_path} has insecure permissions (mode: {oct(mode)}). "
                f"Recommend running: chmod 600 {file_path}"
            )
        
        return {

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · toolkit/config.py (reported line 326)May include surrounding context.

python
if not is_secure:
            warning = (
                f"Config file {file_path} has insecure permissions (mode: {oct(mode)}). "
                f"Recommend running: chmod 600 {file_path}"
            )
        
        return {

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · toolkit/config.py (reported line 360)May include surrounding context.

python
if not is_secure:
            warning = (
                f"Config file {file_path} has insecure permissions (mode: {oct(mode)}). "
                f"Recommend running: chmod 600 {file_path}"
            )
        
        return {

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · toolkit/config.py (reported line 360)May include surrounding context.

python
except Exception:
            warnings.warn(
                f"Could not set secure permissions on {config_path}. "
                f"Please run: chmod 700 {config_path.parent} && chmod 600 {config_path}",
                UserWarning
            )

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The welcome guide is entirely hard-coded in Chinese and presents itself as the default assistant interface without any indication that users can choose another language. This creates a locale/language policy concern because the skill enforces a specific language in user-facing guidance rather than offering user choice or documenting a justified regional constraint.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The module and class docstrings describe this component as generating contextual guidance, but the post-video guide explicitly suggests capabilities such as video editing, merging clips, adding background music, and extracting frames. In this file, those capabilities are not represented in the task routing or documented feature list, so the inline guidance materially overstates what the skill can do and may mislead users about supported operations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code file contains user-facing natural-language descriptions and guidance exclusively in Chinese, starting with the module docstring. Under the policy, forcing a specific language without user opt-in can be a locale/language policy violation when no alternative or justification is provided.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This smoke test sends user-provided prompt text and a generated image URL to remote API endpoints via multiple client.post/client.get calls. The file contains no confirmation prompt, print/log statement, or comment/docstring warning that user content will be transmitted to an external service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code writes state, task data, preferences, and operation history to JSON files under the user's home directory, which can affect user data persistence and privacy. Although the docstrings describe state management, there is no confirmation prompt, user-facing log/print, or explicit warning comment disclosing that data will be stored on disk.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · toolkit/state_manager.py (reported line 101)May include surrounding context.

python
# Operation History
    
    def add_history_entry(self, operation: str, details: Optional[Dict[str, Any]] = None) -> None:
        """Add entry to operation history."""
        entry = {
            "timestamp": datetime.now().isoformat(),
            "operation": operation,

Static analysis

No suspicious patterns detected.