Back to skill

Security audit

小红书自动化 V2

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to do what it advertises, but it needs review because it automates a real social account while weakening browser protections and storing/handling session data with limited safeguards.

Install only if you are comfortable giving the skill control of a logged-in Xiaohongshu account and understand that it may post, comment, like, favorite, scrape page data, and retain browser session state locally. Use a dedicated account and non-root user, avoid untrusted image URLs and untrusted CLI arguments, and review the no-sandbox Chrome behavior before using it on a machine with sensitive data.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/image_downloader.py:23
Finding

Unrestricted Remote Image Download Enables SSRF and Resource Exhaustion

Content
View full analysis
bool: """Determine whether the string is an image/media URL.""" return path.lower().startswith(("http://", "https://")) ``` ```python # Download parsed = urlparse(image_url) headers = { "User-Agent": _USER_AGENT, "Referer": f"{parsed.scheme}://{parsed.hostname}/", } resp = self._session.get(image_url, headers=headers) if resp.status_code != 200: raise RuntimeError(f"Download failed (status={resp.status_code}): {image_url}") # Save with open(filepath, "wb") as f: f.write(resp.content) ``` ### Technical Analysis The downloader considers every HTTP or HTTPS address a valid image URL. It performs no validation of the destination hostname or resolved IP address and does not block loopback, private, link-local, reserved, or cloud metadata addresses. The request also follows redirects by default. Therefore, validating only the original URL would remain insufficient because a public endpoint could redirect the request to an internal destination. No content-type validation, image decoding validation, streaming byte limit, or maximum response size is applied. `resp.content` loads the complete response into memory before writing it to disk. Although the constructor assigns `self._session.timeout = 30`, `requests.Session` does not interpret that attribute as a default request timeout, and the individual request does not supply a `timeout` argument. ### Attack Path 1. An attacker or untrusted caller supplies a crafted value through the `--images` CLI option. 2. `process_images()` recognizes the value as remote input because it begins with `http://` or `https://`. 3. `download_image()` sends a request from the host running the Skill. 4. The destination ...[truncated 1177 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/xhs/cookies.py:9
Finding

Authentication Artifacts Are Written to Predictable Paths Without Explicit Access Controls

Content
View full analysis
str: """Get the cookie file path.""" if account: account_dir = Path.home() / ".xhs" / "accounts" / account account_dir.mkdir(parents=True, exist_ok=True) return str(account_dir / "cookies.json") import tempfile old_path = os.path.join(tempfile.gettempdir(), "cookies.json") if os.path.exists(old_path): return old_path env_path = os.getenv("COOKIES_PATH") if env_path: return env_path return "cookies.json" ``` ```python def save_cookies(path: str, data: bytes) -> None: """Save cookies to a file.""" os.makedirs(os.path.dirname(path) or ".", exist_ok=True) with open(path, "wb") as f: f.write(data) ``` The login QR code is also written to a fixed shared temporary path: ```python qr_dir = os.path.join(tempfile.gettempdir(), "xhs") os.makedirs(qr_dir, exist_ok=True) filepath = os.path.join(qr_dir, "login_qrcode.png") with open(filepath, "wb") as f: f.write(img_data) ``` ### Technical Analysis Cookie data is authentication material and must be protected as a credential. The helper can reuse a predictable system-wide temporary path, `/tmp/cookies.json` on typical Unix systems, or place the file in the current working directory. Files are opened without an explicit restrictive mode, exclusive creation, owner verification, regular-file verification, or protection against symbolic links. The QR code is similarly stored under a predictable filename such as `/tmp/xhs/login_qrcode.png`. The directory and file are created without explicit permission hardening or symlink defenses. The audit found that cookie helper functions are largely unused by the current ...[truncated 1623 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/xhs/stealth.py:124
Finding

Chrome Sandbox Is Unconditionally Disabled

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/xhs/comment.py:174
Finding

User-Controlled Identifier Is Interpolated into JavaScript Executed in an Authenticated Page

Content
View full analysis
{{ const els = document.querySelectorAll( '.parent-comment, .comment-item, .comment' ); for (const el of els) {{ if (el.querySelector('[data-user-id="{user_id}"]')) {{ el.scrollIntoView({{behavior: 'smooth', block: 'center'}}); return true; }} }} return false; }})() """ ) ``` ### Technical Analysis The `user_id` value originates from the CLI and is inserted directly into a JavaScript program using a Python f-string. It is placed inside a quoted CSS selector without JavaScript-string encoding or CSS-selector escaping. A crafted identifier containing quotes and JavaScript syntax can terminate the intended selector string and alter the expression evaluated by Chrome DevTools Protocol. The resulting code executes through `Runtime.evaluate` in the context of an authenticated Xiaohongshu page. This differs from normal browser form input: the value is incorporated into executable source code before evaluation. Validation elsewhere was not identified in the audited flow. ### Attack Path 1. An attacker influences the arguments passed to the `reply-comment` command. 2. The attacker provides a crafted `--user-id` containing quote characters and JavaScript syntax. 3. `reply_comment()` passes that value to `_find_and_scroll_to_comment()`. 4. The function builds JavaScript source through an f-string. 5. `page.evaluate()` submits the resulting source to Chrome's `Runtime.evaluate`. 6. The injected JavaScript runs in the authenticated Xiaohongshu page context. 7. The script can inspect page-accessi ...[truncated 966 chars]
Remediation
View remediation
{{ const userId = {encoded_user_id}; const selector = `[data-user-id="${{CSS.escape(userId)}}"]`; for (const el of document.querySelectorAll( '.parent-comment, .comment-item, .comment' )) {{ if (el.querySelector(selector)) {{ el.scrollIntoView({{behavior: 'smooth', block: 'center'}}); return true; }} }} return false; }})() """ ``` 4. Validate `user_id` against Xiaohongshu's documented identifier syntax and enforce a conservative maximum length. 5. Apply equivalent validation and CSS escaping to `comment_id`, which is also incorporated into selectors. 6. Add tests using quotes, backslashes, brackets, line terminators, and JavaScript metacharacters to ensure inputs remain data rather than executable source. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (29)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill explicitly supports publishing, commenting, liking, favoriting, and persistent cookie storage, but the documentation provides no warning that these actions affect a real user account or that session data will be retained locally. In an automation skill that can perform social actions at scale, this omission increases the risk of unintended account activity, privacy exposure, and unsafe handling of authenticated sessions.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code file contains natural-language strings exclusively in Chinese, including the module docstring and later user-facing exception/log messages, with no indication that the skill is region-specific or that users can opt into this locale. That creates a language policy concern because the skill effectively imposes one language by default.

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 157)May include surrounding context.

python
logger.info("使用代理: %s", _mask_proxy(proxy))

    logger.info("启动 Chrome: port=%d, headless=%s, profile=%s", port, headless, user_data_dir)
    process = subprocess.Popen(
        args,
        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 198)May include surrounding context.

python
try:
        import requests

        resp = requests.get(f"http://127.0.0.1:{port}/json/version", timeout=2)
        if resp.status_code == 200:
            ws_url = resp.json().get("webSocketDebuggerUrl")
            if ws_url:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The code kills any process found listening on the requested port without verifying it is actually the Chrome instance started by this tool. If a sensitive local service is bound to that port, an attacker who can influence the port value or pre-bind the port could cause denial of service by forcing termination of unrelated processes.

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 318)May include surrounding context.

python
"""查找占用指定端口的进程 PID(跨平台)。"""
    try:
        if sys.platform == "win32":
            result = subprocess.run(
                ["netstat", "-ano", "-p", "TCP"],
                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 · scripts/chrome_launcher.py (reported line 334)May include surrounding context.

python
pids.append(int(parts[-1]))
            return list(set(pids))
        else:
            result = subprocess.run(
                ["lsof", "-ti", f":{port}"],
                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 · scripts/chrome_launcher.py (reported line 355)May include surrounding context.

python
"""终止指定 PID 的进程(跨平台)。"""
    try:
        if sys.platform == "win32":
            subprocess.run(
                ["taskkill", "/PID", str(pid), "/F"],
                capture_output=True,
                timeout=5,

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code hard-codes Chinese-language docstrings, help text, error messages, and interactive prompts, and even forces UTF-8 specifically to support Chinese console output. There is no option for the user to choose another language/locale and no documented justification that the tool is restricted to a Chinese-only region or compliance context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code file contains user-facing natural-language text such as the module docstring and CLI help in Chinese, which effectively forces a specific language for users. The policy allows locale constraints only when they are optional, user-selectable, or clearly justified as region-specific, none of which is stated here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This file's user-facing natural-language documentation and inline descriptions are entirely in Chinese, including the module docstring and subsequent method docstrings/comments. Under the stated policy, forcing a specific language without user choice is a natural-language policy violation unless the locale constraint is explicitly justified, which is not present here.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code explicitly injects a stealth script via Page.addScriptToEvaluateOnNewDocument, which is an anti-detection capability intended to evade browser automation checks. In an automation skill with no stated defensive or testing justification, this increases abuse potential for stealth scraping, account automation, or bypassing site controls, making the behavior security-relevant rather than a harmless implementation detail.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill overrides the browser user agent and randomizes viewport/device metrics to impersonate a real user session. Combined with the stealth injection elsewhere in the file, this materially supports deception of anti-bot systems and makes automated activity harder to distinguish from human activity.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code defines all docstrings and exception messages exclusively in Chinese, including user-facing strings such as login and retry guidance. Under the language/locale policy, forcing a specific language without offering a user choice or documenting a justified locale constraint is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

If the script cannot read the current interaction state, it deliberately assumes the opposite state and proceeds to click the like button anyway. In an automation context, this can cause unintended account actions and state changes without reliable verification, which is a real integrity and consent issue even if it does not directly enable code execution or data theft.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

When favorite/collect state retrieval fails, the code forces a click on the collect button rather than stopping or asking for confirmation. This creates unauthorized or unintended user actions in browser automation, and the function may also report success without confirming the final state, increasing the risk of silent integrity errors.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code accepts a one-time SMS verification code and submits it through the browser automation flow, which is a sensitive authentication operation. Although there is internal logging for success or failure, there is no user-facing warning, confirmation, or explicit disclosure in comments/docstrings that the skill will handle authentication credentials.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The function triggers the final publish action immediately via page.click_element(PUBLISH_BUTTON) with no explicit confirmation gate, preview pause, or user-verification step at the moment of publication. In an automation skill that posts content to a real social-media account, this increases the risk of unintended public posting if upstream inputs are wrong, the account/session is not the intended one, or the function is invoked accidentally.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The selector constants rely on fixed Chinese text such as "写长文", "新的创作", and a Chinese placeholder string to locate UI elements. This hard-codes a specific language/locale behavior in the skill without any visible opt-in, fallback, or documentation that the skill is intentionally limited to the Chinese-language Xiaohongshu interface.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The module docstring and comment at L003 describe a stability-oriented stealth approach ('avoid randomization causing inconsistent fingerprints'), but the injected script later makes navigator.hardwareConcurrency and navigator.deviceMemory return randomized values. That is an active contradiction in the code's stated intent, because these values can vary and undermine the claimed consistency.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The injected script forces navigator.languages to return ['zh-CN', 'zh', 'en-US', 'en'], which imposes a specific locale preference in natural-language behavior. This is a language/locale policy concern because the file does not offer user opt-in or explain why a Chinese locale is required.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
76% confidence
Finding

This code file defines structures for content publishing and user actions such as posting images/videos and performing interactions like likes or favorites, which can affect user data or external platform state. There is no accompanying docstring, comment, prompt, or other visible disclosure here warning that these operations may publish content or change account state.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code file performs a network-backed page navigation to a user profile and then collects profile and post data from the loaded page. Although the function has an internal docstring, there is no user-facing warning, confirmation, or visible log disclosing that browsing activity and user data extraction will occur.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The description field is entirely in Chinese and does not indicate that the skill is region-specific or provide any user opt-in for language/locale. Under the policy rule for natural-language violations, forcing a specific language in user-facing metadata without choice or justification is a reportable issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The natural-language instructions in this file are entirely Chinese, and there is no indication that users may select another language or that the skill is intentionally restricted to a Chinese-speaking audience for compliance reasons. This can violate language/locale policy when a specific language is effectively forced without opt-in.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.