Back to skill

Security audit

xiaohongshuskills

Security checks for vulnerabilities and agentic risk

Overview

The skill can control a logged-in Xiaohongshu account, post public comments or content, and read account data, but some high-impact behavior is under-scoped and the code has unsafe handling of untrusted content and media URLs.

Install only if you are comfortable giving this skill control over a logged-in Xiaohongshu browser profile. Use it with a dedicated account/profile, avoid remote CDP unless the host is fully trusted, review all post/comment text before live actions, avoid feeding it untrusted webpage content or media URLs, and treat notification/analytics outputs and CSV files as private account data.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/cdp_publish.py:1944
Finding

Authenticated-Origin HTML Injection Through Unsafe Editor Content Rendering

Content
View full analysis
' + paragraphs[i] + ''); if (i < paragraphs.length - 1) {{ html.push('


'); }} }} el.innerHTML = html.join(''); el.dispatchEvent(new Event('input', {{ bubbles: true }})); }})(); """) print("[cdp_publish] Content set.") return ``` ### Technical Analysis The content is initially serialized with `json.dumps`, which safely embeds it as a JavaScript string literal. That protection does not apply when the resulting string is subsequently treated as HTML. Each paragraph is concatenated directly into an HTML fragment: ```javascript html.push('

' + paragraphs[i] + '

'); ``` The completed fragment is then assigned to `el.innerHTML`. No HTML escaping or sanitization is performed before th ...[truncated 2477 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/image_downloader.py:86
Finding

Arbitrary Media URL Fetching Enables SSRF and Unbounded Disk Consumption

Content
View full analysis
str: """ Download a single image and return the local file path. Args: url: Image URL to download referer: Optional Referer header. If None, auto-generates from URL domain. Raises requests.RequestException on network errors. """ # Build headers with Referer to bypass hotlink protection parsed = urlparse(url) if referer is None: referer = f"{parsed.scheme}://{parsed.netloc}/" headers = { "Referer": referer, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", } resp = requests.get(url, timeout=DEFAULT_TIMEOUT, stream=True, headers=headers) resp.raise_for_status() ext = self._guess_extension(url, resp.headers.get("Content-Type")) filename = f"{uuid.uuid4().hex[:12]}{ext}" filepath = os.path.join(self.temp_dir, filename) with open(filepath, "wb") as f: for chunk in resp.iter_content(chunk_size=8192): f.write(chunk) ``` ```python def download_video(self, url: str, referer: str | None = None) -> str: """ Download a single video and return the local file path. Args: url: Video URL to download referer: Optional Referer header. If None, auto-generates from URL domain. Raises requests.RequestException on network errors. """ parsed = urlparse(url) if referer is None: referer = f"{parsed.scheme}://{parsed.netloc}/" headers = { "Referer": referer, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", } resp = requ ...[truncated 3631 chars]
Remediation
View remediation
max_bytes: raise ValueError("Media exceeds the configured size limit") output.write(chunk) ``` 6. Add a total operation deadline in addition to connection and read timeouts. 7. Verify the response using both an allowlisted media MIME type and file-signature inspection. Do not infer safety from the filename extension or untrusted `Content-Type` alone. 8. Download to a securely created temporary file and ensure partial files are removed on every exception. 9. Where practical, use an explicit domain allowlist or require user confirmation when a media host has not previously been trusted. 10. Add tests for private IPv4 and IPv6 destinations, link-local metadata addresses, redirects to private networks, DNS changes, missing or false `Content-Length`, oversized bodies, endless streaming responses, and non-media p ...[truncated 12 chars]
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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (35)

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The README and stated skill metadata position the tool as an auto-publisher/testing browser utility, but the documented feature set materially expands into scraping note details and comments, harvesting notification data, posting comments, and exporting analytics. This mismatch can mislead users and reviewers about the true privilege and data-access scope of the skill, increasing the risk of unauthorized collection or account actions once installed.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared purpose omits that the skill can automate search, construct result URLs, extract search/detail data, and manipulate filtering controls. While not inherently malicious, this is a meaningful expansion from 'publish content' into web data retrieval and browsing automation, which broadens privacy and misuse risk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared purpose omits that the skill can automate search, construct result URLs, extract search/detail data, and manipulate filtering controls. While not inherently malicious, this is a meaningful expansion from 'publish content' into web data retrieval and browsing automation, which broadens privacy and misuse risk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose omits that the skill can automate search, construct result URLs, extract search/detail data, and manipulate filtering controls. While not inherently malicious, this is a meaningful expansion from 'publish content' into web data retrieval and browsing automation, which broadens privacy and misuse risk.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest states the skill only publishes posts or opens a test browser, but the body documents commenting, notification retrieval, analytics export, and content lookup. This scope deception is dangerous because it hides externally visible actions and access to private account data behind a much narrower stated purpose.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill metadata says it supports publishing图文、发布视频、仅启动测试浏览器, but the code also exposes feed search, feed detail retrieval, comment posting, notification capture, and analytics export. This is a scope expansion into authenticated data access and engagement automation, which increases abuse potential and violates least-functionality expectations for a publisher-only skill.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code includes automated comment posting and also contains like/collect automation helpers, enabling social engagement actions beyond content publishing. These capabilities can be used for spam, manipulation, or unauthorized account activity, especially because they operate through an authenticated browser session.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documented capabilities go beyond the declared purpose of publishing to include social interaction and data harvesting, such as comment posting and notification/detail collection. Even if intended for convenience, these features expand the operational scope from content publishing into account activity automation and data extraction, which raises abuse potential and user-consent concerns.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README advertises comment scraping, notification harvesting, note-detail retrieval, and analytics export without prominent privacy or data-handling guidance. Users may unknowingly collect third-party content or account-linked data without understanding storage, retention, sharing, or compliance implications.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The tool supports automatic publishing and comment posting against a live XHS account, but the documentation does not present a strong upfront warning that these commands perform irreversible external actions. In a skill context, that omission is dangerous because users may invoke automation assuming it is a dry run or test and accidentally modify their real account or public content.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill invokes shell commands, reads and writes local files, uses network access, and can interact with browser sessions, yet it declares no explicit tool scope or permission boundaries. That mismatch increases the chance an agent will grant or use broader capabilities than users expect, enabling unintended local file changes, network access, or browser automation against the user's account.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The trigger phrase '发布内容到小红书' is broad enough to match ordinary user discussion about posting content, increasing the chance the skill activates when the user did not intend full browser automation or account actions. Over-broad triggers are dangerous in action-taking skills because they can cause surprising invocation and unintended external side effects.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The documentation instructs the skill to fetch webpage content and media from arbitrary URLs in order to draft posts, which expands the skill from simple posting into general remote content retrieval. Arbitrary URL fetching can expose the agent to untrusted content sources and may be abused to access unexpected destinations if destination controls are absent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill includes comment-posting capability, which is an externally visible action performed under the user's account, but the description does not clearly warn about that risk. Without a prominent warning and explicit confirmation, the agent could post public or semi-public comments the user did not fully intend, causing reputational or account-policy harm.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill documents connecting to a remote CDP host without warning that this grants control over a potentially non-local browser session and may expose cookies, account data, and browsing context. Remote browser automation materially increases the attack surface because a user may unknowingly target another machine or a less-trusted environment.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The code can recursively delete a Chrome profile directory via shutil.rmtree when --delete-profile is supplied. Although the CLI help mentions deletion, there is no runtime confirmation or stronger user-facing warning immediately before the irreversible removal occurs.

Content

No source excerpt is available for this finding.

Dynamic Request Target

Medium
Category
Server-Side Request Forgery
Confidence
60% confidence
Finding

Request target host is built from a dynamic or untrusted value. If the host is attacker-influenced, this enables SSRF to arbitrary internal or metadata endpoints.

Content

Scanner excerpt · scripts/cdp_publish.py (reported line 468)May include surrounding context.

python
return pages[0]["webSocketDebuggerUrl"]

        # Create a new tab
        resp = requests.put(
            f"http://{self.host}:{self.port}/json/new?{XHS_CREATOR_URL}",
            timeout=5,
        )

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script retrieves private account notifications and creator analytics data that are unrelated to the stated publishing-only purpose. Accessing authenticated mentions and analytics broadens the data exposure surface and could leak sensitive account activity or performance data through logs or downstream consumers.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The code fetches authenticated notification mentions using the browser's logged-in cookies and returns the captured payload, but it provides no explicit warning or consent flow that private account notifications are being accessed. In a shared agent context, this can surprise users and expose sensitive social interactions to operators, logs, or other components.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script captures authenticated creator analytics and can export them to CSV, but there is no explicit warning that account performance data is being extracted and written to disk. This creates privacy and data-handling risk, especially on shared machines or when output paths are broadly accessible.

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 · scripts/chrome_launcher.py (reported line 155)May include surrounding context.

python
print(f"  profile dir: {user_data_dir}")
    print(f"  debug port : {port}")

    proc = subprocess.Popen(
        cmd,
        stdout=subprocess.DEVNULL,
        stderr=subprocess.DEVNULL,

Internal Network Request

Medium
Category
Server-Side Request Forgery
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.

Content

Scanner excerpt · scripts/chrome_launcher.py (reported line 192)May include surrounding context.

python
# Strategy 1: CDP Browser.close
    try:
        import requests
        resp = requests.get(f"http://127.0.0.1:{port}/json/version", timeout=2)
        if resp.ok:
            ws_url = resp.json().get("webSocketDebuggerUrl")
            if ws_url:

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 · scripts/chrome_launcher.py (reported line 227)May include surrounding context.

python
# Strategy 3: Windows taskkill by port (fallback)
    if sys.platform == "win32" and is_port_open(port):
        try:
            result = subprocess.run(
                ["netstat", "-ano"],
                capture_output=True, text=True, timeout=5
            )

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 · scripts/chrome_launcher.py (reported line 234)May include surrounding context.

python
for line in result.stdout.splitlines():
                if f":{port}" in line and "LISTENING" in line:
                    pid = line.strip().split()[-1]
                    subprocess.run(
                        ["taskkill", "/F", "/PID", pid],
                        capture_output=True, timeout=5
                    )

Tainted flow: 'filepath' from requests.get (line 140, network input) → open (file write)

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 · scripts/image_downloader.py (reported line 107)May include surrounding context.

python
filename = f"{uuid.uuid4().hex[:12]}{ext}"
        filepath = os.path.join(self.temp_dir, filename)

        with open(filepath, "wb") as f:
            for chunk in resp.iter_content(chunk_size=8192):
                f.write(chunk)

Static analysis

No suspicious patterns detected.