Back to skill

Security audit

douyin-downloader-js

Security checks for vulnerabilities and agentic risk

Overview

This Douyin downloader is mostly purpose-aligned, but its network fetching is too broadly scoped and could be abused to reach internal URLs or consume excessive memory/disk.

Install only if you are comfortable running a downloader that fetches remote content and writes files locally. Use a dedicated output directory, avoid untrusted links, and prefer a revised version that restricts hosts to Douyin/CDN domains, limits redirects and file sizes, streams downloads safely, and validates response types.

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
script/douyin-parse.cjs:38
Finding

Unrestricted HTTP Requests and Redirects Enable Server-Side Request Forgery

Content
View full analysis
{ if (!url.includes('v.douyin.com')) { resolve(url); return; } const parsedUrl = new URL(url); const isHttps = parsedUrl.protocol === 'https:'; const client = isHttps ? https : http; const options = { headers: { 'User-Agent': USER_AGENT }, timeout: 10000 }; const req = client.request(url, options, (res) => { // Check for a redirect if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { console.log('Redirect found:', res.headers.location); // Recursively process the redirect resolveShortUrl(res.headers.location).then(resolve); } else { resolve(res.responseUrl || url); } }); ``` ```js function fetch(url, options = {}) { return new Promise((resolve, reject) => { const parsedUrl = new URL(url); const isHttps = parsedUrl.protocol === 'https:'; const client = isHttps ? https : http; const defaultOptions = { headers: { 'User-Agent': USER_AGENT, 'Referer': REFERER, ...options.headers }, timeout: 30000 }; const req = client.get(url, defaultOptions, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => resolve(data)); }); ``` Media redirects are followed in the same unrestricted manner: ```js const req = client.request(videoUrl, options, (res) => { // Check for a redirect if (res.s ...[truncated 3110 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
script/douyin-parse.cjs:89
Finding

Unbounded Response Buffering Enables Memory-Exhaustion Denial of Service

Content
View full analysis
{ let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => resolve(data)); }); ``` Image responses are buffered completely before being written: ```js const req = client.request(url, options, (res) => { // Check for a redirect if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { console.log('Image download redirected to:', res.headers.location); downloadImage(res.headers.location, filename).then(resolve).catch(reject); return; } const data = []; res.on('data', chunk => data.push(chunk)); res.on('end', () => { const fs = require('fs'); fs.writeFileSync(filename, Buffer.concat(data)); resolve(filename); }); }); ``` Video responses use the same buffering pattern: ```js const req = client.request(videoUrl, options, (res) => { // Check for a redirect if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { console.log('Video download redirected to:', res.headers.location); // Recursively process the redirect downloadVideoToFile(res.headers.location, filepath).then(resolve).catch(reject); return; } const data = []; res.on('data', chunk => data.push(chunk)); res.on('end', () => { const fs = require('fs'); fs.writeFileSync(filepath, Buffer.concat(data)); resolve(filepath); }); }); ``` ### Technical Analysis The implementation stores entire HTML, image, and video responses in process memory. It does not enforce a maximum byte count or reject an excessive `Content-Length`. For media downloads, `Buffer.concat(data)` c ...[truncated 1710 chars]
Remediation
View remediation
Vulnerability Patterns
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (6)

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest description emphasizes parsing video information and downloading Douyin video/image content, but this file goes beyond retrieval by persisting content to caller-controlled local paths using fs.writeFileSync and creating output directories. Local filesystem modification is a materially broader operation than simple parsing/downloading metadata and is not stated in the manifest text.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code automatically downloads remote video or image content and writes it to local paths under the provided output directory. While there are progress logs, there is no confirmation prompt or clear safety warning before performing these local file writes, which are safety-relevant side effects in a reusable skill context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

When executed as a script, the program creates an output directory and automatically downloads and saves video content if a media URL is found. Although console logs indicate progress, they do not serve as a prior warning or consent mechanism for the disk write operation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill explicitly downloads remote video or image content into the user's workspace, but it does not clearly warn users that untrusted remote files will be fetched and stored locally. This can lead to accidental ingestion of unsafe or policy-sensitive content, unexpected disk usage, or downstream handling of untrusted media without informed consent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

Comments, messages, and user-facing console output are entirely in Chinese, indicating an implicit fixed language choice. There is no indication that the user can opt into another language or that the language restriction is intentionally documented as region-specific.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

When executed directly, the script automatically creates an output directory and saves a video file. The manifest describes a downloader broadly, but does not mention standalone CLI-style execution with implicit local writes, which is a distinct operational behavior.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.