Back to skill

Security audit

video2text-ai

Security checks for vulnerabilities and agentic risk

Overview

This video transcription skill is purpose-aligned overall, but it has under-scoped network and upload behavior that could expose sensitive media or private-network content.

Review before installing. Only use this with videos you are allowed to send to GuaiKei and its storage provider, avoid sensitive meetings or regulated data unless you trust the service terms, and do not give it internal, localhost, metadata-service, or private-network URLs. The publisher should add strict public-domain/IP filtering, upload-destination allowlisting, explicit upload consent/disclosure, size limits, and verifiable retention documentation.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/utils/validator.js:3
Finding
Unrestricted URL Fetching Enables Private-Network Data Exfiltration<![CDATA[ ## Vulnerability Details **File Location**: `scripts/utils/validator.js:3-7`, `scripts/utils/download.js:317-331`, `scripts/video2text/index.js:96-125`, `scripts/video2text/index.js:140-146` **Vulnerability Type**: Server-Side Request Forgery with subsequent external upload **Risk Level**: High ### Vulnerable Code ```js function isUrl(url) { try { const parsedUrl = new URL(url); return parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:"; } catch (_) { return false; } } ``` ```js const getRequest = (url, options) => { if (retryTimeout) { clearTimeout(retryTimeout); retryTimeout = null; } const req = this.__protocol.request(options, (response) => { if (this.__isRequireRedirect(response)) { redirectCount++; if (redirectCount > this.__opts.maxRedirects) { const err = new Error("Too many redirects"); this.__setState(this.__states.FAILED); this.emit("error", err); return reject(err); } const redirectedURL = /^https?:\/\//.test(response.headers.location) ? response.headers.location : new URL(response.headers.location, url).href; this.emit("redirected", redirectedURL, url); return getRequest(redirectedURL, getReqOptions(redirectedURL)); } ``` ```js const downloadResult = await helper.download(file, filepath); let tempFilePath = downloadResult?.filePath || ""; if (tempFilePath === "") { utils.printError("下载失败: 未返回文件路径"); process.exit(1); } ``` ```js const presignedUrl = await video.getPresignedUrl(tokenValue, file); if (!presignedUrl || !presignedUrl?.url || presignedUrl.url === "") { throw new Error("获取预签名URL失败,请反馈给开发者"); } utils.printInfo("上传文件到安全空间..."); await upload.uploadFileToOSS(file, presignedUrl.url, presignedUrl.headers); ``` ### Technical Analysis The URL validator checks only whether the scheme is HTTP or HTTPS. It does not reject loopback addresses, RFC 1918 private addresses, link-local addresses ...[truncated 1824 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Resolve the hostname before connecting and reject every address in loopback, private, link-local, multicast, reserved, and unspecified ranges. 2. Explicitly block cloud metadata destinations, including `169.254.169.254` and IPv6 link-local equivalents. 3. Repeat destination validation after every redirect and after every DNS resolution. 4. Consider allowing only explicitly supported public video domains. 5. Protect against DNS rebinding by connecting to a previously validated address while preserving the expected TLS hostname. 6. Reject URLs containing embedded credentials or unexpected ports. 7. Do not upload downloaded content until its media type and file structure have been validated. 8. Run the downloader in a sandbox with restricted outbound network access so it cannot reach private networks. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/utils/helper.js:27
Finding
Unbounded Remote Downloads Permit Resource Exhaustion<![CDATA[ ## Vulnerability Details **File Location**: `scripts/utils/helper.js:27-38`, `scripts/utils/download.js:547-549` **Vulnerability Type**: Unrestricted download size and duration **Risk Level**: Medium ### Vulnerable Code ```js async function download(url, path) { return new Promise((resolve, reject) => { const options = { retry: { maxRetries: constants.CREATE_MAX_ATTEMPTS, delay: constants.RETRY_INTERVAL, }, override: { skip: true, skipSmaller: true }, }; let progressLog = ""; const dl = new Downloader(url, path, options); ``` ```js if (!this.__filePath || this.__downloaded === 0) { this.__fileStream = fs.createWriteStream(this.__filePath, {}); } else { this.__fileStream = fs.createWriteStream(this.__filePath, { flags: "a" }); } ``` ### Technical Analysis The downloader does not configure or enforce: - A maximum response size. - A maximum total download duration. - A minimum available-disk threshold. - A media-type allowlist. - A streaming byte counter that aborts after a safe threshold. - Reliable cleanup of partial files after failure. A remote server can omit `Content-Length`, provide a deceptive value, send an extremely large body, or keep streaming content indefinitely. The response is written directly to disk. The configured retry behavior can amplify resource consumption when the attacker repeatedly terminates or stalls requests. ### Attack Path 1. An attacker supplies a URL controlled by the attacker. 2. The server returns a very large response, an endless chunked response, or repeatedly interrupted data. 3. The downloader streams the response into the project temporary directory. 4. No byte limit or total deadline terminates the transfer. 5. Storage, bandwidth, file descriptors, or execution time are exhausted. 6. Repeated invocations or retries amplify the impact. ### Impact Assessment Exploitation can cause denial of service affecting the account or host running the Skill. ...[truncated 398 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define a strict maximum supported video size. 2. Reject responses whose declared `Content-Length` exceeds that limit. 3. Count bytes during streaming and abort immediately if the actual response exceeds the limit. 4. Configure separate connection, inactivity, and total-transfer deadlines. 5. Check available disk space before starting and periodically during large downloads. 6. Restrict accepted content types to documented video or audio formats. 7. Validate the downloaded file signature rather than relying only on headers or extensions. 8. Delete partial files whenever a request fails, times out, or exceeds a limit. 9. Limit retry attempts and ensure retries do not retain or append untrusted partial content incorrectly. 10. Apply per-user and global concurrency and bandwidth limits. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/utils/upload.js:10
Finding
API-Controlled Presigned URL Can Redirect Full File Uploads to Arbitrary HTTPS Hosts<![CDATA[ ## Vulnerability Details **File Location**: `scripts/utils/upload.js:10-43`, `scripts/video2text/index.js:140-146` **Vulnerability Type**: Unvalidated external upload destination **Risk Level**: Medium ### Vulnerable Code ```js async function uploadFileToOSS(filename, presignedUrl, headers) { const url = new URL(presignedUrl); if (url.protocol !== "https:") { throw new Error("上传URL必须是HTTPS协议"); } return new Promise((resolve, reject) => { const fileStats = fs.statSync(filename); const totalSize = fileStats.size; let uploadedSize = 0; let settled = false; const fileStream = fs.createReadStream(filename); // 复制预签名 headers,并补充 OSS PUT 必需字段 const uploadHeaders = Object.assign({}, headers); // 关键修复:明确 Content-Length,否则 Node 对流式 body 默认使用 chunked // Transfer-Encoding,阿里云 OSS 预签名 PUT 通常会拒绝而返回 400/403 uploadHeaders["Content-Length"] = String(totalSize); if (!uploadHeaders["Content-Type"]) { uploadHeaders["Content-Type"] = "application/octet-stream"; } const options = { host: url.hostname, path: url.pathname + url.search, method: "PUT", headers: uploadHeaders, }; const req = https.request( { ...options, timeout: constants.REQUEST_TIMEOUT }, ``` ```js const presignedUrl = await video.getPresignedUrl(tokenValue, file); if (!presignedUrl || !presignedUrl?.url || presignedUrl.url === "") { throw new Error("获取预签名URL失败,请反馈给开发者"); } utils.printInfo("上传文件到安全空间..."); await upload.uploadFileToOSS(file, presignedUrl.url, presignedUrl.headers); ``` ### Technical Analysis The upload destination and upload headers are supplied by the remote API. The client verifies only that the URL uses HTTPS. It does not enforce an allowlist of expected object-storage domains, reject IP-literal destinations, restrict ports, or validate the returned headers. As a result, any HTTPS hostname selected by the API response receives the entire selected local file. This behavior ...[truncated 1270 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Maintain a strict allowlist of expected object-storage hostname suffixes. 2. Reject IP-literal hosts, localhost, private addresses, unexpected ports, and malformed hostnames. 3. Validate DNS resolution before connecting and protect against DNS rebinding. 4. Permit only the exact headers required for the documented storage provider. 5. Reject server-supplied authorization, proxy, forwarding, host, and other unexpected headers. 6. Bind presigned responses to the requested task and filename where supported. 7. Display or document the actual storage provider and upload domains. 8. Require explicit user consent before uploading sensitive files to a third-party service. 9. Consider using a fixed service-side upload proxy if it can be operated with appropriate privacy and size controls. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/api/video.js:11
Finding
Absolute Local File Paths Are Disclosed to the Remote API<![CDATA[ ## Vulnerability Details **File Location**: `scripts/api/video.js:11-31`, `scripts/video2text/index.js:140` **Vulnerability Type**: Unnecessary local environment information disclosure **Risk Level**: Low ### Vulnerable Code ```js async function getPresignedUrl(token, filename) { if (!token || typeof token !== "string") { throw new Error("token 必须是非空字符串"); } if (!filename || typeof filename !== "string") { throw new Error("filename 必须是非空字符串"); } const data = { file: filename }; const response = await requestApi( "/api/video/presign", token, data, constants.CREATE_MAX_ATTEMPTS, "预上传", ); if (response.data) { return response.data; } else { throw new Error("获取预签名上传信息失败"); } } ``` ```js const presignedUrl = await video.getPresignedUrl(tokenValue, file); ``` ### Technical Analysis The complete local path is placed in the JSON request sent to the presign API. For local inputs, this can expose operating-system usernames, home-directory layouts, project names, customer names, case identifiers, mount points, and other contextual information. A presign operation generally requires only a sanitized basename, file extension, content type, size, or generated object key. Sending the absolute path exceeds that requirement. ### Attack Path 1. A user invokes the Skill with an absolute local path. 2. The path is retained in the `file` variable. 3. `getPresignedUrl` serializes the entire value as the `file` property. 4. `requestApi` sends it to `www.guaikei.com`. 5. The remote service receives and may log the local filesystem path. ### Impact Assessment The remote service can learn details about the local environment and user identity. This disclosure does not directly grant filesystem access, but the information may assist social engineering, host profiling, targeted attacks, or correlation of sensitive projects and users. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the absolute path with `path.basename(filename)` before constructing the request. 2. Prefer a generated opaque object name instead of any user-controlled local name. 3. Send only the minimum metadata required by the presign endpoint, such as: - Sanitized extension. - File size. - Validated media type. - Random task identifier. 4. Remove path separators and control characters from any retained filename. 5. Document exactly which metadata is transmitted and how long the service retains it. 6. Avoid logging local paths on the server unless operationally necessary, and apply appropriate retention controls. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
Findings (25)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill heavily emphasizes token acquisition, commercial contact details, and trust claims, while the visible file does not provide verifiable implementation detail for actual transcription or content generation. In an agent ecosystem, that kind of gap can mislead users into sending files or credentials to a remote third party without sufficient technical transparency, increasing supply-chain and data-exfiltration concerns.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill heavily emphasizes token acquisition, commercial contact details, and trust claims, while the visible file does not provide verifiable implementation detail for actual transcription or content generation. In an agent ecosystem, that kind of gap can mislead users into sending files or credentials to a remote third party without sufficient technical transparency, increasing supply-chain and data-exfiltration concerns.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill heavily emphasizes token acquisition, commercial contact details, and trust claims, while the visible file does not provide verifiable implementation detail for actual transcription or content generation. In an agent ecosystem, that kind of gap can mislead users into sending files or credentials to a remote third party without sufficient technical transparency, increasing supply-chain and data-exfiltration concerns.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README encourages users to submit local video files or public video links and mentions cloud processing, but it does not clearly warn at the point of use that user-provided content is transmitted to a third-party remote service for processing. In a skill handling potentially sensitive recordings, this omission can mislead users about data exposure and create privacy and compliance risk, especially for meetings, interviews, or internal course content.

Whitespace Padding

Medium
Category
Prompt Injection
Content
4. 同时传入文件路径与任务ID,优先执行 `--id`,忽略 `--file`
5. 无自定义 prompt 时,默认完整转录视频全部文字

| 用户自然语言指令                                         | 自动生成命令                                                                                                |
| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| 视频提取 https://example.com/video.mp4 中的文字          | `node scripts/video2text/index.js --file "https://example.com/video.mp4"`                                   |
| 把本地 /path/to/your/video.mp4 改成小红书风格的文案      | `node scripts/video2text/index.js --file "/path/to/your/video.mp4" --prompt "改写成小红书风格的文案"`       |
Confidence
70% confidence
Finding
Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The opening description does not immediately warn that local files or supplied URLs are uploaded to a remote service for processing. That omission undermines informed consent and can cause users to disclose sensitive media under the assumption that processing is local or purely in-tool.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The trigger criteria include broad requests like summarization, audience analysis, meeting notes, and content rewriting, which can match ordinary conversation even when no video processing is needed. In an agent setting this can cause over-invocation of a remote-upload skill, leading to unnecessary data transfer of local files or URLs and avoidable privacy exposure.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The primary user-facing description is entirely in Chinese and emphasizes Chinese-platform use cases such as 抖音 and 小红书, with no indication that users can choose another language or that the locale restriction is intentional. This can constitute a language/locale policy issue because it implicitly fixes the skill's interaction context to a specific language without opt-in.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This file contains natural-language comments and CLI-facing messages exclusively in Chinese, including errors and help output. That enforces a specific language/locale for users of the skill without any visible opt-in or alternative, which matches the language/locale policy violation category.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The file’s natural-language content, including the function doc comment and user-facing messages, is written exclusively in Chinese. Under the policy, forcing a specific language without user opt-in or documented regional justification is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The file emits user-facing strings exclusively in Chinese, including operational and support guidance, and does not provide any user opt-in or fallback language. Under the policy, forcing a specific language without user choice is a natural-language locale violation unless the constraint is explicitly justified.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The user-facing messages shown when the token is invalid are entirely in Chinese, including warnings, instructions, and promotional text. This imposes a specific language on users without offering a language/locale choice or documenting that the skill is intended only for a Chinese-speaking context.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The comment makes strong privacy and data-handling guarantees ('not leaked,' 'not retained,' 'automatically deleted') that are not enforced anywhere in this code path. In a video-to-text skill, uploaded files may contain sensitive personal, business, or copyrighted content, so relying on unenforced promises can mislead users and create a real privacy/compliance gap if the backend or storage lifecycle is misconfigured.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The banner string is hard-coded in Chinese ("视频文案智能提取助手"), which indicates a fixed language choice in user-facing output. There is no visible opt-in, fallback, or explanation that this skill is intentionally limited to a Chinese-speaking or region-specific audience.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The script uploads user-supplied local video files and downloaded remote videos to a remote service after obtaining a presigned URL, but it does not present an explicit consent prompt or clear warning at the point of transfer. Because videos often contain sensitive audio, faces, screens, or meetings, silent transmission to a third-party backend can cause unintended data disclosure, especially when users may assume processing is local.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The skill description is overly broad, covering generic summarization, copywriting, translation, and content-analysis tasks in addition to video transcription. In an agentic environment, this can cause the skill to activate for requests better handled by other tools, leading to unintended data transfer of local files or remote URLs to a third-party service and expanding the attack surface for prompt-routing abuse.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The activation guidance uses broad categories such as '看懂视频内容' and '基于视频内容产出新文案' without sufficiently strict gating. This increases the chance of accidental invocation on ambiguous user requests, which may result in unnecessary external processing of user-supplied media or URLs and misrouting away from safer or more appropriate skills.

Whitespace Padding

Medium
Category
Prompt Injection
Content
## 7. 🗣️ 自然语言 → 命令(照这张表转)

| 用户说的话                                           | 就执行这条命令                                                                                              |
| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| 提取 https://example.com/video.mp4 里的文字          | `node scripts/video2text/index.js --file "https://example.com/video.mp4"`                                   |
| 总结这个视频的核心观点 https://example.com/video.mp4 | `node scripts/video2text/index.js --file "https://example.com/video.mp4" --prompt "总结这个视频的核心观点"` |
Confidence
70% confidence
Finding
Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Whitespace Padding

Medium
Category
Prompt Injection
Content
## 7. 🗣️ 自然语言 → 命令(照这张表转)

| 用户说的话                                           | 就执行这条命令                                                                                              |
| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| 提取 https://example.com/video.mp4 里的文字          | `node scripts/video2text/index.js --file "https://example.com/video.mp4"`                                   |
| 总结这个视频的核心观点 https://example.com/video.mp4 | `node scripts/video2text/index.js --file "https://example.com/video.mp4" --prompt "总结这个视频的核心观点"` |
Confidence
70% confidence
Finding
Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Vague Triggers

Low
Confidence
84% confidence
Finding
As a manifest file, this description falls under vague-trigger review. The description lists many broad scenarios such as meeting notes, course breakdowns, live-stream review, and content creation, but does not define specific invocation phrases, scope boundaries, or negative examples, which could make activation overly broad in systems that rely on manifest text for routing.

Missing User Warnings

Low
Confidence
84% confidence
Finding
This function sends an API token and filename to a remote endpoint via requestApi, which is a safety-relevant network operation involving user and system data. Although the JSDoc describes the parameters, there is no visible confirmation prompt, user-facing warning, or explicit disclosure in the code that this data will be transmitted externally.

Missing User Warnings

Low
Confidence
85% confidence
Finding
The function posts the API token and a video URL to an external API to obtain an analysis task ID. This is a network operation involving potentially sensitive user content metadata, but the code provides no user-facing notice, confirmation, or explicit runtime disclosure about that transmission.

Missing User Warnings

Low
Confidence
83% confidence
Finding
This request sends the API token along with task ID and prompt content to a remote service for text generation. Because prompts may contain sensitive user instructions or data, the absence of any visible warning or disclosure in the code makes the behavior insufficiently transparent under the missing-user-warnings rule.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
User-facing descriptions, examples, and runtime guidance in this file are exclusively in Chinese. The policy calls for flagging language/locale constraints when a skill forces a specific language without opt-in or documented justification.

Static analysis

No suspicious patterns detected.