Back to skill

Security audit

Ark Seedance Video

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a legitimate Ark video-generation helper, but its runner has under-scoped network and credential handling that users should review before installing.

Install only if you trust the workspace and operator to keep commands and environment variables controlled. Avoid using --base-url, ARK_BASE_URL, or --api-key; provide ARK_API_KEY through a secure environment mechanism, use only the documented Ark endpoint, and do not run download on task.json files from untrusted sources. Treat prompts, task files, generated videos, and downloaded assets as sensitive local artifacts.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/seedance-video.js:215
Finding

Ark bearer credential and submitted media can be exfiltrated through an unrestricted API base URL

Content
View full analysis

Vulnerability Details

File Location: scripts/seedance-video.js:215-233
Vulnerability Type: Unrestricted authenticated endpoint override
Risk Level: High

Vulnerable Code

js
function createClient(options) {
  const apiKey = options.apiKey || process.env.ARK_API_KEY;
  if (!apiKey) {
    throw new Error("Missing ARK_API_KEY. Set the environment variable or pass --api-key.");
  }

  const baseUrl = stripTrailingSlash(options.baseUrl || process.env.ARK_BASE_URL || DEFAULT_BASE_URL);
  const headers = {
    Authorization: `Bearer ${apiKey}`,
    "Content-Type": "application/json",
  };

  return {
    async createTask(payload) {
      return requestJson(`${baseUrl}/api/v3/contents/generations/tasks`, {
        method: "POST",
        headers,
        body: JSON.stringify(payload),
      });
    },

The command-line interface explicitly exposes the override:

js
--api-key <key>                Override ARK_API_KEY
--base-url <url>               Override base URL (default: ${DEFAULT_BASE_URL})

Technical Analysis

The runner obtains a sensitive bearer credential from ARK_API_KEY and unconditionally places it in the Authorization header used with the selected baseUrl. That URL can be controlled through either --base-url or the ARK_BASE_URL environment variable.

No validation requires HTTPS, verifies that the destination is the documented Ark hostname, or otherwise establishes that the bearer credential is being sent to Volcengine. As a result, the credential can be transmitted to any attacker-controlled HTTP or HTTPS server.

During task creation, the same request also contains the generation payload. This can include prompts and Base64-encoded local image, video, or audio files. Although uploading selected media to Volcengine Ark is necessary and disclosed by the Skill, sending it to an arbitrary replacement origin is neither necessary nor dis ...[truncated 1553 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove support for --base-url and ARK_BASE_URL from production Skill execution if endpoint replacement is not a documented functional requirement.
  2. Hardcode the official origin:
    js
    const baseUrl = "https://ark.cn-beijing.volces.com";
    
  3. If endpoint configurability is required for controlled testing, enforce all of the following:
    • Require the https: scheme.
    • Parse the value with new URL().
    • Require an exact hostname allowlist, preferably only ark.cn-beijing.volces.com.
    • Reject embedded credentials, unexpected ports, fragments, and deceptive hostname suffixes.
    • Never attach the Ark authorization header to a non-allowlisted origin.
  4. Separate development endpoint overrides from the distributed production runner.
  5. Treat ARK_BASE_URL as untrusted input rather than trusted configuration.
  6. Add automated tests proving that HTTP URLs, lookalike domains, localhost, private addresses, and arbitrary public domains are rejected before any request is sent.
  7. Rotate any API key that may previously have been used with an untrusted base URL.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/seedance-video.js:201
Finding

Attacker-controlled task files enable arbitrary HTTP requests and unbounded response downloads

Content
View full analysis

Vulnerability Details

File Location: scripts/seedance-video.js:201-210, 358-440
Vulnerability Type: Server-side request forgery and unbounded arbitrary URL download
Risk Level: Medium

Vulnerable Code

The download operation accepts an arbitrary local JSON task file:

js
async function handleDownload(options) {
  const task = options.taskFile
    ? await readJson(path.resolve(options.taskFile))
    : await createClient(options).getTask(requireOption(options.taskId, "--task-id or --task-file is required for download"));

  const taskId = task.id || options.taskId || "unknown-task";
  const downloadDir = resolveDownloadDir(options.downloadDir, taskId);
  await ensureDir(downloadDir);
  await writeJson(path.join(downloadDir, "task.json"), task);
  await maybeDownloadTaskOutputs(task, downloadDir);
  printSummary(task, downloadDir);
}

Every nested HTTP or HTTPS url or *_url field is treated as an output:

js
function collectOutputUrls(value, prefix = "content") {
  const results = [];

  if (typeof value === "string") {
    if (isHttpUrl(value)) {
      results.push({ key: prefix, url: value });
    }
    return results;
  }

  if (Array.isArray(value)) {
    value.forEach((item, index) => {
      results.push(...collectOutputUrls(item, `${prefix}-${index}`));
    });
    return results;
  }

  if (!value || typeof value !== "object") {
    return results;
  }

  for (const [key, child] of Object.entries(value)) {
    const nextPrefix = `${prefix}.${key}`;
    if ((key === "url" || key.endsWith("_url")) && typeof child === "string" && isHttpUrl(child)) {
      results.push({ key: nextPrefix, url: child });
      continue;
    }
    results.push(...collectOutputUrls(child, nextPrefix));
  }

  return dedupeBy(results, (item) => `${item.key}|${item.url}`);
}

URL validation only checks the scheme, after which the r ...[truncated 3546 chars]

Remediation
View remediation

Remediation Suggestions

  1. Do not derive downloadable URLs recursively from arbitrary task-file content.
  2. Define and validate a strict task schema, accepting only documented output fields such as content.video_url and content.last_frame_url.
  3. Prefer downloads from task objects retrieved directly from the authenticated Ark API rather than user-supplied task files.
  4. Allowlist the exact Ark or Volcengine CDN hostnames authorized to serve generated assets.
  5. Before each request:
    • Require HTTPS.
    • Resolve the hostname.
    • Reject loopback, private, carrier-grade NAT, link-local, multicast, reserved, and metadata IP ranges for both IPv4 and IPv6.
    • Protect against DNS rebinding by connecting only to the validated address.
  6. Disable redirects or validate the scheme, hostname, and resolved address after every redirect.
  7. Add strict connection, header, idle, and total-operation timeouts.
  8. Stream downloads instead of calling response.arrayBuffer().
  9. Enforce a conservative maximum download size using Content-Length where available and a streaming byte counter in all cases.
  10. Require expected video or image content types and reject HTML, JSON, executable, or unknown responses.
  11. Avoid issuing a separate HEAD request solely to infer the filename extension; use a safe fixed extension or inspect validated GET response headers.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/seedance-video.js:215
Finding

API key command-line override exposes secrets through process and execution metadata

Content
View full analysis

Vulnerability Details

File Location: scripts/seedance-video.js:84, 215-218
Vulnerability Type: Sensitive credential accepted through command-line arguments
Risk Level: Low

Vulnerable Code

js
--api-key <key>                Override ARK_API_KEY
js
function createClient(options) {
  const apiKey = options.apiKey || process.env.ARK_API_KEY;
  if (!apiKey) {
    throw new Error("Missing ARK_API_KEY. Set the environment variable or pass --api-key.");
  }

Technical Analysis

The script permits the Ark bearer credential to be supplied as --api-key. Command-line arguments are generally not an appropriate secret transport mechanism because they can be exposed through:

  • Operating-system process inspection.
  • Shell history.
  • Agent tool-call records and execution transcripts.
  • CI/CD job logs.
  • Diagnostic and process-monitoring systems.
  • Error reports that reproduce complete commands.

This interface also conflicts with the Skill's declared policy in SKILL.md, which specifies use of ARK_API_KEY. Although the environment itself must also be secured, it avoids placing the credential directly in the command string.

Attack Path

  1. A user or agent invokes the runner with:
    text
    node scripts/seedance-video.js --api-key SECRET_VALUE --model MODEL_ID --prompt "..."
    
  2. The complete command is retained in shell history, an agent transcript, a job log, or process metadata.
  3. Another local user, log reader, monitoring service, or transcript recipient accesses that record.
  4. The exposed bearer credential is reused against Ark before it expires or is revoked.

Impact Assessment

An attacker who obtains the command-line value receives the same Ark API authority granted to the bearer token. Depending on the token's server-side privileges, this may enable billable task creation, task enumeration, access to generated output metadata, or deleti ...[truncated 197 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove the --api-key option from the CLI and from createClient().
  2. Accept the credential only through ARK_API_KEY or a dedicated secret-manager integration.
  3. Change the missing-key error so it no longer recommends passing the secret on the command line.
  4. Ensure agent execution logs do not print secret-bearing environment values.
  5. Document safe secret provisioning for local shells, CI/CD systems, and agent runtimes.
  6. Add tests confirming that --api-key is rejected and that credentials never appear in normal output or error messages.
  7. Rotate credentials previously supplied through commands retained in shared logs or transcripts.
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (9)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- Use only `scripts/seedance-video.js` for live execution.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- Use only `scripts/seedance-video.js` for live execution.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- Use only `scripts/seedance-video.js` for live execution.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- Use only `scripts/seedance-video.js` for live execution.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- Use only `scripts/seedance-video.js` for live execution.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- Use only `scripts/seedance-video.js` for live execution.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill instructs agents to execute a Node.js script that uses an environment secret (ARK_API_KEY) and performs network operations, but the manifest does not declare an explicit tool scope such as permissions or allowed-tools. This creates a governance gap: an agent may invoke broader execution or network capabilities than reviewers expect, making secret use and outbound data transfer less auditable and easier to misuse.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The documentation instructs users to write request payloads into the workspace, and these payloads may contain sensitive prompts, base64-encoded local media, asset identifiers, or URLs. In this skill's context, local files and generated artifacts are central to operation, so omitting any warning about local persistence, exposure to other tools/processes, or later cleanup creates a real privacy and data-handling weakness even if it is not an exploit primitive by itself.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The usage rule tells operators to keep request.json, task.json, and downloaded assets together for reproducibility, but does not mention that these files may include sensitive prompts, task metadata, generated media, or identifiers that persist locally. Because this skill is specifically designed to download and retain media artifacts, the missing privacy and retention warning is more relevant than in a generic skill and can lead to unintended disclosure or over-retention of user data.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/seedance-video.js:215