Back to skill

Security audit

AI抖音信息源

Security checks across malware telemetry and agentic risk

Overview

The skill mostly does what it says, but its optional subscription feature installs persistent scheduled jobs and can store an API key on disk without enough warning.

Install only if you are comfortable giving this skill a RedFox API key, letting it query redfox.hk, writing reports under ~/Downloads/QoderReports, and optionally adding a daily scheduled job. Avoid --subscribe unless you understand that it modifies LaunchAgents or crontab; on macOS it may store REDFOX_API_KEY in a plist. Prefer running reports manually with --no-open, and inspect or remove any scheduler entry if you stop using it.

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

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
90% confidence
Finding
The skill advertises executable behavior that uses environment variables, file reads/writes, network access, and shell execution, but it does not declare permissions up front. This weakens user consent and reviewability because users cannot clearly assess that the skill will access local files, contact external services, and invoke system-level commands before running it.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The documented purpose focuses on producing a Douyin AI report, but the behavior also includes persistence via launchd/crontab, local agent/log file creation, automatic browser launching, and transmission to a third-party API provider. This mismatch is dangerous because users may authorize a seemingly simple content-report skill without realizing it installs recurring jobs, persists on the host, and sends data off-device.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The skill's stated purpose is feed aggregation and report generation, but it also installs and removes persistent scheduled tasks at the OS level. That broadens its authority and attack surface, especially because persistence is not necessary for one-off report generation and can surprise users.

Intent-Code Divergence

Low
Confidence
83% confidence
Finding
The documentation suggests direct Douyin keyword searching, but the implementation sends user queries and credentials to a third-party Redfox API. This mismatch matters because users may not realize their inputs and API key are being shared with an external service, affecting trust and data handling expectations.

Vague Triggers

Medium
Confidence
84% confidence
Finding
The README states the skill should be used whenever a user asks for broad phrases like 'AI 抖音日报', '抖音AI热点', 'AI抖音内容', '抖音信息源', or 'douyin ai feed'. This kind of wide invocation guidance can cause the agent to trigger the skill for loosely related requests, increasing the chance of unintended external data access, unnecessary API-key-backed operations, or user confusion about why the skill activated.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The README instructs users to invoke the skill with very broad natural-language phrases such as generic requests for '抖音 AI 热点' or '日报', without defining clear routing boundaries or requiring explicit confirmation. In an agent ecosystem, this can cause overbroad or accidental activation, leading the skill to run when the user intended a different tool, which may trigger unintended external API calls and data retrieval.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The subscription feature is described as a convenience option, but the documentation does not prominently warn that it installs a persistent local scheduled task that will continue executing automatically. Persistence changes the risk profile substantially because it creates ongoing network activity, repeated local writes, and a foothold that users may forget is active.

Missing User Warnings

Low
Confidence
80% confidence
Finding
Automatically opening a browser and writing reports to a local directory are lower-risk behaviors, but they still affect user environment and privacy and are not prominently surfaced as side effects. In some contexts this could expose sensitive report contents on screen unexpectedly or clutter trusted locations with generated files.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
During subscription setup on macOS, the script reads the API key from the environment and embeds it into a LaunchAgent plist on disk. Persisting a credential in a config file without a clear warning increases exposure to other local users, backups, and forensic recovery, and turns a transient secret into a stored one.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill automatically appends a cron entry without an upfront warning or confirmation, modifying persistent user configuration as a side effect. Even if initiated via --subscribe, silent crontab mutation is risky because it changes system behavior and can be abused if users do not understand the persistence being installed.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The unsubscribe path rewrites the user's crontab automatically, again without confirmation and using a brittle text filter. This can unintentionally remove or corrupt entries and changes persistent configuration in a way users may not expect.

Env Variable Harvesting

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

        env_section = ""
        api_key = os.environ.get(ENV_KEY, "").strip()
        if api_key:
            env_section = f"""
        <key>EnvironmentVariables</key>
Confidence
94% 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
98% confidence
Finding
subprocess.run( f'crontab -l 2>/dev/null | grep -v "{script_path}" | crontab -', shell=True, check=True, capture_output

Unvalidated Output Injection

High
Category
Output Handling
Content
# ── 打开浏览器 ──
    if not args.no_open:
        if sys.platform == "darwin":
            subprocess.run(["open", str(output_path)], check=False)
        elif sys.platform == "linux":
            subprocess.run(["xdg-open", str(output_path)], check=False)
        info(f"浏览器已打开: {output_path}")
Confidence
90% confidence
Finding
subprocess.run(["open", str(output

Unvalidated Output Injection

High
Category
Output Handling
Content
if sys.platform == "darwin":
            subprocess.run(["open", str(output_path)], check=False)
        elif sys.platform == "linux":
            subprocess.run(["xdg-open", str(output_path)], check=False)
        info(f"浏览器已打开: {output_path}")

    print(f"\n{GREEN}{BOLD}✓ 完成!{RESET}")
Confidence
90% confidence
Finding
subprocess.run(["xdg-open", str(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
93% 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
95% 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-douyin-ai-feed.log")
Confidence
95% 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-douyin-ai-feed.log")
Confidence
95% 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-douyin-ai-feed.log")
Confidence
95% 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-douyin-ai-feed.log")
Confidence
95% 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
92% 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
92% confidence
Finding
plist

VirusTotal

VirusTotal findings are pending for this skill version.

View on VirusTotal

Static analysis

No suspicious patterns detected.