Back to skill

Security audit

AI小红书信息源

Security checks for vulnerabilities and agentic risk

Overview

The skill largely matches its stated report-generation purpose, but subscription mode persists a plaintext API key and installs recurring execution with unsafe command handling.

Install only if you are comfortable giving this skill a RedFox API key, making outbound RedFox API calls, writing local HTML reports, and potentially installing a daily scheduled task. Avoid `--subscribe` until credential storage and crontab handling are fixed; use `--no-open` for reports from external data, and prefer a dedicated, revocable API key.

Vulnerability Patterns
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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
Findings (5)

T06 · System Persistence

Error
Location
scripts/fetch_xhs_ai.py:407
Finding

Persistent Scheduled Execution Through LaunchAgent or Crontab

Content
View full analysis
EnvironmentVariables {ENV_KEY} {api_key} """ plist_content = f''' Label {PLIST_LABEL} ProgramArguments /usr/bin/python3 {script_path} --no-open StartCalendarInterval Hour 16 Minute 0 StandardOutPath {log_path} StandardErrorPath {log_path} RunAtLoad {env_section} ''' plist_path.write_text(plist_content, encoding="utf-8") try: subprocess.run(["launchctl", "load", str(plist_path)], check=True, capture_output=True) info("订阅成功! 每天 16:00 自动生成小红书 AI 日报") info(f"日报目录: ~/Downloads/QoderReports/") info(f"日志: {log_path}") return True except subp ...[truncated 2415 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fetch_xhs_ai.py:418
Finding

API Key Persisted in Plaintext LaunchAgent Configuration

Content
View full analysis
EnvironmentVariables {ENV_KEY} {api_key} """ plist_content = f''' Label {PLIST_LABEL} ProgramArguments /usr/bin/python3 {script_path} --no-open StartCalendarInterval Hour 16 Minute 0 StandardOutPath {log_path} StandardErrorPath {log_path} RunAtLoad {env_section} ''' plist_path.write_text(plist_content, encoding="utf-8") ``` ### Technical Analysis On macOS, subscription installation copies `REDFOX_API_KEY` from the process environment into the LaunchAgent property-list file. The value is stored unencrypted in: ```text ~/Library/LaunchAgents/com.qoder.xiaohongshu-ai-feed.plist ``` The code does not explicitly create the file with restrictive permissions, use the macOS Keychain, or escape the credential for XML. Consequently: - The credential becomes a persistent plaintext artifact. - Local processes running as the user can read it. - Backups, support archives, synchronization tools, or accidental file sharing can disclose it. - XML metacharacters in the credential can corrupt the generated plist. This implementati ...[truncated 985 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fetch_xhs_ai.py:469
Finding

Shell Command Injection Through an Unquoted Script Path

Content
View full analysis
/dev/null; echo "{cron_line}") | crontab -', shell=True, check=True, capture_output=True ) ``` ```python script_path = os.path.abspath(__file__) try: subprocess.run( f'crontab -l 2>/dev/null | grep -v "{script_path}" | crontab -', shell=True, check=True, capture_output=True ) ``` ### Technical Analysis A filesystem-derived path is interpolated directly into shell command strings executed with `shell=True`. The path is not shell-quoted, and dangerous characters such as double quotes, command substitutions, semicolons, shell metacharacters, or newlines are not rejected. Although `script_path` is not a normal command-line argument, it can be attacker-influenced when the project is unpacked, cloned, mounted, or renamed under a crafted directory name. Shell parsing occurs before `echo` or `grep` receives the path. The uninstall operation additionally uses `grep -v` against the entire crontab. A crafted path can alter the grep expression or shell syntax, and a broad textual match may remove unrelated entries containing the same string. ### Attack Path 1. An attacker distributes or places the Skill under a directory whose name contains shell syntax, such as command substitution or an injected quote and command. 2. The user invokes `--subscribe` or `--unsubscribe`. 3. `os.path.abspath(__file__)` preserves the malicious directory characters in `script_path`. 4. The path is interpolated into a command passed to `/bin/sh` because `shell=True` is enabled. 5. The shell interprets the injected characters as syntax rather than path data. 6. The injected ...[truncated 473 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fetch_xhs_ai.py:267
Finding

Stored HTML Injection Through Unescaped Remote API Data

Content
View full analysis
' articles_html += f'''
{cover_html}
{title}
{author} 👍 {likes} 🔁 {shares} 💬 {comments}
''' cards_html += f'''
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:82
Finding

Unpinned Third-Party Dependency Installation

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (42)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

This is a classic tool-parameter abuse pattern: shell=True with interpolated script_path lets external filesystem-controlled data influence shell parsing and grep behavior. An attacker who can affect the script location or naming could achieve arbitrary command execution or unintended crontab modification during unsubscribe.

Content

Scanner excerpt · scripts/fetch_xhs_ai.py (reported line 502)May include surrounding context.

python
else:
        script_path = os.path.abspath(__file__)
        try:
            subprocess.run(
                f'crontab -l 2>/dev/null | grep -v "{script_path}" | crontab -',
                shell=True, check=True, capture_output=True
            )

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The README describes automatic scanning of Xiaohongshu content and generation of HTML daily reports, but it does not clearly warn that user requests may trigger outbound API calls and local artifact creation. This lack of transparency can mislead users about data flow and side effects, increasing privacy, compliance, and trust risks in environments where external transmission or file generation must be explicit.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README says users can invoke the skill with broad natural-language requests such as generic Xiaohongshu AI queries. In an agent environment, overly broad triggers can cause unintended activation, leading the skill to fetch external data, consume API quota, and generate outputs when the user did not explicitly intend to use this specific integration.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README instructs users to invoke the skill with very broad natural-language phrases such as general requests for "小红书 AI 热点" or "日报" without defining clear boundaries for when the skill should activate. In an agent ecosystem, this can cause over-triggering or accidental invocation in unrelated contexts, increasing the chance of unintended data access, external API usage, or confusing skill selection behavior.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill advertises and documents capabilities that involve environment access, filesystem writes, network access, and shell execution, but it does not declare any explicit tool scope or permissions boundaries. This creates an authorization gap where an agent may invoke the skill with broader capabilities than users expect, increasing the chance of unintended data access, local persistence, or command execution.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The activation text is broad enough to trigger on generic requests related to AI, 小红书 content, or information feeds, without narrowing to reporting-only use cases. Overbroad triggers can cause the agent to invoke a skill with network, file, and scheduling side effects in situations where the user did not clearly request those actions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill states that it saves HTML reports locally, automatically opens the browser, and can install a daily scheduled subscription, but it does not prominently warn users about these side effects before execution. These behaviors can surprise users, create persistent local changes, and repeatedly perform networked actions without fully informed consent.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/fetch_xhs_ai.py (reported line 38)May include surrounding context.

python
DEFAULT_OUTPUT_DIR = Path.home() / "Downloads" / "QoderReports"
PAGE_SIZE = 50

PLIST_LABEL = "com.qoder.xiaohongshu-ai-feed"
PLIST_DIR = Path.home() / "Library" / "LaunchAgents"

# ─── 终端颜色 ──────────────────────────────────────────────────────────────────────

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/fetch_xhs_ai.py (reported line 39)May include surrounding context.

python
DEFAULT_OUTPUT_DIR = Path.home() / "Downloads" / "QoderReports"
PAGE_SIZE = 50

PLIST_LABEL = "com.qoder.xiaohongshu-ai-feed"
PLIST_DIR = Path.home() / "Library" / "LaunchAgents"

# ─── 终端颜色 ──────────────────────────────────────────────────────────────────────

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/fetch_xhs_ai.py (reported line 487)May include surrounding context.

python
DEFAULT_OUTPUT_DIR = Path.home() / "Downloads" / "QoderReports"
PAGE_SIZE = 50

PLIST_LABEL = "com.qoder.xiaohongshu-ai-feed"
PLIST_DIR = Path.home() / "Library" / "LaunchAgents"

# ─── 终端颜色 ──────────────────────────────────────────────────────────────────────

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill installs and removes OS-level scheduled tasks via LaunchAgents and crontab, creating persistence beyond the immediate feed/report generation action. In this skill context, persistence is not strictly necessary for one-off report generation and increases risk, especially because it modifies user startup/task configuration and later executes network-capable code automatically.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
95% confidence
Finding

This function exists specifically to install a persistent scheduled task, which creates recurring execution on the host. In a report-generation skill, that capability expands operational scope and risk beyond the user's immediate request.

Content

Scanner excerpt · scripts/fetch_xhs_ai.py (reported line 411)May include surrounding context.

python
def install_subscription():
    """安装定时任务,每天自动生成日报"""
    if sys.platform == "darwin":
        PLIST_DIR.mkdir(parents=True, exist_ok=True)
        plist_path = PLIST_DIR / f"{PLIST_LABEL}.plist"

        script_path = os.path.abspath(__file__)

Session Persistence

Medium
Category
Rogue Agent
Confidence
95% confidence
Finding

Constructing a plist path under ~/Library/LaunchAgents prepares installation of a user-level autorun item. This persistence mechanism can cause the script to re-execute automatically and maintain long-lived access to network/API capabilities.

Content

Scanner excerpt · scripts/fetch_xhs_ai.py (reported line 412)May include surrounding context.

python
"""安装定时任务,每天自动生成日报"""
    if sys.platform == "darwin":
        PLIST_DIR.mkdir(parents=True, exist_ok=True)
        plist_path = PLIST_DIR / f"{PLIST_LABEL}.plist"

        script_path = os.path.abspath(__file__)
        log_path = str(Path.home() / "Library" / "Logs" / "qoder-xhs-ai-feed.log")

Session Persistence

Medium
Category
Rogue Agent
Confidence
95% confidence
Finding

Constructing a plist path under ~/Library/LaunchAgents prepares installation of a user-level autorun item. This persistence mechanism can cause the script to re-execute automatically and maintain long-lived access to network/API capabilities.

Content

Scanner excerpt · scripts/fetch_xhs_ai.py (reported line 412)May include surrounding context.

python
"""安装定时任务,每天自动生成日报"""
    if sys.platform == "darwin":
        PLIST_DIR.mkdir(parents=True, exist_ok=True)
        plist_path = PLIST_DIR / f"{PLIST_LABEL}.plist"

        script_path = os.path.abspath(__file__)
        log_path = str(Path.home() / "Library" / "Logs" / "qoder-xhs-ai-feed.log")

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

When installing the LaunchAgent, the code writes the API key into a persistent plist file in the user's home directory. That expands the secret's exposure window and may leak credentials to local users, backups, system inspection tools, or accidental file sharing, especially because the user is not clearly warned that the key will be stored on disk.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
96% confidence
Finding

The generated plist content includes persistent configuration for a LaunchAgent and embeds the API key into its environment variables. This combines persistence with credential storage, increasing both recurring execution risk and secret exposure.

Content

Scanner excerpt · scripts/fetch_xhs_ai.py (reported line 427)May include surrounding context.

python
<string>{api_key}</string>
        </dict>"""

        plist_content = f'''<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>

Session Persistence

Medium
Category
Rogue Agent
Confidence
95% confidence
Finding

Generating a plist document is part of creating macOS user persistence. In this context, persistence is more dangerous because the job will repeatedly run code that fetches remote data and writes local files without further prompts.

Content

Scanner excerpt · scripts/fetch_xhs_ai.py (reported line 428)May include surrounding context.

python
</dict>"""

        plist_content = f'''<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>

Session Persistence

Medium
Category
Rogue Agent
Confidence
95% confidence
Finding

Generating a plist document is part of creating macOS user persistence. In this context, persistence is more dangerous because the job will repeatedly run code that fetches remote data and writes local files without further prompts.

Content

Scanner excerpt · scripts/fetch_xhs_ai.py (reported line 428)May include surrounding context.

python
</dict>"""

        plist_content = f'''<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>

Session Persistence

Medium
Category
Rogue Agent
Confidence
94% confidence
Finding

Setting up the plist body contributes directly to a persistent LaunchAgent configuration. The issue is not this line alone, but its role in establishing recurring unattended execution for a networked tool.

Content

Scanner excerpt · scripts/fetch_xhs_ai.py (reported line 429)May include surrounding context.

python
plist_content = f'''<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>{PLIST_LABEL}</string>

Session Persistence

Medium
Category
Rogue Agent
Confidence
94% confidence
Finding

Specifying ProgramArguments in the plist defines what code will run automatically on schedule. That creates a durable execution path for the script and broadens the impact of any future code or content compromise.

Content

Scanner excerpt · scripts/fetch_xhs_ai.py (reported line 432)May include surrounding context.

python
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>{PLIST_LABEL}</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/python3</string>

Session Persistence

Medium
Category
Rogue Agent
Confidence
94% confidence
Finding

Finalizing the plist content with env_section completes the persistent autorun configuration and may also persist the API key. This increases both execution persistence and credential lifetime on disk.

Content

Scanner excerpt · scripts/fetch_xhs_ai.py (reported line 453)May include surrounding context.

python
<key>RunAtLoad</key>
    <false/>{env_section}
</dict>
</plist>'''

        plist_path.write_text(plist_content, encoding="utf-8")

Session Persistence

Medium
Category
Rogue Agent
Confidence
96% confidence
Finding

Writing the plist to ~/Library/LaunchAgents materially installs a persistence artifact on disk. Once present and loaded, it enables unattended re-execution of the script and persists beyond the current session.

Content

Scanner excerpt · scripts/fetch_xhs_ai.py (reported line 455)May include surrounding context.

python
</dict>
</plist>'''

        plist_path.write_text(plist_content, encoding="utf-8")

        try:
            subprocess.run(["launchctl", "load", str(plist_path)],

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/fetch_xhs_ai.py (reported line 458)May include surrounding context.

python
plist_path.write_text(plist_content, encoding="utf-8")

        try:
            subprocess.run(["launchctl", "load", str(plist_path)],
                           check=True, capture_output=True)
            info("订阅成功! 每天 16:00 自动生成小红书 AI 日报")
            info(f"日报目录: ~/Downloads/QoderReports/")

Session Persistence

Medium
Category
Rogue Agent
Confidence
97% confidence
Finding

Loading the plist via launchctl activates the persistence mechanism, causing scheduled future execution. Because this skill fetches remote data and may store secrets for the task, persistence meaningfully increases risk in this context.

Content

Scanner excerpt · scripts/fetch_xhs_ai.py (reported line 458)May include surrounding context.

python
plist_path.write_text(plist_content, encoding="utf-8")

        try:
            subprocess.run(["launchctl", "load", str(plist_path)],
                           check=True, capture_output=True)
            info("订阅成功! 每天 16:00 自动生成小红书 AI 日报")
            info(f"日报目录: ~/Downloads/QoderReports/")

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
98% confidence
Finding

This code builds a shell command string and executes it with shell=True while interpolating script_path into the command. If the script resides in a path containing shell metacharacters or quotes, an attacker could trigger command injection when the subscription feature is used, leading to arbitrary command execution under the current user account.

Content

Scanner excerpt · scripts/fetch_xhs_ai.py (reported line 471)May include surrounding context.

python
script_path = os.path.abspath(__file__)
        cron_line = f"0 16 * * * /usr/bin/python3 {script_path} --no-open"
        try:
            subprocess.run(
                f'(crontab -l 2>/dev/null; echo "{cron_line}") | crontab -',
                shell=True, check=True, capture_output=True
            )

Static analysis

No suspicious patterns detected.