Back to skill

Security audit

小红书热门账号推荐

Security checks for vulnerabilities and agentic risk

Overview

The skill broadly matches its Xiaohongshu ranking purpose, but its generated HTML reports and subscription flow create review-worthy safety risks.

Review before installing. This skill needs a RedFox API key, calls an external ranking API, writes downloadable HTML reports, and can create recurring pushes if you opt in. Treat generated reports as active web pages: open only reports from trusted data, be cautious with account links, and verify any scheduled subscription so you know how to cancel it.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_report.py:460
Finding
Generated HTML reports allow attacker-controlled markup and unsafe link schemes<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_report.py`, lines 460-548 **Vulnerability Type**: Stored HTML injection and unsafe URL handling **Risk Level**: Medium ### Vulnerable Code ```python 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>{new_notes}</td> <td class="interaction">{new_fans}</td> <td class="interaction">{new_likes}</td> <td class="interaction">{new_comments}</td> <td class="interaction">{new_collects}</td> <td class="interaction">{new_shares}</td> </tr>""" def _fmt(val, fmt_fn=None) -> str: if val is None or val == "" or val == "-": return "-" if isinstance(val, str): return val if val.strip() else "-" try: n = int(val) if n == 0: return "-" return fmt_fn(n) if fmt_fn else str(n) except (TypeError, ValueError): return str(val) if val else "-" rows.append(ROW_TEMPLATE.format( rank=rank, rank_class=rank_class, account_name=html_utils.escape(item.get("accountName", "")), profile_url=html_utils.escape( item.get("accountLink") or item.get("profileUrl", "#") ), followers=_fmt(item.get("followers"), format_followers), new_notes=item.get("newNoteCount", "-") or "-", new_fans=_fmt(item.get("newFans"), format_interaction), new_likes=_fmt(item.get("newLikes"), format_interaction), new_comments=_fmt(item.get("newComments"), format_interaction), new_collects=_fmt(item.get("newCollects"), format_interaction), new_shares=_fmt(item.get("newShares"), format_interaction), score=int(item.get("comprehensiveScore")) if item.get("comprehensiveScore") else "-", )) ``` ### Technical Analysis The report generator inser ...[truncated 2503 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Escape every value inserted into HTML, not only account names: ```python def escape_text(value) -> str: return html_utils.escape(str(value), quote=True) followers = escape_text(_fmt(item.get("followers"), format_followers)) new_notes = escape_text(item.get("newNoteCount", "-") or "-") new_fans = escape_text(_fmt(item.get("newFans"), format_interaction)) new_likes = escape_text(_fmt(item.get("newLikes"), format_interaction)) new_comments = escape_text(_fmt(item.get("newComments"), format_interaction)) new_collects = escape_text(_fmt(item.get("newCollects"), format_interaction)) new_shares = escape_text(_fmt(item.get("newShares"), format_interaction)) ``` 2. Validate profile URLs structurally and allow only expected HTTPS destinations: ```python from urllib.parse import urlparse def safe_profile_url(value: str) -> str: try: parsed = urlparse(value) allowed_hosts = {"www.xiaohongshu.com", "xiaohongshu.com"} if parsed.scheme == "https" and parsed.hostname in allowed_hosts: return html_utils.escape(value, quote=True) except (TypeError, ValueError): pass return "#" ``` 3. Add `rel="noopener noreferrer"` to links opened with `target="_blank"`: ```html <a href="{profile_url}" target="_blank" rel="noopener noreferrer" class="account-name"> ``` 4. Validate API and JSON fields against an explicit schema. Numeric metrics should be accepted only as numbers or narrowly defined numeric strings such as `123`, `12.3w`, or `-`. 5. Add automated tests using payloads containing `<script>`, event-handler attributes, quotes, encoded markup, and `javascript:` URLs. 6. Consider using a templating engine with automatic HTML escaping enabled rather than manually formatting HTML strings. ]]>

T03 · Remote Payload Retrieval and Execution

Warning
Location
scripts/generate_report.py:408
Finding
Generated reports retrieve and execute mutable JavaScript from a third-party CDN<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_report.py`, lines 408-431 **Vulnerability Type**: Remote JavaScript execution without integrity verification **Risk Level**: Medium ### Vulnerable Code ```html <script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script> <script> async function downloadAsImage() { const btn = document.getElementById('downloadImgBtn'); btn.textContent = '⏳ 生成中...'; btn.disabled = true; try { const element = document.querySelector('.table-wrap'); const canvas = await html2canvas(element, { scale: 2, backgroundColor: '#ffffff', useCORS: true }); const link = document.createElement('a'); link.download = '小红书榜单_{date}.png'; link.href = canvas.toDataURL('image/png'); link.click(); } catch (e) { alert('生成图片失败,请尝试使用浏览器截图'); } } </script> ``` ### Technical Analysis Every generated report includes a script reference to jsDelivr. When the report is opened, the browser retrieves the JavaScript from the network and executes it with the same privileges as the report's own scripts. Although the dependency uses an explicit version, the report does not include a Subresource Integrity hash and does not bundle an audited local copy. The effective executable content is therefore outside the reviewed project and can change independently of the Skill package if the CDN, package publication path, or upstream account is compromised. This behavior is not necessary for the core ranking-query or static-report functionality. It exists only for optional image export and expands the report's privileges from static local rendering to remote code retrieval and execution. ### Attack Path 1. An attacker compromises the CDN delivery path, the upstream package publication, or another component capable of changing the resource served at the referenced URL. 2. A user opens a generated HTML report while network access is available. 3. The brows ...[truncated 1055 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prefer bundling a reviewed local copy of `html2canvas` into the Skill and embedding it into the generated report. This produces a self-contained artifact and removes runtime remote-code retrieval. 2. If remote loading is unavoidable, add Subresource Integrity and strict cross-origin handling: ```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 integrity hash must be calculated from and verified against the exact reviewed file. 3. Apply a restrictive Content Security Policy. If the dependency is bundled locally, an appropriate baseline is: ```html <meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self'; style-src 'unsafe-inline'; img-src 'self' data:; connect-src 'none'; object-src 'none'; base-uri 'none'; form-action 'none'"> ``` For a standalone `file://` report, test the policy across supported browsers and adjust it without permitting unnecessary network access. 4. Make image export optional and clearly disclose any network requirement before loading external resources. 5. Pin and periodically review the dependency, record its hash, and add tests confirming that generated reports contain no unapproved external script references. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • 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 (12)

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"]

    # 3. 兜底关键词
    for category, keywords in FALLBACK_KEYWORDS.items():
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The README’s natural-language content, examples, and usage guidance are all presented in Chinese, and there is no indication that users may choose another language or that the skill is intentionally restricted to Chinese-speaking users. Under the language/locale policy criterion, forcing a specific language without opt-in is a policy concern.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill instructs use of environment variables, network access to third-party APIs, and HTML report generation/file delivery, but declares no explicit tool scope or permissions boundary. This creates an overbroad-execution risk: a host agent may expose more capabilities than intended, making accidental or unsafe tool use harder to constrain and audit.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
该技能从描述、触发词、输出模板到固定回复内容均强制为中文,未说明是否允许根据用户偏好切换语言。若组织要求尊重用户语言/地区选择,这种默认且唯一的语言约束属于自然语言策略风险。

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger list includes broad everyday phrases like '最新推荐' and generic ranking terms, which can cause the skill to activate in contexts the user did not intend. Over-triggering is risky here because the skill can make network requests, generate files, and initiate follow-on subscription prompts tied to persistent actions.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The skill contains conflicting instructions for creating subscriptions: one section says to use automation_update, while another later requires calendar_create. In agentic environments, contradictory side-effect instructions can cause unintended persistence, duplicate tasks, or the wrong automation primitive being invoked without clear user understanding.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill directs the agent to create subscriptions/calendars but does not clearly disclose the user impact of creating a persistent recurring task, especially since the flow pushes subscription prompts immediately after content output. This raises consent and surprise-action risks, where users may not appreciate that accepting the prompt creates ongoing scheduled behavior.

External Transmission

Medium
Category
Data Exfiltration
Content
"source": "小红书指数榜-ClawHub"
}

resp = requests.post(url, json=payload_day, timeout=15)
data = resp.json()

if data["code"] == 2000:        # 注意:成功码是 2000
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The module docstring, usage examples, CLI help text, warnings, and generated output are written in Chinese, which imposes a language/locale choice on users. Under the policy, locale constraints should either be optional for the user or clearly justified as region-specific; this file does neither.

Intent-Code Divergence

Low
Confidence
93% confidence
Finding
The monthly subscription example uses a weekly recurrence with INTERVAL=4, which does not reliably correspond to 'monthly' behavior and can drift across calendar months. This can cause unexpected executions and user confusion for a persistent scheduled action.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The document presents all instructions, warnings, and examples exclusively in Chinese, which can amount to a language-policy issue when no user opt-in or alternative language is provided. The file does not state that it is intended only for a Chinese-speaking or region-specific audience.

Intent-Code Divergence

Low
Confidence
97% confidence
Finding
函数 `_is_data_updated` 的文档在 L290 声称“月榜:每月 2号 9:00 更新”,但同一函数实际代码在 L306-L311 按“每月 1日 9:00 更新”判断。这属于注释/文档对代码行为的直接矛盾,可能误导维护者理解“最新”月榜的回退逻辑。

Static analysis

No suspicious patterns detected.