Back to skill

Security audit

Douyin Favorites to Knowledge

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its Douyin-to-local-notes purpose, but it asks for recurring background sync and has under-scoped outbound credential/media handling that users should review before installing.

Install only if you are comfortable with a dedicated persistent Douyin browser profile, automatic local note/report writes, and any selected cloud transcription provider receiving media or audio. Do not enable the daily scheduled task unless you explicitly want recurring background sync, avoid using SILICONFLOW_ASR_URL unless you fully trust and control it, store API keys in a scoped secret manager rather than a shared agent .env file, and treat custom module:function adapters as arbitrary local code.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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)

T06 · System Persistence

Error
Location
SKILL.md:74
Finding

Setup and login instructions mandate unsolicited scheduled persistence

Content
View full analysis
Remediation
View remediation

T01 · Skill Instruction Hijacking

Warning
Location
src/douyin_favorites_knowledge/cli.py:328
Finding

Hard-coded commercial referral steers Agent output and browser navigation

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/douyin_favorites_knowledge/siliconflow.py:193
Finding

Environment-controlled ASR endpoint can receive the API key and private media

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:87
Finding

API key is recommended for persistence in a broadly scoped Agent environment file

Content
View full analysis
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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (42)

Tainted flow: 'request' from os.environ.get (line 14, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · src/douyin_favorites_knowledge/feishu.py (reported line 20)May include surrounding context.

python
headers={"Content-Type": "application/json"},
        method="POST",
    )
    with urlopen(request, timeout=10) as response:
        if response.status // 100 != 2:
            raise ValueError("飞书 webhook 返回非成功状态")

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

声明的用途聚焦于把抖音收藏/喜欢内容同步到本地 Markdown 或 Obsidian 知识库,以及转录方式选择;并未提到任何飞书集成、外部通知或向第三方服务发送结果。该代码的实际行为是访问环境变量中的 FEISHU_WEBHOOK_URL,并通过 HTTP POST 向飞书 webhook 发送“已沉淀多少条新笔记”的通知。这属于未声明的外部网络通知能力和额外资源访问。虽然发送的内容看起来只是计数,不明显涉及 Cookie 或私密数据,但它仍然超出了“同步到本地知识库”的已声明范围,因此应判定为描述与行为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

该代码块的核心行为是环境探测和转录服务推荐,属于安装/诊断子模块,而声明描述的是一个面向抖音内容同步到 Markdown/Obsidian 的完整技能。虽然声明中提到需要让用户选择 SiliconFlow、本地 Whisper 或不转录,因此“转录相关配置”与整体技能有关,但此代码不仅没有实现声明中的主要业务流程(抓取已授权账号的收藏/喜欢、同步到本地知识库),还额外检查并推荐了百炼和 MiniMax,这些提供方未在声明的首选列表中明确出现。若将此代码视为整个技能的实际行为,则其主要目的与声明明显不一致,应判定为描述与行为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

声明描述的是一个面向抖音数据同步与可选转录的业务技能,而提供的代码片段是 security.py,功能集中在文本安全检查和错误信息脱敏。它会检测推理标签、若干令牌格式、私密字段名和私有文件路径,并阻止或清洗这些内容。这与声明中的核心能力(获取用户授权账号的收藏/喜欢列表、同步到 Markdown/Obsidian、处理首次转录选择)没有直接对应关系。虽然其中“不泄露 Cookie 与私密数据”的安全目标与声明的安全约束部分一致,但这只是局部支撑性安全实现,不能代表整体技能用途。因此就该代码片段与声明用途的对应关系来看,存在明显不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description describes a Douyin content synchronization skill with account-scoped data access, source selection between favorites and likes, optional transcription, and local knowledge-base export. The supplied code does none of that. It is purely a test file for repository hygiene and packaging consistency. Its behavior is materially different from the declared primary purpose, and it lacks any implementation of the described syncing, transcription, or user-account handling capabilities. Therefore this is a clear description-behavior mismatch.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · src/douyin_favorites_knowledge/cli.py (reported line 334)May include surrounding context.

python
print("—— SiliconFlow 配置(抖音推荐)——", file=sys.stderr)
            print("  ① 推荐注册/登录:https://cloud.siliconflow.cn/i/1srulim9", file=sys.stderr)
            print("  ② 控制台建 Key:https://cloud.siliconflow.cn/account/ak", file=sys.stderr)
            print("  ③ export SILICONFLOW_API_KEY='…' 或写入 ~/.hermes/.env 后重启", file=sys.stderr)
            try:
                ans = input("是否打开推荐注册页?[Y/n] ").strip().lower()
            except EOFError:

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · tests/test_workflow.py (reported line 26)May include surrounding context.

python
def cli(config: Path, *args: str) -> subprocess.CompletedProcess[str]:
    env = dict(os.environ)
    env["PYTHONPATH"] = PYTHONPATH
    return subprocess.run(
        [sys.executable, "-m", "douyin_favorites_knowledge", "--config", str(config), *args],

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · tests/test_workflow.py (reported line 900)May include surrounding context.

python
def cli(config: Path, *args: str) -> subprocess.CompletedProcess[str]:
    env = dict(os.environ)
    env["PYTHONPATH"] = PYTHONPATH
    return subprocess.run(
        [sys.executable, "-m", "douyin_favorites_knowledge", "--config", str(config), *args],

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill requests or implies capabilities including shell, network, environment-variable access, and file read/write, but does not declare an explicit tool scope such as permissions or allowed-tools. That creates an over-privileged execution surface where an agent may invoke sensitive operations without a clear least-privilege contract, increasing the chance of unintended command execution, network egress, or secret exposure.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

The entire skill description and operational instructions are written as mandatory Chinese-language guidance, and there is no indication that users may choose another language or locale. Under the policy, forcing a specific language without opt-in is a natural-language policy violation unless the locale constraint is explicitly documented and justified.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The description explains behavior and defaults, but it does not clearly define the exact trigger phrases or contexts that should invoke the skill. Phrases like acting when a user says they want favorites or likes synchronized are implied rather than narrowly enumerated, which can lead to unintended activation in ordinary conversation about Douyin content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill instructs the agent to create and verify a 23:00 scheduled task that performs silent daily synchronization and writes Markdown reports. Even though it says this should happen after setup/login and on the user's machine, the wording makes automatic ongoing file modification the default behavior without an equally explicit user-facing consent checkpoint for persistence, cadence, and continued writes.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The file implements a DashScope/Bailian transcription path even though the skill description only mentions SiliconFlow, local Whisper, or no transcription. That mismatch can defeat user expectations and informed consent, causing audio/media URLs from an authorized Douyin account to be sent to an unadvertised third-party service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code sends the Douyin media play URL to DashScope for remote ASR, which shares user-derived content with an external service. In this skill's context, the data originates from a user's favorites/likes and may reveal private interests or account-linked content; because the code itself does not enforce a user-facing disclosure or consent check, this creates a real privacy and data-handling risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The browser is launched with a hard-coded locale of "zh-CN", which enforces a specific language/locale regardless of user preference. The file does not offer an opt-in or configuration path for locale selection, matching the policy-violation criterion for forced language settings.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The sync and daily commands are explicitly described as silently writing to the knowledge base, and the implementation auto-approves all collected candidates before promotion. In a skill that ingests browser-derived content into local notes, this increases the risk of unexpected persistent writes, content poisoning, or accidental inclusion of sensitive/private material without a final user-visible confirmation at execution time.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The CLI allows arbitrary module:function adapters for collector, enricher, and notifier, which expands the trust boundary far beyond the stated browser-to-local-sync workflow. Because these adapters are dynamically loaded and executed, a user or downstream automation can run unintended code with the tool's privileges, enabling data exfiltration or unauthorized side effects if an untrusted adapter is supplied.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest describes syncing Douyin favorites/likes into a local Markdown or Obsidian knowledge base, with optional transcription choices, but says nothing about sending data or status messages to third-party chat platforms. This function reads a Feishu webhook URL from the environment and performs an external POST request, which is an additional notification/integration capability beyond the stated purpose.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · src/douyin_favorites_knowledge/local_whisper.py (reported line 142)May include surrounding context.

python
if err:
                    last = err
                    continue
                extracted = subprocess.run(
                    ["ffmpeg", "-nostdin", "-y", "-i", str(media_path), "-vn", "-ac", "1", "-ar", rate, str(audio_path)],
                    capture_output=True,
                    text=True,

Tainted flow: 'rate' from os.environ.get (line 55, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · src/douyin_favorites_knowledge/local_whisper.py (reported line 142)May include surrounding context.

python
if err:
                    last = err
                    continue
                extracted = subprocess.run(
                    ["ffmpeg", "-nostdin", "-y", "-i", str(media_path), "-vn", "-ac", "1", "-ar", rate, str(audio_path)],
                    capture_output=True,
                    text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · src/douyin_favorites_knowledge/provider_discovery.py (reported line 19)May include surrounding context.

python
if not shutil.which("mmx"):
        return {"state": "unavailable", "reason": "未发现 MiniMax 命令行转录接口"}
    try:
        result = subprocess.run(["mmx", "speech", "--help"], capture_output=True, text=True, timeout=5, check=False)
    except (OSError, subprocess.TimeoutExpired):
        return {"state": "unavailable", "reason": "无法确认 MiniMax 是否提供转录接口"}
    help_text = f"{result.stdout}\n{result.stderr}".lower()

External Transmission

Medium
Category
Data Exfiltration
Confidence
81% confidence
Finding

The code is explicitly designed to transmit media to api.siliconflow.cn, which is an external service boundary crossing and therefore a real data-exposure concern when handling private or user-authenticated content. In this skill context, external transmission is expected for cloud ASR, but it remains security-relevant because user favorites/liked media and extracted audio may contain sensitive personal information.

Content

Scanner excerpt · src/douyin_favorites_knowledge/siliconflow.py (reported line 31)May include surrounding context.

python
KEY_NAME = "SILICONFLOW_API_KEY"
DEFAULT_MODEL = "FunAudioLLM/SenseVoiceSmall"
DEFAULT_ENDPOINT = "https://api.siliconflow.cn/v1/audio/transcriptions"
MAX_MEDIA_BYTES = 512 * 1024 * 1024
TEMP_PREFIX = "douyin-sf-asr-"
DEFAULT_BITRATE = "64k"

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · src/douyin_favorites_knowledge/siliconflow.py (reported line 136)May include surrounding context.

python
if not shutil.which("ffmpeg"):
        return False
    rate, bitrate = _audio_encode_settings()
    completed = subprocess.run(
        [
            "ffmpeg",
            "-nostdin",

Tainted flow: 'rate' from os.environ.get (line 56, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · src/douyin_favorites_knowledge/siliconflow.py (reported line 136)May include surrounding context.

python
if not shutil.which("ffmpeg"):
        return False
    rate, bitrate = _audio_encode_settings()
    completed = subprocess.run(
        [
            "ffmpeg",
            "-nostdin",

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code uploads downloaded media content to a third-party transcription provider, which can expose user media and spoken content outside the local environment. In the skill context, the metadata says transcription provider choice should be explicitly selected by the user first, but this file itself contains no consent enforcement or disclosure guard, so misuse by callers could lead to unintended external sharing of private content.

Content

No source excerpt is available for this finding.