Back to skill

Security audit

ZeeLin 小红书自动发布

Security checks for vulnerabilities and agentic risk

Overview

This skill is meant to generate and publish Xiaohongshu posts, but it can automatically post through a logged-in browser without a clear final approval step.

Install only if you intentionally want a skill that can operate a logged-in Xiaohongshu creator account. Use an isolated browser profile, review generated titles/body/tags manually, set draft-only controls where available, and do not rely on the documented XHS_AUTO_PUBLISH safety claim unless the scripts are fixed.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/cdp_xhs_publish.py:436
Finding
Live Publishing Is Enabled by Default Despite the Documented Opt-In Safety Contract<![CDATA[ ## Vulnerability Details **File Location**: `scripts/cdp_xhs_publish.py:436-459` **Vulnerability Type**: Default-allow handling of a consequential external action **Risk Level**: Medium ### Vulnerable Code ```python no_publish = os.environ.get("XHS_NO_PUBLISH", "").strip() in ("1", "true", "yes") if no_publish: print("XHS: content filled. Skipping live Ops (XHS_NO_PUBLISH=1).") else: ``` The default branch eventually performs the live publication action: ```python js_eval(ws, "(function(){window.scrollTo(0,document.body.scrollHeight);return 'SCROLLED';})()") time.sleep(1) r3 = js_eval(ws, PUBLISH_JS) ``` ### Technical Analysis The script header states that the live publication action requires the explicit `XHS_AUTO_PUBLISH=1` opt-in. The implementation never checks that variable. Instead, it publishes unless the caller knows to set the inverse `XHS_NO_PUBLISH` variable. This is a fail-open design for a consequential external action. A caller following the documented interface can reasonably expect draft-only behavior when `XHS_AUTO_PUBLISH` is absent, but the implementation proceeds through formatting, navigation, publication, and confirmation. The script controls an already authenticated Xiaohongshu browser tab through CDP. Therefore, the publication occurs with the privileges of the user currently signed in to that browser profile. ### Attack Path 1. A user opens an authenticated Xiaohongshu creator session with CDP enabled. 2. The user or an automation workflow invokes `cdp_xhs_publish.py` with a title and body. 3. The caller does not set `XHS_AUTO_PUBLISH=1`, relying on the documented opt-in contract. 4. The caller also does not set the undocumented inverse safety flag `XHS_NO_PUBLISH=1`. 5. The script enters the default `else` branch. 6. It clicks the live publication control and subsequently attempts to confirm publication. 7. The supplied content is published or submitted for review without the documented opt-in. ### Impact Assess ...[truncated 458 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make draft-only behavior the default. 2. Require the documented positive opt-in before any live publication action: ```python auto_publish = os.environ.get("XHS_AUTO_PUBLISH", "").strip().lower() in { "1", "true", "yes" } if not auto_publish: print("Content filled. Live publication was not requested.") return ``` 3. Remove or deprecate the inverse `XHS_NO_PUBLISH` control to avoid conflicting configuration semantics. 4. Require a separate final confirmation immediately before clicking the live publication control. 5. Display the target account, title, and a content preview before confirmation. 6. Add automated tests proving that publication cannot occur when the opt-in variable is absent, empty, malformed, or false. 7. Update the Skill documentation and wrapper scripts so all entry points use the same publication-consent policy. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/cdp_xhs_publish_v5.py:439
Finding
The Version 5 Publisher Also Performs Live Publishing Without the Documented Positive Opt-In<![CDATA[ ## Vulnerability Details **File Location**: `scripts/cdp_xhs_publish_v5.py:439-462` **Vulnerability Type**: Default-allow handling of a consequential external action **Risk Level**: Medium ### Vulnerable Code ```python no_publish = os.environ.get("XHS_NO_PUBLISH", "").strip() in ("1", "true", "yes") if no_publish: print("XHS: content filled. Skipping live Ops (XHS_NO_PUBLISH=1).") else: ``` The default branch later invokes the live publication control: ```python js_eval(ws, "(function(){window.scrollTo(0,document.body.scrollHeight);return 'SCROLLED';})()") time.sleep(1) r3 = js_eval(ws, PUBLISH_JS) ``` ### Technical Analysis Like the primary publisher, the version 5 script documents a positive `XHS_AUTO_PUBLISH=1` requirement but does not enforce it. Live publishing is enabled whenever `XHS_NO_PUBLISH` is not explicitly set to a recognized true value. This creates a mismatch between the documented safety boundary and actual behavior. The script uses the authenticated browser session and repeatedly attempts both publication and confirmation, increasing the probability that an unintended submission succeeds. ### Attack Path 1. A Xiaohongshu account is logged in through a CDP-enabled browser. 2. A workflow invokes `cdp_xhs_publish_v5.py` with generated or user-supplied content. 3. The workflow omits `XHS_AUTO_PUBLISH=1` because no live post is intended. 4. `XHS_NO_PUBLISH` is also absent. 5. The script treats publication as enabled. 6. It advances to the publication page, clicks the publication control, and attempts confirmation. 7. Content is posted or submitted under the authenticated account. ### Impact Assessment The affected scope is the user's authenticated Xiaohongshu creator session. The script can submit public content using that account without enforcing the documented positive consent gate. Consequences include accidental disclosure of drafts, unwanted promotional posts, reputational harm, moderation penalties, and loss of contr ...[truncated 170 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Enforce `XHS_AUTO_PUBLISH=1` as the sole positive authorization for live publishing. 2. Exit after filling the draft when the positive opt-in is absent. 3. Add a user-visible final confirmation that cannot be inferred from a prior content-generation request. 4. Avoid automatic repeated publication and confirmation attempts unless the user explicitly authorized retries. 5. Consolidate the duplicate publisher implementations so a single reviewed consent policy applies to every entry point. 6. Add regression tests that mock CDP calls and assert that the publication JavaScript is unreachable by default. 7. Correct the script documentation and runtime messages so they accurately describe the implemented behavior. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/cdp_xhs_publish_v2.py:15
Finding
Legacy CDP Publishers Select Browser Tabs Using an Untrusted URL Substring<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/cdp_xhs_publish_v2.py:15-18` - `scripts/cdp_xhs_publish_v3.py:25-29` - `scripts/cdp_xhs_publish_v4.py:13-17` **Vulnerability Type**: Improper validation of the browser target origin **Risk Level**: Medium ### Vulnerable Code Version 2: ```python def find_tab(): for t in requests.get(CDP).json(): if "xiaohongshu" in t.get("url",""): return t return None ``` Version 3: ```python def find_tab(): for t in requests.get(CDP).json(): if "xiaohongshu" in t.get("url",""): return t return None ``` Version 4: ```python def find_tab(): for t in requests.get(CDP).json(): if "xiaohongshu" in t.get("url",""): return t return None ``` After selecting the tab, the scripts connect to its debugger endpoint. Version 2 then inserts the supplied content into broadly selected inputs: ```python ws=websocket.create_connection(tab["webSocketDebuggerUrl"]) send(ws,"Runtime.evaluate",{"expression":focus_title}) send(ws,"Input.insertText",{"text":TITLE}) send(ws,"Runtime.evaluate",{"expression":focus_body}) send(ws,"Input.insertText",{"text":"\n"+BODY}) ``` Versions 3 and 4 additionally execute automated element searches and click operations in the selected page. ### Technical Analysis The scripts identify a trusted Xiaohongshu tab by checking whether the complete URL contains the text `xiaohongshu`. This does not validate the URL scheme or parsed hostname. An attacker-controlled URL such as `https://xiaohongshu.attacker.example/` or `https://attacker.example/?site=xiaohongshu` satisfies the condition. If that tab appears first in the CDP target list, the script connects to it and performs DOM evaluation, text insertion, and, in versions 3 and 4, automated click operations. The browser target is therefore selected using attacker-influenced display data rather than a strict origin allowlist. The primary and version 5 publishers ...[truncated 1590 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse each target URL and validate both the scheme and hostname: ```python from urllib.parse import urlparse def is_allowed_xhs_url(raw_url): parsed = urlparse(raw_url) host = (parsed.hostname or "").lower() return ( parsed.scheme == "https" and ( host == "xiaohongshu.com" or host.endswith(".xiaohongshu.com") ) ) ``` 2. Prefer a narrower allowlist such as the exact official creator hostname rather than every platform subdomain. 3. Navigate the selected tab to the canonical HTTPS creator URL before performing any DOM interaction. 4. Revalidate the origin after every navigation and immediately before inserting content or clicking a consequential control. 5. Verify that the CDP target has type `page`. 6. Reject URLs containing credentials, non-HTTPS schemes, unexpected ports, or unapproved hostnames. 7. Replace broad input and button selectors with page-state-specific selectors. 8. Remove the obsolete legacy variants from the distributed package if they are no longer required. 9. Add tests using lookalike domains, query-string matches, mixed-case hosts, suffix confusion, and malicious subdomains. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (35)

Tp2

High
Category
MCP Tool Poisoning
Confidence
85% confidence
Finding
Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The documentation describes a broad trend-scraping and planning workflow, but the actual code path appears to be a narrow execution wrapper for publishing via CDP, with key claimed capabilities not evidenced. This mismatch is security-relevant because it obscures the true privileged action the skill performs and frustrates accurate review of operational risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documentation describes a broad trend-scraping and planning workflow, but the actual code path appears to be a narrow execution wrapper for publishing via CDP, with key claimed capabilities not evidenced. This mismatch is security-relevant because it obscures the true privileged action the skill performs and frustrates accurate review of operational risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documentation describes a broad trend-scraping and planning workflow, but the actual code path appears to be a narrow execution wrapper for publishing via CDP, with key claimed capabilities not evidenced. This mismatch is security-relevant because it obscures the true privileged action the skill performs and frustrates accurate review of operational risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The documentation describes a broad trend-scraping and planning workflow, but the actual code path appears to be a narrow execution wrapper for publishing via CDP, with key claimed capabilities not evidenced. This mismatch is security-relevant because it obscures the true privileged action the skill performs and frustrates accurate review of operational risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The documentation describes a broad trend-scraping and planning workflow, but the actual code path appears to be a narrow execution wrapper for publishing via CDP, with key claimed capabilities not evidenced. This mismatch is security-relevant because it obscures the true privileged action the skill performs and frustrates accurate review of operational risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The documentation describes a broad trend-scraping and planning workflow, but the actual code path appears to be a narrow execution wrapper for publishing via CDP, with key claimed capabilities not evidenced. This mismatch is security-relevant because it obscures the true privileged action the skill performs and frustrates accurate review of operational risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documentation describes a broad trend-scraping and planning workflow, but the actual code path appears to be a narrow execution wrapper for publishing via CDP, with key claimed capabilities not evidenced. This mismatch is security-relevant because it obscures the true privileged action the skill performs and frustrates accurate review of operational risk.

Vague Triggers

High
Confidence
99% confidence
Finding
The trigger description is extremely broad and overlaps with ordinary requests for writing, topic ideas, hooks, and content planning. Because the same skill also contains live publishing behavior, this broad activation surface materially increases the risk of unexpected invocation of a high-impact automation pathway.

Missing User Warnings

High
Confidence
96% confidence
Finding
The skill describes automatic publishing/output generation without warning the user that actions may affect a live third-party account or produce externally visible posts. In this context, absence of disclosure is dangerous because publication is irreversible in practice and can cause reputational, compliance, or business harm if done unexpectedly.

Missing User Warnings

High
Confidence
99% confidence
Finding
The publishing SOP culminates in clicking the final red 'publish' button, yet there is no explicit user confirmation, safety pause, or caution about the external effect. This is especially dangerous because it automates a sensitive state-changing action on a logged-in account and could post unintended, unreviewed, or policy-violating content.

Ae1

High
Category
analysis-evasion
Content
- `scripts/auto_topic_post_xiaohongshu.sh`:主题到发布一体化。
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/post_xiaohongshu.sh`:仅执行发布流程(接收标题与正文)。
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Vague Triggers

High
Confidence
97% confidence
Finding
The trigger conditions are extremely broad and include generic terms like '文案', '内容运营', '选题', and even common requests such as '帮我写个短视频文案', which can cause the skill to activate for many ordinary user prompts outside its intended scope. Overbroad routing can hijack unrelated conversations, override more appropriate tools or skills, and increase the chance that web-search-driven automation runs without clear user intent or sufficient context validation.

Intent-Code Divergence

High
Confidence
99% confidence
Finding
The module docstring explicitly says publishing will not occur unless XHS_AUTO_PUBLISH=1, but the actual logic does the opposite: it publishes by default unless XHS_NO_PUBLISH is set. In an automation skill that controls a live creator account, this mismatch is dangerous because callers may trust the documented safety guard and unintentionally trigger real posts, causing unauthorized publication, reputational harm, or disclosure of draft/sensitive content.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The script connects to an existing Chrome DevTools endpoint on localhost and attaches to a live Xiaohongshu tab, giving it powerful control over an already authenticated browser session. That allows the skill to act as the logged-in user without normal application permission checks, creating a high-risk path for account misuse, unintended actions, or abuse of any accessible browser context.

Intent-Code Divergence

High
Confidence
99% confidence
Finding
The docstring states the script will not click the publish button unless XHS_AUTO_PUBLISH=1, but the implementation does the opposite: it publishes by default unless XHS_NO_PUBLISH is set. This creates a dangerous mismatch between documented and actual behavior, making accidental live posting likely for operators or downstream agents that rely on the stated safety guard.

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill advertises executable behavior that depends on network and environment-backed capabilities, but it does not declare a restrictive tool scope such as allowed-tools or permissions. This creates an authorization and review gap: the runtime may grant broader access than users or reviewers expect, increasing the chance of unintended network access or local-environment interaction.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The documentation shifts from content planning into a concrete live website publishing workflow, but the manifest framing does not clearly surface that escalation. In context, this increases danger because a user selecting a content-ops skill may unknowingly expose an authenticated browser session to automated posting behavior.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The shell-script entrypoints enable direct website posting, which is broader and more sensitive than the stated content ideation use case. Exposing executable publication scripts without a clearly declared permission boundary increases the chance of misuse, accidental execution, or under-reviewed account-impacting actions.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The file is written as a Chinese-only operating skill and all invocation examples, output structures, and writing guidance assume Chinese content generation by default. There is no indication that the user can choose another language or locale, which may violate a language-choice policy when the skill is used in broader contexts.

Natural-Language Policy Violations

Medium
Confidence
81% confidence
Finding
This markdown file is written as a core reference for content generation entirely in Chinese and does not indicate that users may choose another language or locale. Under the policy rule for natural-language violations, a skill that implicitly enforces a specific language without opt-in can be noncompliant unless the locale restriction is clearly documented and justified.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The skill metadata frames this capability as content ideation and copy generation, but the script goes further and performs a live publish action to Xiaohongshu. That mismatch is security-relevant because users or calling agents may invoke the skill expecting draft assistance, while the script can cause an external side effect by posting content without an explicit, separately authorized publish step.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The script automatically publishes generated content immediately after draft creation, with no user confirmation, review gate, or warning before the external action. In the context of a social-media automation skill, this is more dangerous because model-generated content may be inaccurate, policy-violating, or manipulated by prompt/input content, leading to unwanted public posts, reputational harm, or account penalties.

Internal Network Request

Medium
Category
Server-Side Request Forgery
Content
def list_tabs(p: int):
    with urllib.request.urlopen(f"http://127.0.0.1:{p}/json", timeout=8) as r:
        return json.loads(r.read())
Confidence
70% confidence
Finding
Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.

Static analysis

No suspicious patterns detected.