Back to skill

Security audit

douyin-video-distiller

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent video-distillation purpose, but it can upload whole media files and the NVIDIA API bearer token to a user-configurable endpoint, so it should be reviewed before installation.

Install only if you are comfortable with selected videos or images being sent to NVIDIA or to any endpoint configured by the environment. Before using it, verify NVIDIA_ENDPOINT is unset or restricted to the intended HTTPS NVIDIA host, avoid private or regulated media unless you have explicit approval to upload it, and treat the non-upload promise for sensitive content as unenforced by the bundled script.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/analyze.rb:76
Finding
Arbitrary API Endpoint Override Exposes Media and Bearer Credentials<![CDATA[ ## Vulnerability Details **File Location**: `scripts/analyze.rb:76-104` **Vulnerability Type**: Unrestricted outbound destination and optional plaintext transport **Risk Level**: High ### Vulnerable Code ```ruby endpoint = URI(ENV.fetch('NVIDIA_ENDPOINT', DEFAULT_ENDPOINT)) model = ENV.fetch('NVIDIA_MODEL', DEFAULT_MODEL) encoded = Base64.strict_encode64(File.binread(input_path)) content = [{ type: 'text', text: instruction }] if mime.start_with?('video/') # NVIDIA 的 Omni 端点使用视频块时通常要求 video_url;如官方页面指定了别的字段,可通过 NVIDIA_VIDEO_CONTENT_TYPE 覆盖。 video_type = ENV.fetch('NVIDIA_VIDEO_CONTENT_TYPE', 'video_url') content << if video_type == 'video_url' { type: 'video_url', video_url: { url: "data:#{mime};base64,#{encoded}" } } else { type: video_type, video: "data:#{mime};base64,#{encoded}" } end else content << { type: 'image_url', image_url: { url: "data:#{mime};base64,#{encoded}" } } end payload = { model: model, messages: [{ role: 'user', content: content }], max_tokens: Integer(ENV.fetch('NVIDIA_MAX_TOKENS', '65536')), reasoning_budget: Integer(ENV.fetch('NVIDIA_REASONING_BUDGET', '16384')), stream: false, temperature: Float(ENV.fetch('NVIDIA_TEMPERATURE', '0.6')), top_p: Float(ENV.fetch('NVIDIA_TOP_P', '0.95')) } request = Net::HTTP::Post.new(endpoint) request['Authorization'] = "Bearer #{api_key}" request['Content-Type'] = 'application/json' request.body = JSON.generate(payload) http = Net::HTTP.new(endpoint.host, endpoint.port) http.use_ssl = endpoint.scheme == 'https' ``` ### Technical Analysis The `NVIDIA_ENDPOINT` environment variable accepts an arbitrary URI without validating its scheme, hostname, port, or origin. The script subsequently sends the NVIDIA bearer credential, user instruction, and complete Base64-encoded media file to that URI. TLS is enabled only when the supplied scheme is exactly `https`. A value using `http` is accepted and causes the credential and media to be transmitted without transport ...[truncated 1511 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `NVIDIA_ENDPOINT` configurability if custom endpoints are not essential. 2. If configurability is required, enforce an allowlist of approved HTTPS hosts and ports: - Require `endpoint.scheme == "https"`. - Require the expected NVIDIA hostname, such as `integrate.api.nvidia.com`. - Reject embedded user information, unexpected ports, fragments, and malformed paths. 3. Do not send the bearer credential to a host other than the approved API origin. 4. If redirects are added later, reject cross-origin redirects and never forward authorization headers to redirected hosts. 5. Consider separating endpoint-specific credentials so one provider's credential cannot be sent to another provider. 6. Document the exact external recipient and notify the user before uploading the media. 7. Add automated tests confirming that HTTP URLs, loopback addresses, private network addresses, and unapproved domains are rejected. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/analyze.rb:78
Finding
Declared Sensitive-Content Non-Upload Policy Is Not Enforced<![CDATA[ ## Vulnerability Details **File Location**: `scripts/analyze.rb:78-101` **Related Policy Location**: `SKILL.md:81` **Vulnerability Type**: Unconditional third-party upload of potentially sensitive media **Risk Level**: Medium ### Vulnerable Code The Skill documentation states: ```markdown - 内容含个人隐私、健康、财务、密码、Cookie、API Key 或身份凭据:不上传、不输出、不写入公开 Wiki。 ``` The implementation nevertheless reads and uploads every accepted file without a consent or sensitivity gate: ```ruby encoded = Base64.strict_encode64(File.binread(input_path)) content = [{ type: 'text', text: instruction }] if mime.start_with?('video/') # NVIDIA 的 Omni 端点使用视频块时通常要求 video_url;如官方页面指定了别的字段,可通过 NVIDIA_VIDEO_CONTENT_TYPE 覆盖。 video_type = ENV.fetch('NVIDIA_VIDEO_CONTENT_TYPE', 'video_url') content << if video_type == 'video_url' { type: 'video_url', video_url: { url: "data:#{mime};base64,#{encoded}" } } else { type: video_type, video: "data:#{mime};base64,#{encoded}" } end else content << { type: 'image_url', image_url: { url: "data:#{mime};base64,#{encoded}" } } end payload = { model: model, messages: [{ role: 'user', content: content }], max_tokens: Integer(ENV.fetch('NVIDIA_MAX_TOKENS', '65536')), reasoning_budget: Integer(ENV.fetch('NVIDIA_REASONING_BUDGET', '16384')), stream: false, temperature: Float(ENV.fetch('NVIDIA_TEMPERATURE', '0.6')), top_p: Float(ENV.fetch('NVIDIA_TOP_P', '0.95')) } request = Net::HTTP::Post.new(endpoint) request['Authorization'] = "Bearer #{api_key}" request['Content-Type'] = 'application/json' request.body = JSON.generate(payload) ``` ### Technical Analysis Remote transfer to a vision model is consistent with the declared analysis functionality. However, the documentation explicitly promises that media containing personal, health, financial, password, cookie, API-key, or identity information will not be uploaded. The script has no pre-upload consent prompt, sensitivity declaration, local inspection, redaction step, o ...[truncated 1505 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require explicit informed consent before any media is uploaded to a third-party service. 2. Clearly disclose: - That the entire file will be transferred. - The intended API provider and endpoint. - That visible and audible sensitive information may be included. 3. Ask the user to confirm that the input does not contain prohibited sensitive content before invoking the script. 4. For stronger enforcement, provide a local-only preprocessing option that can detect or redact sensitive frames, text, audio, and metadata before remote transfer. 5. Allow users to review extracted frames, transcript data, or redacted output before upload. 6. Remove or qualify the absolute non-upload promise in `SKILL.md` unless the implementation can reliably enforce it. 7. Add a command-line confirmation flag, such as `--allow-remote-upload`, and fail closed when it is absent. 8. Log only transfer status and file size; never log the media payload, API key, or sensitive content. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
描述强调的是面向抖音短视频的知识蒸馏场景,但代码实际实现的是一个通用文件分析脚本。它接受本地图片或视频路径和任意指令,将内容发送给 NVIDIA 模型处理,因此可用于 OCR、图片理解、一般视频总结等多种用途。与声明相比,最明显的不一致有两点:一是代码不支持抖音链接抓取/解析,只能处理本地文件;二是它没有实现专门的“蒸馏成知识卡片/时间线/证据/第二大脑资料”的固定工作流,只是把用户指令原样转发给模型。虽然用户可以手动要求模型总结视频,这与声明部分重叠,但整体能力范围和接口形式都比声明更通用且存在关键缺口,因此应判定为不匹配。

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill declares no explicit tool scope or allowed-tools despite instructing the agent to perform network-enabled actions such as downloading Douyin content and calling external APIs. This is dangerous because it expands the agent’s effective capabilities without clear policy boundaries, increasing the chance of unauthorized network access, unintended data egress, or misuse of ambient credentials.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The trigger description contains broad natural-language examples like turning a video into searchable knowledge, which can overlap with ordinary conversation and cause accidental invocation. This is dangerous because misfires may cause the agent to initiate downloads, analyze local media, or process sensitive content when the user did not intend to run this higher-privilege workflow.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The script base64-encodes the full local image/video and sends it, along with the user’s instruction, to a third-party NVIDIA API endpoint. For a video-distillation skill, inputs are likely to contain personal, confidential, or regulated data, and the script provides no explicit consent prompt, privacy warning, or data-minimization controls before transfer. This is dangerous because users may assume local-only processing and unintentionally disclose sensitive content to an external service.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
This JSON file contains user-facing prompt and output expectations exclusively in Chinese, which effectively constrains the skill to a specific language without indicating user choice or explicit locale scoping. Under the policy, forced language behavior without opt-in can be a natural-language policy violation.

Missing User Warnings

Low
Confidence
76% confidence
Finding
The code reads an API key from the environment and uses it for outbound authentication. Although this is expected for an API client, there is no explicit comment or user-facing notice clarifying that the script depends on and will use a credential from the environment.

Natural-Language Policy Violations

Low
Confidence
87% confidence
Finding
This markdown file contains user-facing natural language that implicitly forces a specific language, but it does not mention any user opt-in, bilingual support, or justified region-specific constraint. Under the language/locale policy rule, a fixed language can be a policy issue when no choice or rationale is provided.

Static analysis

No suspicious patterns detected.