Back to skill

Security audit

AI小红书信息源

Security checks across malware telemetry and agentic risk

Overview

The skill’s core report generation is coherent, but its subscription feature creates persistent scheduled jobs and can store an API key on disk without clear disclosure.

Install only if you are comfortable giving the skill a RedFox API key and letting it contact redfox.hk and write reports under ~/Downloads/QoderReports. Avoid --subscribe unless you have reviewed the LaunchAgent or crontab behavior; on macOS it may store REDFOX_API_KEY in a plist file. Treat generated HTML reports as containing untrusted remote content.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (26)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
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
            )
Confidence
96% confidence
Finding
subprocess.run( f'(crontab -l 2>/dev/null; echo "{cron_line}") | crontab -', shell=True, check=True, capture_output=True )

subprocess module call

Medium
Category
Dangerous Code Execution
Content
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
            )
Confidence
98% confidence
Finding
subprocess.run( f'crontab -l 2>/dev/null | grep -v "{script_path}" | crontab -', shell=True, check=True, capture_output=True )

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill advertises capabilities that require access to environment variables, the filesystem, network, and shell execution, but it does not declare permissions or boundaries for those actions. This creates a transparency and consent problem: users cannot readily assess that the skill will read API keys, write reports locally, contact external services, and potentially install or invoke shell-based behavior.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The skill installs and removes OS-level scheduled tasks, which exceeds a simple one-shot report generator and creates persistence on the host. In an agent skill context, persistence is security-relevant because it changes system state over time and may continue running with stored credentials after the original invocation.

Vague Triggers

Medium
Confidence
84% confidence
Finding
The invocation guidance is broad enough that common phrases like '小红书 AI 热点' or '小红书 AI 日报' could trigger the skill in situations where the user did not explicitly intend to invoke this specific integration. This can cause unintended data retrieval or skill activation, especially in environments with multiple overlapping content-discovery skills.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The skill offers a '--subscribe' feature that installs a daily scheduled task, but the documentation does not disclose how persistence is implemented, what exact command will run, where the job is registered, or how users can inspect it. Silent or poorly explained persistence is risky because it creates ongoing execution with network, file write, and environment access beyond the initial user action.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The code reads the API key from the environment and embeds it into a LaunchAgent plist, persisting the credential on disk without a clear warning. This increases exposure because local users, backups, or other software may recover the key from the plist or related artifacts.

Missing User Warnings

Medium
Confidence
99% confidence
Finding
The report generator injects remote fields like title, author, category, cover URL, and links directly into HTML without escaping. If the upstream API returns malicious markup or javascript-like payloads, opening the generated report can trigger stored XSS or dangerous browser behavior from a local file.

Env Variable Harvesting

High
Category
Data Exfiltration
Content
log_path = str(Path.home() / "Library" / "Logs" / "qoder-xhs-ai-feed.log")

        env_section = ""
        api_key = os.environ.get(ENV_KEY, "").strip()
        if api_key:
            env_section = f"""
        <key>EnvironmentVariables</key>
Confidence
90% confidence
Finding
os.environ.get(ENV_KEY

Unvalidated Output Injection

High
Category
Output Handling
Content
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
            )
Confidence
97% confidence
Finding
subprocess.run( f'crontab -l 2>/dev/null | grep -v "{script_path}" | crontab -', shell=True, check=True, capture_output

Session Persistence

Medium
Category
Rogue Agent
Content
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
            )
            info("订阅成功! 每天 16:00 自动生成小红书 AI 日报 (crontab)")
Confidence
94% confidence
Finding
crontab -l

Session Persistence

Medium
Category
Rogue Agent
Content
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__)
Confidence
93% confidence
Finding
PLIST

Session Persistence

Medium
Category
Rogue Agent
Content
"""安装定时任务,每天自动生成日报"""
    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")
Confidence
90% confidence
Finding
plist

Session Persistence

Medium
Category
Rogue Agent
Content
"""安装定时任务,每天自动生成日报"""
    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")
Confidence
90% confidence
Finding
PLIST

Session Persistence

Medium
Category
Rogue Agent
Content
"""安装定时任务,每天自动生成日报"""
    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")
Confidence
90% confidence
Finding
PLIST

Session Persistence

Medium
Category
Rogue Agent
Content
"""安装定时任务,每天自动生成日报"""
    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")
Confidence
90% confidence
Finding
plist

Session Persistence

Medium
Category
Rogue Agent
Content
<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>
Confidence
88% confidence
Finding
plist

Session Persistence

Medium
Category
Rogue Agent
Content
</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>
Confidence
88% confidence
Finding
plist

Session Persistence

Medium
Category
Rogue Agent
Content
</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>
Confidence
88% confidence
Finding
PLIST

Session Persistence

Medium
Category
Rogue Agent
Content
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>
Confidence
88% confidence
Finding
plist

Session Persistence

Medium
Category
Rogue Agent
Content
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>{PLIST_LABEL}</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/python3</string>
Confidence
88% confidence
Finding
PLIST

Session Persistence

Medium
Category
Rogue Agent
Content
<key>RunAtLoad</key>
    <false/>{env_section}
</dict>
</plist>'''

        plist_path.write_text(plist_content, encoding="utf-8")
Confidence
89% confidence
Finding
plist

Session Persistence

Medium
Category
Rogue Agent
Content
</dict>
</plist>'''

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

        try:
            subprocess.run(["launchctl", "load", str(plist_path)],
Confidence
90% confidence
Finding
plist

Session Persistence

Medium
Category
Rogue Agent
Content
</dict>
</plist>'''

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

        try:
            subprocess.run(["launchctl", "load", str(plist_path)],
Confidence
90% confidence
Finding
plist

Session Persistence

Medium
Category
Rogue Agent
Content
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/")
Confidence
91% confidence
Finding
plist

VirusTotal

VirusTotal findings are pending for this skill version.

View on VirusTotal

Static analysis

No suspicious patterns detected.