Back to skill

Security audit

dy-video-to-text

Security checks for vulnerabilities and agentic risk

Overview

The skill’s Douyin transcription and download purpose is clear, but its scripts can make requests to arbitrary user-supplied URLs before validating that they are Douyin links.

Review before installing. Only use this with trusted Douyin links, avoid running it in environments with access to internal services, and prefer an isolated virtual environment with pinned dependencies. Be aware that transcription sends the video URL and API key to Alibaba Cloud and downloading writes video files locally.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/douyin_parse.py:35
Finding
Unrestricted User-Supplied URL Requests Enable Blind SSRF<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/douyin_parse.py:35-43` - `scripts/douyin_download.py:37-45` - `scripts/douyin_extract_text.py:42-50` **Vulnerability Type**: Server-Side Request Forgery through unrestricted URLs and redirects **Risk Level**: High ### Vulnerable Code The same vulnerable URL-processing pattern appears in all three scripts: ```python urls = re.findall( r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', share_text, ) if not urls: raise ValueError("No valid share link found in input") share_url = urls[0] share_response = requests.get(share_url, headers=HEADERS, timeout=15) video_id = share_response.url.split("?")[0].strip("/").split("/")[-1] ``` ### Technical Analysis Although the Skill declares that its input should be a Douyin share URL, the regular expression accepts any HTTP or HTTPS URL. The code does not verify: - That the hostname belongs to Douyin or ByteDance. - That HTTPS is used. - That the destination port is expected. - That the resolved IP address is public. - That the destination is not loopback, private, link-local, or reserved. - That each redirect remains within an approved domain. `requests.get()` follows HTTP redirects by default. Consequently, even an initially acceptable-looking URL could redirect the request to an internal service. The timeout limits request duration but does not prevent SSRF. The response body from the first request is not directly returned to the caller, which limits direct data extraction. Nevertheless, response timing, error behavior, and subsequent script behavior may provide a blind network oracle. More importantly, the HTTP GET itself can reach endpoints that are unavailable to the attacker directly. ### Attack Path 1. An attacker supplies a direct internal URL, such as `http://127.0.0.1:PORT/path`, as the first URL in the input. 2. Alternatively, the attacker supplies an externally controlled URL that redirects to a p ...[truncated 1330 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse input with `urllib.parse.urlsplit()` rather than accepting the first generic URL matched by a regular expression. 2. Require HTTPS and allow only explicitly approved Douyin share hosts, such as `v.douyin.com`. 3. Reject embedded credentials, unexpected ports, malformed hostnames, and hostname suffix tricks. 4. Resolve the hostname before connecting and reject every loopback, private, link-local, multicast, unspecified, or reserved IPv4/IPv6 address. 5. Disable automatic redirects with `allow_redirects=False`. 6. Process redirects manually with a small maximum redirect count, validating the scheme, hostname, port, and resolved IP address at every hop. 7. Validate the final URL structure and video identifier before making the second request. 8. Apply the fix consistently in all three affected scripts, preferably by moving URL validation and metadata parsing into one shared, reviewed module. 9. Where supported, enforce an outbound network policy that limits the Skill to documented Douyin and Alibaba Cloud endpoints. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/install_deps.sh:11
Finding
Unpinned Dependencies Are Installed into User or System Python Environments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install_deps.sh:11-22` **Related Instruction**: `SKILL.md:24-28` **Vulnerability Type**: Unpinned third-party dependency installation and unsafe system-environment modification **Risk Level**: Medium ### Vulnerable Code ```bash if command -v uv &> /dev/null; then uv pip install --system requests dashscope 2>/dev/null \ || uv pip install requests dashscope elif command -v pip3 &> /dev/null; then pip3 install --user requests dashscope 2>/dev/null \ || pip3 install --break-system-packages requests dashscope 2>/dev/null \ || pip3 install requests dashscope elif command -v pip &> /dev/null; then pip install --user requests dashscope 2>/dev/null \ || pip install --break-system-packages requests dashscope 2>/dev/null \ || pip install requests dashscope else ``` ### Technical Analysis The installer requests `requests` and `dashscope` without exact versions or package hashes. Each installation can therefore resolve to different package artifacts over time. A compromised upstream release, account takeover, repository compromise, or future malicious dependency could execute package installation logic and runtime code with the invoking user's privileges. The installer also attempts `uv pip install --system` and falls back to `pip --break-system-packages`. These modes can modify the host's shared Python environment rather than an isolated environment belonging only to the Skill. This exceeds the minimum privilege needed to run two Python dependencies and can overwrite or conflict with packages used by other applications. Redirecting installation errors to `/dev/null` also obscures useful security and compatibility information, making it harder for users to understand which privileged fallback was selected. ### Attack Path 1. A user follows the documented setup procedure and runs `bash scripts/install_deps.sh`. 2. The package manager resolves mutable, unpinned ver ...[truncated 1446 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create a dedicated virtual environment for the Skill instead of installing into the user or system Python environment. 2. Pin exact reviewed versions of all direct dependencies. 3. Generate a lock file that includes transitive dependencies. 4. Record and enforce cryptographic hashes, for example by using `pip install --require-hashes -r requirements.txt`. 5. Remove the `--system` and `--break-system-packages` installation fallbacks. 6. Fail safely with a clear message if an isolated installation cannot be created. 7. Avoid suppressing package-manager errors so users can review installation failures and selected sources. 8. Explicitly configure and document the trusted package index, and require TLS certificate verification. 9. Periodically review and update locked dependencies after vulnerability and provenance checks. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This finding includes a real security issue: the skill documents access to `DASHSCOPE_API_KEY` and outbound calls to Douyin and Alibaba Cloud, yet no explicit permissions/tool scope are declared. Even if the 'download not implemented' portion is likely a false positive, the undeclared secret and network usage can lead to unreviewed data exfiltration or policy bypass in environments that rely on manifest-declared capabilities.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This finding includes a real security issue: the skill documents access to `DASHSCOPE_API_KEY` and outbound calls to Douyin and Alibaba Cloud, yet no explicit permissions/tool scope are declared. Even if the 'download not implemented' portion is likely a false positive, the undeclared secret and network usage can lead to unreviewed data exfiltration or policy bypass in environments that rely on manifest-declared capabilities.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This finding includes a real security issue: the skill documents access to `DASHSCOPE_API_KEY` and outbound calls to Douyin and Alibaba Cloud, yet no explicit permissions/tool scope are declared. Even if the 'download not implemented' portion is likely a false positive, the undeclared secret and network usage can lead to unreviewed data exfiltration or policy bypass in environments that rely on manifest-declared capabilities.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This finding includes a real security issue: the skill documents access to `DASHSCOPE_API_KEY` and outbound calls to Douyin and Alibaba Cloud, yet no explicit permissions/tool scope are declared. Even if the 'download not implemented' portion is likely a false positive, the undeclared secret and network usage can lead to unreviewed data exfiltration or policy bypass in environments that rely on manifest-declared capabilities.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This finding includes a real security issue: the skill documents access to `DASHSCOPE_API_KEY` and outbound calls to Douyin and Alibaba Cloud, yet no explicit permissions/tool scope are declared. Even if the 'download not implemented' portion is likely a false positive, the undeclared secret and network usage can lead to unreviewed data exfiltration or policy bypass in environments that rely on manifest-declared capabilities.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This finding includes a real security issue: the skill documents access to `DASHSCOPE_API_KEY` and outbound calls to Douyin and Alibaba Cloud, yet no explicit permissions/tool scope are declared. Even if the 'download not implemented' portion is likely a false positive, the undeclared secret and network usage can lead to unreviewed data exfiltration or policy bypass in environments that rely on manifest-declared capabilities.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill declares external network use and environment variable access in metadata (`requires.env`, external endpoints, and API-key-driven transcription) but does not declare an explicit tool scope such as permissions or allowed tools. This creates a transparency and policy-enforcement gap: an orchestrator or reviewer may not realize the skill can access secrets and send user data to third parties.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The skill description includes broad triggers such as 'use when user shares a Douyin link' or 'needs to extract text from Chinese short videos,' which could cause the agent to invoke a networked, file-writing, or API-consuming workflow in situations where the user did not explicitly request those actions. In a skill that can contact third parties and consume an API key, over-broad activation increases the risk of unintended data disclosure, surprise downloads, or unnecessary paid API usage.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The manifest explicitly advertises speech-to-text extraction and watermark-free video downloading but does not warn users that shared Douyin links, video content, and extracted audio/transcripts may be sent over the network to third-party services such as Alibaba Cloud Bailian ASR. This creates a real privacy and transparency issue because users may submit videos containing personal, copyrighted, or otherwise sensitive material without understanding that external processing and content retrieval occur.

Tainted flow: 'page_url' from requests.get (line 47, network input) → requests.get (network output)

Medium
Category
Data Flow
Content
video_id = share_response.url.split("?")[0].strip("/").split("/")[-1]
    page_url = f'https://www.iesdouyin.com/share/video/{video_id}'

    response = requests.get(page_url, headers=HEADERS, timeout=15)
    response.raise_for_status()

    pattern = re.compile(
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Tainted flow: 'page_url' from requests.get (line 52, network input) → requests.get (network output)

Medium
Category
Data Flow
Content
video_id = share_response.url.split("?")[0].strip("/").split("/")[-1]
    page_url = f'https://www.iesdouyin.com/share/video/{video_id}'

    response = requests.get(page_url, headers=HEADERS, timeout=15)
    response.raise_for_status()

    pattern = re.compile(
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Tainted flow: 'page_url' from requests.get (line 45, network input) → requests.get (network output)

Medium
Category
Data Flow
Content
video_id = share_response.url.split("?")[0].strip("/").split("/")[-1]
    page_url = f'https://www.iesdouyin.com/share/video/{video_id}'

    response = requests.get(page_url, headers=HEADERS, timeout=15)
    response.raise_for_status()

    pattern = re.compile(
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Static analysis

No suspicious patterns detected.