Back to skill

Security audit

抖音热门账号推荐

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stated Douyin ranking purpose, but its report generator automatically opens unescaped ranking data as HTML and loads remote JavaScript, so it needs review before installation.

Review this skill before installing. Use it only if you trust RedFox as the data/API provider and can limit the key's scope or revoke it. Avoid generating or opening reports from untrusted JSON or API responses until the publisher escapes HTML, validates Douyin profile URLs, removes automatic opening or gates it behind an explicit option, and pins or bundles the report JavaScript. Confirm any subscription schedule and know how to cancel it.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate_report.py:455
Finding
Unescaped Ranking Data Enables HTML and Script Injection in Generated Reports<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_report.py`, lines 455–479, 584–612, 633–650, and 684–695 **Vulnerability Type**: HTML injection, script injection, and unsafe URL interpolation **Risk Level**: High ### Vulnerable Code ```python ROW_TEMPLATE_CAT = """ <tr> <td><span class="rank-badge {rank_class}">{rank}</span></td> <td><a href="{profile_url}" target="_blank" class="account-name" title="点击查看抖音主页">{account_name}</a></td> <td class="category">{category}</td> <td><span class="score">{score}</span></td> <td>{followers}</td> <td class="interaction">{new_fans}</td> <td class="interaction">{new_likes}</td> <td class="interaction">{new_comments}</td> <td class="interaction">{new_shares}</td> </tr>""" ROW_TEMPLATE = """ <tr> <td><span class="rank-badge {rank_class}">{rank}</span></td> <td><a href="{profile_url}" target="_blank" class="account-name" title="点击查看抖音主页">{account_name}</a></td> <td><span class="score">{score}</span></td> <td>{followers}</td> <td class="interaction">{new_fans}</td> <td class="interaction">{new_likes}</td> <td class="interaction">{new_comments}</td> <td class="interaction">{new_shares}</td> </tr>""" ``` ```python account_name = item.get('accountName', '') profile_url = item.get('profileUrl', '') # ... if is_all_category: account_category = item.get('category', '-') rows.append(ROW_TEMPLATE_CAT.format( rank_class=rank_class, rank=rank, account_name=account_name, profile_url=profile_url or '#', category=account_category, score=score, followers=followers, new_fans=new_fans, new_likes=new_likes, new_comments=new_comments, new_shares=new_shares, )) else: rows.append(ROW_TEMPLATE.format( rank_class=rank_class, rank=rank, account_name=account_name, profile_url=p ...[truncated 3680 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Escape every untrusted value according to its HTML context: ```python from html import escape safe_account_name = escape(str(account_name), quote=True) safe_category = escape(str(account_category), quote=True) ``` 2. Validate profile links using `urllib.parse.urlparse`. Permit only HTTPS URLs on an explicit host allowlist, such as `www.douyin.com`: ```python from urllib.parse import urlparse def safe_profile_url(value: str) -> str: try: parsed = urlparse(value) if parsed.scheme == "https" and parsed.hostname == "www.douyin.com": return escape(value, quote=True) except Exception: pass return "#" ``` 3. Reject `javascript:`, `data:`, `file:`, and other unexpected schemes. Host validation must occur after parsing rather than through prefix matching. 4. Prefer a template engine with auto-escaping enabled instead of assembling HTML through unrestricted `str.format()` calls. 5. Add a restrictive Content Security Policy, for example one that denies inline scripts and limits network connections to the minimum required origins. 6. Remove automatic report opening or place it behind an explicit `--open` option. Report generation should not render externally controlled content without user confirmation. 7. Add regression tests containing account names such as `<script>...</script>`, quotes, event handlers, and malformed URLs to confirm that they are rendered as text rather than executable markup. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/generate_report.py:360
Finding
Generated Reports Execute Third-Party CDN JavaScript Without Integrity Verification<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_report.py`, line 360 **Vulnerability Type**: Unverified third-party runtime dependency **Risk Level**: Medium ### Vulnerable Code ```html <script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script> ``` ### Technical Analysis Every generated report references and executes `html2canvas` directly from a third-party CDN when the report is opened. Although the package version is fixed to `1.4.1`, the script element does not include a Subresource Integrity hash, and the report does not enforce a Content Security Policy. As a result, the effective JavaScript executed by the report is not fully contained in the audited project. A compromise of the package artifact, CDN infrastructure, publishing account, or delivery path could cause modified code to execute in generated reports. This network request is not required for displaying the ranking report. It is used only for the optional image-export feature, so loading it automatically for every report exceeds the minimum network access needed for basic report generation and viewing. ### Attack Path 1. An attacker compromises or substitutes the CDN-hosted `html2canvas@1.4.1` asset. 2. A user generates a report with `generate_report.py`. 3. The script automatically opens the report, or the user opens it later. 4. The browser requests the JavaScript file from `cdn.jsdelivr.net`. 5. Because no integrity hash is supplied, the browser accepts and executes the substituted content. 6. The malicious dependency reads or modifies report data and may transmit it through browser network requests or present deceptive content to the user. ### Impact Assessment Malicious CDN-delivered JavaScript would execute in the report's browser context and could: - Read all ranking and account data rendered in the report. - Modify rankings, links, export controls, or other report content. - Send report data and browser metadata to an e ...[truncated 334 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Bundle a reviewed copy of `html2canvas` with the project and reference it locally. This makes the code executed by the report part of the auditable artifact and removes the runtime CDN dependency. 2. If CDN loading is retained, add a verified Subresource Integrity hash and anonymous CORS mode: ```html <script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js" integrity="sha384-REPLACE_WITH_VERIFIED_HASH" crossorigin="anonymous"></script> ``` The hash must be calculated from and compared against a trusted copy of the exact distributed file. 3. Add a restrictive Content Security Policy that limits script sources, connection destinations, frames, and object loading. Avoid allowing unrestricted inline script execution. 4. Load the image-export dependency only after explicit user action rather than whenever the report is opened. 5. Document the dependency, version, source, integrity value, and update-review procedure so future updates receive security review before deployment. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (22)

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

Critical
Category
Data Flow
Content
data = json.dumps(payload).encode("utf-8")
    req = urllib.request.Request(API_URL, data=data, headers=headers, method="POST")
    try:
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            return json.loads(resp.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        body = e.read().decode("utf-8", errors="replace")
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
for rule in CATEGORY_INFER_RULES:
        for kw in rule["keywords"]:
            if kw.lower() in combined:
                return rule["category"]

    return "全部"
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The README says users can 'Describe what you need in plain language — no commands to memorize,' which makes activation scope ambiguous for a markdown skill description. Although examples are provided below, the text does not clearly define what kinds of requests should or should not invoke the skill, increasing the risk of unintended triggering from ordinary Douyin-related conversation.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README advertises subscription and automatic push capabilities but does not clearly warn users that this creates a persistent task with ongoing outbound notifications. Without explicit disclosure and consent language, users may unknowingly authorize recurring actions, leading to privacy concerns, notification abuse, or unexpected long-lived automation.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The activation guidance says users can interact using unrestricted natural language, but it does not clearly bound the skill to ranking/report/subscription use cases. In agent environments, overly broad invocation language can cause accidental routing of unrelated requests into this skill, increasing the chance of inappropriate data access, unintended actions such as subscription setup, or confused-deputy behavior.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill instructs use of environment variables, file reads/writes, shell commands, and network-backed API access, but declares no explicit tool scope or permissions. This creates a least-privilege failure: a host agent may expose more capabilities than intended, making accidental or unauthorized execution paths harder to constrain or review.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The trigger phrases include broad natural-language terms such as generic ranking or recommendation requests, which can cause the skill to activate in contexts the user did not intend. Unintended invocation is risky here because the skill can lead to network queries, file generation, and subscription automation, amplifying the effect of a false trigger.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
该 markdown 文件适用 SQP-2。文档说明会调用外部接口 `https://redfox.hk/...`,并从环境变量 `REDFOX_API_KEY` 读取凭证,但未提醒用户该技能会向第三方服务发送请求,也未说明会使用本地环境中的凭证。

Vague Triggers

Medium
Confidence
92% confidence
Finding
该 markdown 文件适用 SQP-1。L117 明确写明“用户任何口语化表达都会自动映射到最匹配的赛道,无法识别时降级为‘全部’”,且后续示例包含大量日常高频词如“车”“老师”“品牌”“健康”等,缺少边界条件或反例,容易把普通对话误判为赛道选择触发。

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The module docstring, usage examples, and user-facing behavior are entirely in Chinese, which imposes a specific language on users without any opt-in or alternative locale support. The policy for this audit flags language or locale constraints when they are forced rather than explicitly optional or justified as region-specific.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
This Python skill emits Chinese-only natural-language content in its usage text and report template, including fixed `zh-CN` HTML locale and Chinese UI strings. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is explicitly documented and justified as region-specific.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The script's declared purpose is report generation, but it also launches the generated file via platform-specific system commands. That extra execution capability is not strictly required for producing the report and increases the attack surface, especially in agent or automation contexts where a file-generating skill should not unexpectedly trigger local applications.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
try:
        system = platform.system()
        if system == "Darwin":  # macOS
            subprocess.run(["open", str(abs_path)], check=True)
        elif system == "Windows":
            subprocess.run(["start", "", str(abs_path)], shell=True, check=True)
        else:  # Linux
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if system == "Darwin":  # macOS
            subprocess.run(["open", str(abs_path)], check=True)
        elif system == "Windows":
            subprocess.run(["start", "", str(abs_path)], shell=True, check=True)
        else:  # Linux
            subprocess.run(["xdg-open", str(abs_path)], check=True)
        print(f"\n✓ HTML 报告已自动打开: {abs_path}", file=sys.stderr)
Confidence
92% confidence
Finding
On Windows, the script invokes subprocess.run with shell=True to execute 'start' on a path that can be influenced by user input via --output. Using shell=True introduces command-injection risk if the output path contains shell metacharacters, and it also grants the script an unnecessary ability to launch local applications beyond pure report generation.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
elif system == "Windows":
            subprocess.run(["start", "", str(abs_path)], shell=True, check=True)
        else:  # Linux
            subprocess.run(["xdg-open", str(abs_path)], check=True)
        print(f"\n✓ HTML 报告已自动打开: {abs_path}", file=sys.stderr)
    except Exception as e:
        print(f"\n✓ HTML 报告已生成: {abs_path}", file=sys.stderr)
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Low
Confidence
76% confidence
Finding
All visible instructions, examples, and usage guidance are presented only in Chinese, which can amount to a language/locale constraint without user opt-in. The policy allows locale constraints when they are clearly documented and justified, but no such explanation or language choice appears here.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
Natural-language policy issues apply to all file types, and this file consistently assumes Chinese-language interaction with no opt-in, fallback, or statement that the skill is intentionally limited to Chinese-speaking users. That can violate language/locale policy when a skill forces a specific language without user choice.

Natural-Language Policy Violations

Low
Confidence
92% confidence
Finding
This JSON file uses Chinese-language category names and trigger terms throughout, including display labels, with no accompanying indication that the skill is China/Chinese-specific or that users can choose another language. That can violate language/locale policy when a skill implicitly forces one locale without explicit opt-in or justification.

Natural-Language Policy Violations

Low
Confidence
87% confidence
Finding
This JSON file defines period labels entirely in Chinese, and the alias lists also include Chinese-only terms later in the file. Because the configuration does not document that it is region-specific or offer a language/locale choice, it may violate the policy against forcing a specific language without user opt-in.

Natural-Language Policy Violations

Low
Confidence
65% confidence
Finding
SQP-3 适用于所有文件。全文仅以中文描述接口,并在参数与赛道映射中要求使用中文类别值,未见向用户提供语言或 locale 选择的说明;若该技能面向通用用户,这构成潜在的语言策略限制。

Intent-Code Divergence

Low
Confidence
98% confidence
Finding
L021 将 `source` 示例值写为 `抖音每日最具影响力账号-ClawHub`,但 L025 又明确说明 `source` 必须为 `抖音每日最具影响力账号`,否则会返回空数据。这属于文档内部对实际调用要求的直接矛盾,可能导致按示例实现的代码与预期接口行为不一致。

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
This markdown file presents all instructions and scoring rules solely in Chinese, which can amount to a language policy violation when no user opt-in or locale justification is provided. The file does not indicate that the skill is intended only for Chinese-speaking users or a China-specific compliance context.

Static analysis

No suspicious patterns detected.