Back to skill

Security audit

guaikei-video2text-ai

Security checks for vulnerabilities and agentic risk

Overview

This skill is built for cloud video transcription, but it deserves review because selected media can be fetched from broad URLs and uploaded through under-scoped third-party destinations.

Install only if you are comfortable sending selected videos, prompts, the service token, and some filename/path metadata to GuaiKei and its cloud upload workflow. Avoid using untrusted, internal, or private-network URLs with this skill, and do not use it for sensitive media unless you have independently accepted the provider's retention, deletion, privacy, and billing terms.

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/utils/validator.js:3
Finding
Arbitrary URL Fetching Enables SSRF and External Data Relay<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/utils/validator.js:3-7` - `scripts/video2text/index.js:96-108` - `scripts/utils/download.js:323-331` - `scripts/video2text/index.js:140-146` **Vulnerability Type**: Server-Side Request Forgery (SSRF) with response exfiltration **Risk Level**: High ### Vulnerable Code ```js // scripts/utils/validator.js:3-7 function isUrl(url) { try { const parsedUrl = new URL(url); return parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:"; } catch (_) { return false; } } ``` ```js // scripts/video2text/index.js:96-108 if (validator.isUrl(file)) { const filepath = utils.downloadPath(); try { await fs.promises.mkdir(filepath, { recursive: true }); } catch (error) { utils.printError("临时下载目录创建失败: " + (error.message || String(error))); process.exit(1); } try { const downloadResult = await helper.download(file, filepath); ``` ```js // scripts/utils/download.js:323-331 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 // scripts/video2text/index.js:140-146 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 verifies only that the input uses the `http:` or `https:` scheme. It does not resolve or ...[truncated 2389 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Accept HTTPS URLs only unless plain HTTP is explicitly required and approved. 2. Resolve the destination hostname before connecting and reject every address in loopback, private, link-local, multicast, reserved, and cloud-metadata ranges for both IPv4 and IPv6. 3. Apply the same validation to every redirect target before following it. 4. Prevent HTTPS-to-HTTP redirect downgrades. 5. Consider allowlisting supported video-hosting domains rather than accepting arbitrary hosts. 6. Restrict destination ports to expected web ports. 7. Protect against DNS rebinding by ensuring the validated address is the address used for the connection. 8. Enforce maximum response size and download duration before writing the complete response to disk. 9. Verify the response MIME type and file signature against an allowlist of supported video formats before upload. 10. Abort and delete the temporary file if any validation fails. ]]>

other

Note
Location
scripts/api/video.js:11
Finding
Full Local File Paths Are Disclosed to the External API<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/video2text/index.js:140` - `scripts/api/video.js:11-23` **Vulnerability Type**: Local filesystem metadata disclosure **Risk Level**: Low ### Vulnerable Code ```js // scripts/video2text/index.js:140 const presignedUrl = await video.getPresignedUrl(tokenValue, file); ``` ```js // scripts/api/video.js:11-23 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, ``` ### Technical Analysis The complete value of the local `file` argument is sent to the external presign API as the `file` JSON property. When the user supplies an absolute local path, the transmitted value can expose operating-system and directory metadata unrelated to the content required for transcription. For example, paths may reveal: - Local account names - Home-directory layouts - Project and customer names - Internal mount points - Confidential case or document identifiers - Organizational directory conventions A presign operation generally needs only a generated object name, sanitized basename, or validated file extension. Sending the complete path exceeds that requirement and conflicts with the documentation's minimal-data assertion. ### Attack Path 1. A user invokes the Skill with an absolute local path. 2. The path is assigned to the `file` variable. 3. `getPresignedUrl()` receives the complete path as `filename`. 4. The complete path is serialized into the API request body. 5. `www.guaikei.com` receives and may log or retain the local filesystem metadata. ### Impact Assessment The external service can learn sensitive environmental metadata about the machine and user running the Skill. This does not directly expose arbitr ...[truncated 237 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never send the complete local path to the remote API. 2. Generate an opaque random object name locally and send only that identifier. 3. If an original filename is required, use `path.basename(filename)` and sanitize it before transmission. 4. Allowlist supported extensions and derive the media type locally. 5. Remove user names, directory components, control characters, and application-specific metadata. 6. Update the privacy documentation to identify all metadata transmitted to remote services. 7. Establish server-side retention and logging controls for filename metadata. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/utils/upload.js:10
Finding
API-Controlled Upload Destination Is Not Host-Allowlisted<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/video2text/index.js:140-146` - `scripts/utils/upload.js:10-35` **Vulnerability Type**: Unrestricted externally supplied upload destination **Risk Level**: Medium ### Vulnerable Code ```js // scripts/video2text/index.js:140-146 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); ``` ```js // scripts/utils/upload.js:10-35 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, }; ``` ### Technical Analysis The presign API controls the upload URL and upload headers. The client validates only that the URL uses HTTPS; it does not verify that the hostname belongs to an approved object-storage provider or expected account. Consequently, a compromised, malicious, or misconfigured API response can direct a user-selected local file to any HTTPS server. The supplied headers are also forwarded without ...[truncated 1329 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Maintain an explicit allowlist of approved object-storage hostnames or tightly scoped hostname suffixes. 2. Verify hostname boundaries correctly; do not use unsafe substring or unanchored suffix checks. 3. Reject IP-literal destinations and hostnames resolving to private, loopback, link-local, reserved, or metadata addresses. 4. Validate that the URL path and signing parameters conform to the expected storage provider and account. 5. Allowlist only the headers required by the storage provider instead of forwarding the entire API-provided object. 6. Reject sensitive headers such as `Authorization`, cookies, proxy authorization, and unrelated custom credentials unless explicitly required. 7. Pin the expected storage region or account where operationally possible. 8. Log and abort unexpected upload destinations before opening the local file stream. 9. Update the Skill documentation to disclose the actual object-storage domains contacted during upload. ]]>
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 (20)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill claims to process video inputs but the finding indicates token validation, configuration checks, and marketing/contact prompts are part of the effective behavior. That mismatch is risky because it can steer users into out-of-band credential acquisition and trust decisions unrelated to the technical task, while obscuring what the code actually does with data and secrets.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill claims to process video inputs but the finding indicates token validation, configuration checks, and marketing/contact prompts are part of the effective behavior. That mismatch is risky because it can steer users into out-of-band credential acquisition and trust decisions unrelated to the technical task, while obscuring what the code actually does with data and secrets.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill claims to process video inputs but the finding indicates token validation, configuration checks, and marketing/contact prompts are part of the effective behavior. That mismatch is risky because it can steer users into out-of-band credential acquisition and trust decisions unrelated to the technical task, while obscuring what the code actually does with data and secrets.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill claims to process video inputs but the finding indicates token validation, configuration checks, and marketing/contact prompts are part of the effective behavior. That mismatch is risky because it can steer users into out-of-band credential acquisition and trust decisions unrelated to the technical task, while obscuring what the code actually does with data and secrets.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The entire README presents usage, instructions, support, and examples only in Chinese, including required onboarding and prompt examples, with no indication that other languages are supported or that the language choice is optional. This can violate a language/locale policy when a skill effectively requires a specific language without user opt-in.

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
90% confidence
Finding
The skill declares access to an environment variable (`GUAIKEI_API_TOKEN`) but does not define an explicit tool scope such as `permissions` or `allowed-tools`. In agent environments, missing scoping weakens least-privilege guarantees and can make secret access and execution boundaries ambiguous, especially for a skill that also promotes external network use and opaque backend processing.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The activation guidance is broad enough to match many common content-analysis and rewriting requests, which can cause the agent to invoke this skill in situations beyond strict video transcription. In context, that increases the chance of unnecessary external data transfer of user content to a third-party service and over-collection relative to user intent.

Whitespace Padding

Medium
Category
Prompt Injection
Content
当用户用自然语言下达指令时,按以下映射生成命令,保证识别与执行一致:

| 用户自然语言指令                                     | 生成的命令                                                                                                  |
| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| 提取 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

Medium
Confidence
87% confidence
Finding
The natural-language-to-command mapping uses permissive auto-invocation rules such as inferring `--id last` reuse and automatically embedding free-form prompts. This can lead to processing the wrong prior task, sending unintended content to the backend, or executing on stale context without explicit user confirmation.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
This file uses Chinese-only natural-language comments and user-facing error/status strings such as "token 必须是非空字符串" and labels like "预上传" and "视频文案". Per the policy, forcing a specific language without offering user choice or documenting a justified locale constraint is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This file hardcodes user-facing help text, warnings, and error messages in Chinese throughout the parser, such as parameter errors and usage/help output. That creates a language/locale constraint without offering the user a choice or documenting that the skill is intentionally region-specific.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This JavaScript file contains natural-language comments and all user-visible status/error messages exclusively in Chinese, such as the docstring and download progress messages. Under the policy rule, forcing a specific language without user opt-in or a documented regional justification is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The natural-language strings in thrown errors are hard-coded in Chinese, including user-directed remediation text. This enforces a specific language/locale without any opt-in or documented justification, which matches the language/locale policy violation criterion.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
This code constructs and sends an HTTPS POST request containing caller-provided JSON data and an authentication token header. While the function has validation and retry logging, there is no user-facing warning, confirmation, or explicit comment/docstring disclosing that data and credentials are transmitted over the network.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The file emits all user-facing status and warning messages exclusively in Chinese, including operational guidance and promotional text. This imposes a specific language on users without any opt-in, fallback, or indication that the skill is intended only for a Chinese-speaking or region-specific context.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The comment makes strong privacy and retention assurances about uploaded videos being used only for transcription and automatically deleted, but this file only performs an HTTPS upload and contains no mechanism to enforce, verify, or audit deletion or downstream-use restrictions. In a video-to-text skill handling potentially sensitive user media, such misleading claims can cause users or integrators to trust data handling guarantees that are not technically implemented.

Natural-Language Policy Violations

Low
Confidence
80% confidence
Finding
The skill description, examples, usage guidance, and support flow are entirely Chinese-centric, including platform-specific rewriting targets and Chinese-language acquisition instructions, with no indication that users may choose another language for interaction. Because the policy applies to natural-language constraints, this can be treated as a locale/language default imposed without explicit opt-in.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The natural-language comment is written entirely in Chinese and describes the skill behavior in that locale without offering any language or locale choice. Under the stated policy, forcing or assuming a specific language without user opt-in can be a policy violation.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
The banner string is hard-coded in Chinese, which indicates the skill presents itself in a specific language without any visible mechanism for user language selection. This is a natural-language policy concern because the file enforces a locale-specific user-facing message rather than offering a choice.

Static analysis

No suspicious patterns detected.