Back to skill

Security audit

Douyin Upload Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill largely does what it claims for Douyin publishing, but it needs Review because private video audio can be sent to external transcription endpoints by default and public-account actions rely on stored credentials and configurable confirmation bypasses.

Install only if you are comfortable giving the skill access to your Douyin app credentials, local video files, and a publishing token. Prefer local Whisper mode for sensitive media, keep autoConfirm disabled for account posts, restrict ASR endpoints to trusted HTTPS services, and periodically delete transcript caches/outbox files. Verify the external Whisper dependency and model before installing them.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/douyin.js:63
Finding

OAuth State Is Generated but Not Validated

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/lib/media.js:245
Finding

Extracted Audio and ASR Credentials Can Be Sent to an Arbitrary Endpoint

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
README.md:225
Finding

Installation Instructions Use Mutable, Unverified Third-Party Artifacts

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/lib/media.js:210
Finding

Local Whisper Leaves Plaintext Transcript Files in the System Temporary Directory

Content
View full analysis
file.endsWith(".json")); if (!found) { throw new Error(`Whisper output JSON not found in ${tempDir}`); } jsonPath = path.join(tempDir, found); } const payload = JSON.parse(await fsp.readFile(jsonPath, "utf8")); return normalizeWhisperJson(payload); } ``` The caller cleans only a different `douyin-asr-*` directory: ```js const tmpDir = await fsp.mkdtemp(path.join(os.tmpdir(), "douyin-asr-")); const wavPath = path.join(tmpDir, "audio.wav"); try { await extractAudio(videoPath, wavPath, config); let transcription; let source = mode; if (mode === "whisper-gpu") { transcription = await runWhisper(wavPath, config, true); source = "whisper-gpu"; } else if (mode === "whisper-cpu") { transcription = await runWhisper(wavPath, config, false); source = "whisper-cpu"; } else if (mode === "api") { transcription = await runThirdPartyAsrApi(wavPath, config); source = "asr-api"; } else { const error = new Error(`Unsupported asrMode: ${mode}`); error.code = " ...[truncated 2501 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (38)

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · README.md (reported line 222)May include surrounding context.

Ubuntu/Debian 快速安装指令:

bash
sudo apt-get update && sudo apt-get install -y ffmpeg cmake build-essential curl jq xdg-utils

# 安装 whisper.cpp
git clone https://github.com/ggerganov/whisper.cpp.git

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · scripts/douyin.js (reported line 239)May include surrounding context.

js
**Ubuntu/Debian 快速安装指令:**
```bash
sudo apt-get update && sudo apt-get install -y ffmpeg cmake build-essential curl jq xdg-utils

# 安装 whisper.cpp
git clone https://github.com/ggerganov/whisper.cpp.git

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This code chunk is a reusable command-line utility module, not an implementation of the declared Douyin publishing workflow. While interactive prompting and confirmation could support such a tool, the actual code does not demonstrate any of the core declared capabilities. Because the described primary purpose is specific and substantial, and the code shown is only unrelated generic support infrastructure, this is a description-behavior mismatch for the supplied chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The code is genuinely related to Douyin authorization and publishing, so the primary domain matches part of the description. However, this chunk only provides API-layer functionality for OAuth, token refresh, uploading a local video file, creating a video post, and classifying permission errors. It does not implement the declared local speech-to-text pipeline, automatic caption/title generation from audio, any confirmation workflow, or a fallback export mechanism when publish permissions are absent. Because several prominent declared behaviors are not represented in the supplied code chunk, the description overstates what this code actually does.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/douyin.js (reported line 123)May include surrounding context.

js
}

  if (!tokenData.refreshToken) {
    const error = new Error("Access token expired and refresh_token is missing. Re-run auth.");
    error.code = "TOKEN_EXPIRED";
    throw error;
  }

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill is marketed as local-first and privacy-preserving, yet later says the default ASR mode is a third-party API. In this context, the contradiction is dangerous because the tool handles potentially sensitive video/audio content, and users may unknowingly expose that content to external providers.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The README explicitly promises that audio does not need to be uploaded to any cloud ASR service, but elsewhere documents a third-party API ASR mode. This is a security/privacy documentation integrity issue because users may make deployment decisions based on a false assumption that sensitive audio never leaves the device.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation introduces a third-party ASR API mode without a clear warning that user audio or derived transcript data may be sent to an external service. Because this skill processes local media files, the missing disclosure can cause unintended data exfiltration of private or regulated content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The fallback outbox bundles video, captions, subtitles, and metadata into an export package, but the README does not warn users about the sensitivity and persistence of that bundle. In practice this can create an unprotected local archive of highly sensitive content that is easy to copy, sync, or mishandle.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · README.md (reported line 222)May include surrounding context.

Ubuntu/Debian 快速安装指令:

bash
sudo apt-get update && sudo apt-get install -y ffmpeg cmake build-essential curl jq xdg-utils

# 安装 whisper.cpp
git clone https://github.com/ggerganov/whisper.cpp.git

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 231)May include surrounding context.

ln -sf "$(pwd)/build/bin/whisper-cli" ~/.local/bin/whisper-cli

下载模型文件

mkdir -p ~/.cache/whisper.cpp curl -L https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.bin -o ~/.cache/whisper.cpp/ggml-small.bin

text

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill advertises and instructs use of shell execution, environment-variable access, and networked OAuth/API flows, but it does not declare any explicit tool scope such as allowed-tools or permissions. That creates an authorization and review gap: operators cannot easily constrain what the skill is allowed to access, and an agent may invoke high-risk capabilities without clear least-privilege boundaries.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

The config command allows persistent storage of autoConfirm and other operational settings, which can enable future publishes or account actions with reduced user oversight. In a skill that performs OAuth, local file handling, and remote publishing, persistent autonomous settings increase the chance of accidental or unauthorized actions if reused later.

Content

Scanner excerpt · SKILL.md (reported line 78)May include surrounding context.

md
- `auth`: opens OAuth URL, accepts pasted callback URL or `code`, stores encrypted token.
- `prepare`: returns metadata, transcript, and ASR failure detail (without stopping publish flow).
- `publish`: uploads and creates video via official API. If permission-like API errors occur, writes fallback files under outbox and returns `mode: fallback`.
- `config`: stores persistent settings (`defaultPrivateStatus`, `autoConfirm`, `whisperBin`, `whisperModelPath`, `outboxDir`, etc.).

## Caption Rules

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · README.md (reported line 192)May include surrounding context.

md
"  node scripts/douyin.js doctor",
    "  node scripts/douyin.js auth [--code <code>] [--callback-url <url>] [--scope <scope>] [--open true|false]",
    "  node scripts/douyin.js prepare --video <path>",
    "  node scripts/douyin.js publish --video <path> --text <caption> [--private-status 0|1|2] [--auto-confirm true|false]",
    "  node scripts/douyin.js config list",
    "  node scripts/douyin.js config get <key>",
    "  node scripts/douyin.js config set <key> <value>",

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · README.md (reported line 194)May include surrounding context.

md
"  node scripts/douyin.js doctor",
    "  node scripts/douyin.js auth [--code <code>] [--callback-url <url>] [--scope <scope>] [--open true|false]",
    "  node scripts/douyin.js prepare --video <path>",
    "  node scripts/douyin.js publish --video <path> --text <caption> [--private-status 0|1|2] [--auto-confirm true|false]",
    "  node scripts/douyin.js config list",
    "  node scripts/douyin.js config get <key>",
    "  node scripts/douyin.js config set <key> <value>",

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · SKILL.md (reported line 69)May include surrounding context.

md
"  node scripts/douyin.js doctor",
    "  node scripts/douyin.js auth [--code <code>] [--callback-url <url>] [--scope <scope>] [--open true|false]",
    "  node scripts/douyin.js prepare --video <path>",
    "  node scripts/douyin.js publish --video <path> --text <caption> [--private-status 0|1|2] [--auto-confirm true|false]",
    "  node scripts/douyin.js config list",
    "  node scripts/douyin.js config get <key>",
    "  node scripts/douyin.js config set <key> <value>",

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · SKILL.md (reported line 85)May include surrounding context.

md
"  node scripts/douyin.js doctor",
    "  node scripts/douyin.js auth [--code <code>] [--callback-url <url>] [--scope <scope>] [--open true|false]",
    "  node scripts/douyin.js prepare --video <path>",
    "  node scripts/douyin.js publish --video <path> --text <caption> [--private-status 0|1|2] [--auto-confirm true|false]",
    "  node scripts/douyin.js config list",
    "  node scripts/douyin.js config get <key>",
    "  node scripts/douyin.js config set <key> <value>",

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · scripts/douyin.js (reported line 34)May include surrounding context.

js
"  node scripts/douyin.js doctor",
    "  node scripts/douyin.js auth [--code <code>] [--callback-url <url>] [--scope <scope>] [--open true|false]",
    "  node scripts/douyin.js prepare --video <path>",
    "  node scripts/douyin.js publish --video <path> --text <caption> [--private-status 0|1|2] [--auto-confirm true|false]",
    "  node scripts/douyin.js config list",
    "  node scripts/douyin.js config get <key>",
    "  node scripts/douyin.js config set <key> <value>",

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · scripts/douyin.js (reported line 413)May include surrounding context.

js
"  node scripts/douyin.js doctor",
    "  node scripts/douyin.js auth [--code <code>] [--callback-url <url>] [--scope <scope>] [--open true|false]",
    "  node scripts/douyin.js prepare --video <path>",
    "  node scripts/douyin.js publish --video <path> --text <caption> [--private-status 0|1|2] [--auto-confirm true|false]",
    "  node scripts/douyin.js config list",
    "  node scripts/douyin.js config get <key>",
    "  node scripts/douyin.js config set <key> <value>",

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/douyin.js (reported line 239)May include surrounding context.

js
};

  const installHints = [
    "sudo apt-get update && sudo apt-get install -y ffmpeg cmake build-essential curl jq",
    "git clone https://github.com/ggerganov/whisper.cpp.git && cd whisper.cpp && cmake -B build && cmake --build build -j",
    "ln -sf $(pwd)/build/bin/whisper-cli ~/.local/bin/whisper-cli",
    "mkdir -p ~/.cache/whisper.cpp && curl -L https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.bin -o ~/.cache/whisper.cpp/ggml-small.bin",

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/douyin.js (reported line 242)May include surrounding context.

js
"sudo apt-get update && sudo apt-get install -y ffmpeg cmake build-essential curl jq",
    "git clone https://github.com/ggerganov/whisper.cpp.git && cd whisper.cpp && cmake -B build && cmake --build build -j",
    "ln -sf $(pwd)/build/bin/whisper-cli ~/.local/bin/whisper-cli",
    "mkdir -p ~/.cache/whisper.cpp && curl -L https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.bin -o ~/.cache/whisper.cpp/ggml-small.bin",
    "export DOUYIN_ASR_MODE=api && export DOUYIN_ASR_API_KEY=*** && export DOUYIN_ASR_API_URL=https://api.openai.com/v1/audio/transcriptions",
    "or set local whisper mode: node scripts/douyin.js config set asrMode whisper-gpu",
  ];

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/douyin.js (reported line 243)May include surrounding context.

js
"git clone https://github.com/ggerganov/whisper.cpp.git && cd whisper.cpp && cmake -B build && cmake --build build -j",
    "ln -sf $(pwd)/build/bin/whisper-cli ~/.local/bin/whisper-cli",
    "mkdir -p ~/.cache/whisper.cpp && curl -L https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.bin -o ~/.cache/whisper.cpp/ggml-small.bin",
    "export DOUYIN_ASR_MODE=api && export DOUYIN_ASR_API_KEY=*** && export DOUYIN_ASR_API_URL=https://api.openai.com/v1/audio/transcriptions",
    "or set local whisper mode: node scripts/douyin.js config set asrMode whisper-gpu",
  ];

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

This is the same functional issue as the duplicate finding at the same line: autoConfirm can suppress human review before a publish action. In a social-media publishing skill, that context makes the risk more relevant because the action has external side effects on a real account.

Content

Scanner excerpt · scripts/douyin.js (reported line 409)May include surrounding context.

js
}

  const caption = normalizeCaption(captionInput);
  const autoConfirm = parseBoolean(options["auto-confirm"], config.autoConfirm);

  if (!autoConfirm) {
    if (!process.stdin.isTTY) {

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

This is the same functional issue as the duplicate finding at the same line: autoConfirm can suppress human review before a publish action. In a social-media publishing skill, that context makes the risk more relevant because the action has external side effects on a real account.

Content

Scanner excerpt · scripts/douyin.js (reported line 409)May include surrounding context.

js
}

  const caption = normalizeCaption(captionInput);
  const autoConfirm = parseBoolean(options["auto-confirm"], config.autoConfirm);

  if (!autoConfirm) {
    if (!process.stdin.isTTY) {

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

This file accepts and persists a whisperLang setting from the DOUYIN_WHISPER_LANG environment variable, indicating the skill can enforce a fixed transcription language. There is no natural-language indication here that users can choose or opt in to that locale behavior, which matches the policy concern for language/locale constraints.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access, suspicious.exposed_secret_literal

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/douyin.js:83

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/lib/media.js:253

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/douyin.js:445

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/lib/douyin-api.js:140

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/lib/token-store.js:110