Back to skill

Security audit

guaikei-video-transcript-extractor

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it advertises, but it can upload arbitrary local files and fetch arbitrary web URLs with weaker limits and disclosure than users should expect.

Review before installing. Use this only with videos you intentionally want to send to the GuaiKei service and its storage provider. Do not let untrusted pages, prompts, or collaborators choose the --file path or URL. Avoid sensitive local paths, private/internal URLs, and very large remote files until the publisher adds explicit confirmation, media validation, host restrictions, size limits, and accurate destination disclosure.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/utils/validator.js:3
Finding
Unrestricted URL Fetching Enables SSRF and Internal Data Exfiltration<![CDATA[ ## Vulnerability Details **File Location**: `scripts/utils/validator.js:3-9`; related request and redirect handling in `scripts/video2text/index.js:101-109` and `scripts/utils/download.js:317-332, 464-494` **Vulnerability Type**: Server-Side Request Forgery through unrestricted URL downloading **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; } } ``` The accepted URL is subsequently downloaded: ```js if (validator.isUrl(file)) { const filepath = utils.downloadPath(); // ... const downloadResult = await helper.download(file, filepath); } ``` The downloader also follows redirects, including cross-host redirects: ```js 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)); ``` ### Technical Analysis URL validation checks only whether the scheme is HTTP or HTTPS. It does not reject: - Loopback addresses such as `127.0.0.1` and `::1` - Private network ranges - Link-local addresses - Cloud metadata services - Internal DNS names - Hostnames that resolve to prohibited addresses - Public URLs that redirect to internal resources Redirect targets are followed without repeating a network-boundary validation check. DNS resolution is also not pinned, leaving the implementation potentially exposed to DNS rebinding. After the response is downloaded, the entry point treats it as a video file and uploads it to remote object storage. This creates an exfiltration path rather than merely allowing blind SSRF. ### Attack Path 1. An attacker causes the Skill to receive an internal URL as the `--file` argument, or supplies a public URL that redirects to an internal endpoint. 2. `isUrl( ...[truncated 973 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Resolve the hostname before connecting and reject all loopback, private, link-local, multicast, unspecified, and reserved IP ranges for both IPv4 and IPv6. 2. Explicitly block cloud metadata destinations, including common link-local metadata addresses. 3. Repeat the full validation process after every redirect. 4. Restrict redirects to HTTPS and, where practical, to the same registrable domain. 5. Mitigate DNS rebinding by connecting only to the validated resolved address and verifying resolution throughout the request lifecycle. 6. Permit only expected media hosts or require explicit user approval for arbitrary hosts. 7. Validate response `Content-Type`, file signatures, and maximum size before upload. 8. Avoid automatically uploading downloaded content until it has passed media validation. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/utils/validator.js:11
Finding
Arbitrary Readable Local Files Can Be Uploaded to Remote Storage<![CDATA[ ## Vulnerability Details **File Location**: `scripts/utils/validator.js:11-18`; upload workflow in `scripts/video2text/index.js:125-145` **Vulnerability Type**: Insufficient restriction of local file access and upload scope **Risk Level**: High ### Vulnerable Code ```js function isFilePath(path) { try { const stats = fs.statSync(path); return stats.isFile(); } catch (_) { return false; } } ``` Any path that points to a readable regular file is subsequently uploaded: ```js if (!fs.existsSync(file)) { utils.printError("文件不存在: " + file); process.exit(1); } try { 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 local-path validator verifies only that the supplied path exists and is a regular file. It does not verify that the file: - Is a supported video or audio format - Is within a user-approved directory - Was explicitly selected or authorized by the user - Has an acceptable size - Has a media file signature consistent with its extension - Is not a sensitive configuration, credential, key, token, or system file The upload function uses `fs.createReadStream(filename)`, so access is limited only by the operating-system permissions of the Agent process. A misleading extension is unnecessary because no extension or content validation is performed. Although local video upload is part of the declared functionality, accepting every readable regular file exceeds the minimum access scope needed for video transcription. ### Attack Path 1. An attacker or untrusted instruction supplies the path of a sensitive local file through `--file`. 2. `isFilePath()` calls `fs.statSync()` and accepts the file because it is a regular file. 3. The program requests a ...[truncated 611 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict local files to explicitly approved directories or files selected through a trusted user-mediated workflow. 2. Resolve paths with `realpath()` and verify that the canonical path remains inside an allowed root. 3. Require explicit confirmation showing the canonical path, destination, and file size before uploading local data. 4. Allowlist supported media extensions and verify content using file signatures or a trusted media parser. 5. Reject symbolic links where they are not necessary, and revalidate the opened file to reduce time-of-check/time-of-use risks. 6. Define maximum file-size limits before opening or uploading a file. 7. Run the Skill under a least-privileged operating-system account with no access to unrelated credentials or user files. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/utils/helper.js:28
Finding
Unbounded Remote Downloads Can Exhaust Local Disk Space<![CDATA[ ## Vulnerability Details **File Location**: `scripts/utils/helper.js:28-37`; streaming write in `scripts/utils/download.js:510-557` **Vulnerability Type**: Unrestricted resource consumption **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); ``` The response is streamed directly to disk without enforcing a byte limit: ```js readable.on("data", (chunk) => this.__calculateStats(chunk.length)); this.__pipes.forEach((pipe) => { readable.pipe(pipe.stream, pipe.options); readable = pipe.stream; }); readable.pipe(this.__fileStream); readable.on("error", this.__onError(resolve, reject)); this.__fileStream.on("finish", this.__onFinished(resolve, reject)); this.__fileStream.on("error", this.__onError(resolve, reject)); ``` ### Technical Analysis The downloader does not define a maximum accepted `Content-Length`, streamed-byte threshold, media duration, free-space requirement, or download timeout in the helper configuration. A server may omit `Content-Length`, use chunked transfer encoding, report a false size, or continuously stream data. Because data is piped directly to a file, the process continues consuming disk space until the remote endpoint closes the connection, an external timeout occurs, or the filesystem becomes full. The 24-hour cleanup routine does not mitigate an active oversized or endless download. Retry behavior may also repeat resource consumption following network failures. ### Attack Path 1. An attacker supplies a URL controlled by an endpoint that returns an extremely large or continuous response. 2. URL validation accepts the endpoint. 3. The downloader creates a file in the proje ...[truncated 610 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define a strict configurable maximum download size suitable for the service. 2. Reject responses whose declared `Content-Length` exceeds that limit. 3. Count actual streamed bytes and immediately destroy the response and file stream when the limit is exceeded. 4. Apply connection, response, idle, and total-operation timeouts. 5. Check available disk space and reserve a safety margin before starting a download. 6. Validate media type and file signatures early rather than downloading arbitrary response bodies in full. 7. Store temporary data in a quota-controlled, process-specific directory. 8. Remove partial files reliably on size-limit, timeout, and validation failures. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/utils/upload.js:10
Finding
API-Controlled Upload Destination Is Not Restricted to Trusted Storage Hosts<![CDATA[ ## Vulnerability Details **File Location**: `scripts/utils/upload.js:10-15, 37-44` **Vulnerability Type**: Unrestricted server-provided 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) => { ``` The parsed hostname and API-provided headers are then used directly: ```js const options = { host: url.hostname, path: url.pathname + url.search, method: "PUT", headers: uploadHeaders, }; const req = https.request( { ...options, timeout: constants.REQUEST_TIMEOUT }, ``` ### Technical Analysis The only destination security check is that the presigned URL uses HTTPS. The hostname, port, path, query string, and most request headers originate from the remote API response and are trusted without validation. This behavior also conflicts with the documentation's statement that the Skill only sends HTTPS requests to `www.guaikei.com`; object-storage uploads necessarily contact another destination unless storage is hosted under that domain. If the API is compromised, misconfigured, or manipulated upstream, it can return a presigned URL for any HTTPS host. The Skill will then upload the complete user-selected file to that destination. HTTPS protects transport confidentiality but does not establish that the destination is authorized. ### Attack Path 1. The presign API is compromised or returns a malicious or incorrectly configured response. 2. The response specifies an attacker-controlled HTTPS upload host and optional headers. 3. `uploadFileToOSS()` verifies only the scheme. 4. The function opens the selected local file and sends it to the supplied host using HTTP `PUT`. 5. The attacker-controlled server receives the file. ### Impact Assessment The issue can redirect uploaded user videos or arbitrary readable local ...[truncated 303 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Maintain an explicit allowlist of authorized object-storage domains and validate the exact hostname against it. 2. Reject IP-literal hosts, unexpected ports, embedded credentials, and malformed or ambiguous hostnames. 3. If multiple storage providers are supported, document and validate each expected domain suffix carefully. 4. Allowlist upload headers rather than forwarding arbitrary API-provided headers. 5. Bind the presigned response cryptographically or structurally to the current request, expected object key, file size, and content type. 6. Log the normalized destination domain without logging signed query parameters or credentials. 7. Update documentation to disclose all storage and API destinations accurately. ]]>

other

Note
Location
scripts/api/video.js:17
Finding
Presign Requests Disclose Complete Local Filesystem Paths<![CDATA[ ## Vulnerability Details **File Location**: `scripts/api/video.js:17-23` **Vulnerability Type**: Privacy-sensitive local metadata disclosure **Risk Level**: Low ### Vulnerable Code ```js 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 `filename` argument is the complete user-supplied local path. The code places it directly into the JSON body sent to the remote presign API. A full path is not generally required to generate an object-storage upload URL. A sanitized basename, generated identifier, content type, and file size should be sufficient. Full paths can expose user names, home-directory structure, project names, customer names, internal mount points, and other contextual information unrelated to transcription. The behavior also weakens the documentation's claim that no unrelated local data is transmitted. Although the path describes the selected file, its parent-directory information is unnecessary metadata. ### Attack Path 1. A user invokes the Skill with a local file such as `/home/user/confidential-client/project/video.mp4`. 2. The complete path is passed to `getPresignedUrl()`. 3. The path is serialized as the `file` property. 4. The JSON body is transmitted to `www.guaikei.com`. 5. The remote service receives filesystem metadata beyond the file content itself. ### Impact Assessment The remote service gains knowledge of local directory names and filesystem layout. This may reveal user identity, organization names, project names, operational structure, or sensitive contextual metadata. The issue does not expose additional file contents by itself and does not grant code execution or elevated privileges. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the full path with `path.basename(filename)` after sanitization. 2. Prefer a generated opaque object identifier rather than retaining the original filename. 3. Send only metadata required by the presign service, such as file size and validated media type. 4. Document all metadata transmitted to the service. 5. Add tests confirming that absolute paths and parent-directory names never appear in outbound request bodies or logs. ]]>
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 (23)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill advertises processing arbitrary public video URLs and likely performs generic network download and local file write behavior to handle them. Without explicit restrictions on allowed domains, file size, storage paths, redirect handling, and protocol validation, this can create SSRF-like fetch abuse, unexpected internal network access in permissive runtimes, or disk/resource exhaustion from attacker-controlled URLs.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill advertises processing arbitrary public video URLs and likely performs generic network download and local file write behavior to handle them. Without explicit restrictions on allowed domains, file size, storage paths, redirect handling, and protocol validation, this can create SSRF-like fetch abuse, unexpected internal network access in permissive runtimes, or disk/resource exhaustion from attacker-controlled URLs.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill advertises processing arbitrary public video URLs and likely performs generic network download and local file write behavior to handle them. Without explicit restrictions on allowed domains, file size, storage paths, redirect handling, and protocol validation, this can create SSRF-like fetch abuse, unexpected internal network access in permissive runtimes, or disk/resource exhaustion from attacker-controlled URLs.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill advertises processing arbitrary public video URLs and likely performs generic network download and local file write behavior to handle them. Without explicit restrictions on allowed domains, file size, storage paths, redirect handling, and protocol validation, this can create SSRF-like fetch abuse, unexpected internal network access in permissive runtimes, or disk/resource exhaustion from attacker-controlled URLs.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill advertises processing arbitrary public video URLs and likely performs generic network download and local file write behavior to handle them. Without explicit restrictions on allowed domains, file size, storage paths, redirect handling, and protocol validation, this can create SSRF-like fetch abuse, unexpected internal network access in permissive runtimes, or disk/resource exhaustion from attacker-controlled URLs.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README encourages users to submit local video files or public video links to a cloud-backed processing service, but it does not clearly warn at the point of use that content is transmitted to a remote third-party server for processing. This can mislead users into sending sensitive or regulated media under the assumption the tool operates locally, creating privacy, confidentiality, and compliance risk.

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.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The skill description is extremely broad ('handle all video-to-text needs') and overlaps with general content analysis and copywriting tasks. Overbroad activation increases the chance that an agent invokes this skill for ordinary requests and unnecessarily uploads local files or third-party URLs to an external service, causing unintended data disclosure and spend.

Natural-Language Policy Violations

Medium
Confidence
86% confidence
Finding
The manifest description is entirely in Chinese and frames the skill's use cases and outputs from a Chinese-language perspective, but does not indicate language choice or opt-in. For a generally scoped skill, this can amount to an implicit locale/language constraint without documenting user selection.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The guidance says to prioritize the skill whenever any matching intent appears, and the listed categories include broad writing and analysis scenarios. In an agentic environment, that can steer unrelated user requests into a networked third-party workflow, increasing privacy exposure, wrong-tool execution, and unnecessary token-billed operations.

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
86% confidence
Finding
The package description advertises very broad capabilities across local files, public links, transcription, analysis, summarization, rewriting, and style transformation without stating clear trigger boundaries, supported-source restrictions, or abuse-prevention constraints. In an agent ecosystem, this can cause over-invocation, unsafe handling of arbitrary remote content, and use in higher-risk content transformation scenarios without explicit user confirmation.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
This JavaScript file uses Chinese-only natural-language documentation and error/status strings throughout, such as comments and thrown messages, with no indication that the skill supports user language selection or is intentionally limited to a Chinese-only context. That can violate language/locale policy when a skill imposes a language without user opt-in or explicit justification.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The stop() and __removeFile() logic can unlink downloaded files when removeOnStop or removeOnFail is enabled, which is a destructive file operation covered by the missing-warning rule. The code includes no confirmation prompt and no direct user-facing warning that stopping or failed downloads may delete partially downloaded files.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This downloader accepts arbitrary HTTP/HTTPS URLs, follows redirects, and writes the response to a local file path derived from remote-controlled headers or URL path. In a skill whose advertised purpose includes fetching public video links, this creates a real SSRF and untrusted file-write primitive if upstream callers do not strictly validate allowed domains, schemes, destinations, and file types.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
Multiple user-visible error strings are written only in Chinese, such as request failures, parse failures, token errors, and timeout/network messages. This imposes a specific language on users without any evident locale selection or documented regional constraint.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This code emits all warning and informational messages exclusively in Chinese, including error and recovery guidance. For a general utility file with no documented region-specific scope or language choice, this constitutes a natural-language locale policy issue because users are not offered an opt-in or alternative language.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The banner text is explicitly Chinese-language text ("视频文案智能提取助手"), which indicates a fixed language/locale choice in user-facing output. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the constraint is justified or configurable.

Natural-Language Policy Violations

Low
Confidence
78% confidence
Finding
The natural-language description and author contact metadata are presented only in Chinese, which may effectively constrain the skill's usability and interaction expectations to a specific language without stating that this is optional or region-specific. The policy requires avoiding language or locale constraints unless users are given a choice or the limitation is clearly documented and justified.

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
The file’s natural-language comments and all user-facing error/help strings are written in Chinese, indicating the skill is designed to communicate in a single language by default. Under the policy, forcing a specific language without offering a user choice or documenting a justified locale constraint is a natural-language policy issue.

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
This JavaScript file contains natural-language comments and user-facing status/error messages entirely in Chinese, such as the doc comment at L24-L26 and progress/error output at L41, L45, L51, L61, L73, and L78. Under the policy rule for language/locale, this is a violation because the skill imposes a specific language without any opt-in or documented locale constraint.

Missing User Warnings

Low
Confidence
80% confidence
Finding
This code sends JSON data over HTTPS and includes a TOKEN header, which can transmit user or system data to a remote service. In this file, there is no confirmation prompt or explicit user-facing disclosure near the network operation itself; only retry/error handling is present.

Static analysis

No suspicious patterns detected.