Back to skill

Security audit

AI视频号信息源

Security checks for vulnerabilities and agentic risk

Overview

The report feature is coherent, but the subscription and HTML generation paths create review-worthy risks around persistent credentials, scheduled execution, command injection, and unsafe generated reports.

Review before installing, especially if you plan to use --subscribe. Prefer one-shot runs with --no-open, use a scoped and revocable RedFox API key, avoid installing from paths with unusual shell characters, and do not enable the daily scheduler until plaintext credential storage, crontab shell usage, and HTML escaping are fixed.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fetch_sph_ai.py:281
Finding

Unescaped API Data Enables Persistent Script Injection in Generated Reports

Content
View full analysis
' articles_html += f'''
{cover_html}
{title}
{author} 👍 {likes} 🔁 {shares} 💬 {comments}
''' ``` The generated content is then written to disk and opened automatically: ```python html = html.replace("{{CATEGORY_CARDS}}", category_cards) output_path.write_text(html_content, encoding="utf-8") 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) ``` ### Technical Analysis The report generator treats fields returned by the remote API—including titles, authors, categories, and co ...[truncated 1976 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/fetch_sph_ai.py:424
Finding

API Credential Is Persisted in Plaintext in a 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 When `--subscribe` is used on macOS, the script copies `REDFOX_API_KEY` from the process environment into a persistent LaunchAgent property-list file. The key is stored as ordinary XML text under `~/Library/LaunchAgents`. The script does not explicitly create the file with restrictive permissions, does not use an operating-system credential store, and does not warn that the secret will be copied into a persistent file. This also conflicts with the documentation's instruction not to expose the key in files. Although persistence is necessary for the declared daily subscription feature, persisting the authentication secret in plaintext exceeds the minimum safe credential-ha ...[truncated 1041 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fetch_sph_ai.py:475
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 ) info("订阅成功! 每天 16:00 自动生成视频号 AI 日报 (crontab)") info(f"日报目录: ~/Downloads/QoderReports/") return True except subprocess.CalledProcessError: warn("自动配置 crontab 失败,请手动添加:") print(f" {cron_line}") return False ``` The unsubscription path has the same weakness: ```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 ) info("已取消订阅,crontab 任务已移除") return True except subprocess.CalledProcessError: warn("自动移除 crontab 失败,请手动执行: crontab -e") return False ``` ### Technical Analysis The absolute path of the running script is interpolated into shell command strings and passed to `subprocess.run(..., shell=True)`. The path is not shell-quoted. File and directory names may legally contain spaces, quotes, command-substitution syntax, semicolons, and other shell metacharacters. If the Skill is installed under an attacker-chosen path, these characters are interpreted by the shell rather than treated as literal path content. Both subscription and unsubscription are affected. The resulting commands execute with all privileges of the user invoking the script. ### Attack Path 1. An attacker distributes, extracts, moves, or renames the project into a directory whose name contains a shell payload. 2. The victim invokes `--subscribe` or `--unsubscribe`. 3. `os.path.abspath(__file__)` returns the attacker-crafted path. 4. The path is inserted into a comman ...[truncated 890 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:81
Finding

Third-Party Dependency Is Installed Without Version or Integrity Pinning

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill description focuses on generating an AI content report, but the behavior also includes installing persistent scheduled tasks, removing them, opening browser content, and embedding a sensitive API key into a macOS LaunchAgent plist. This mismatch is dangerous because persistence and secret handling materially increase host risk, and users may not realize the skill modifies the system or stores credentials in a recoverable location.

Content

No source excerpt is available for this finding.

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · assets/report_template.html (reported line 8)May include surrounding context.

html
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI视频号信息源 - {{DATE}}</title>

<!-- Fonts: Archivo Black (display) + Space Grotesk (body) -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Archivo+Black&family=Space+Grotesk:wght@300;400;500;600;700&display=swap" rel="stylesheet">

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The code reads the API key from the environment and embeds it into a LaunchAgent plist stored on disk. That creates a persistent plaintext credential copy that may be readable by local processes, backups, or users with filesystem access, increasing credential exposure far beyond runtime memory use.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
98% confidence
Finding

Embedding script_path inside a shell command used for grep and crontab manipulation creates a tool parameter abuse risk. If an attacker can influence the installation path or filename, shell metacharacters may break out of the intended command and execute arbitrary commands under the user's privileges.

Content

Scanner excerpt · scripts/fetch_sph_ai.py (reported line 508)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
            )

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · scripts/fetch_sph_ai.py (reported line 522)May include surrounding context.

python
warn("自动移除 crontab 失败,请手动执行: crontab -e")
            return False


# ─── 主流程 ────────────────────────────────────────────────────────────────────────
def main():
    parser = argparse.ArgumentParser(
        description="AI视频号信息源 — 每日 AI 相关视频号热门内容聚合",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  python3 fetch_sph_ai.py
  python3 fetch_sph_ai.py --keyword "ChatGPT"
  python3 fetch_sph_ai.py --start-time 2026-06-09 --end-time 2026-06-10
  python3 fetch_sph_ai.py --subscribe
  python3 fetch_sph_ai.py --unsubscribe
        """,
    )
    parser.add_argument("--keyword", default=DEFAULT_KEYWORD,
                        help=f"搜索关键词 (默认: {DEFAULT_KEYWORD})")
    parser.add_argument("--page-size", type=i

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README says users can invoke the skill by broadly describing their need in natural language, and the example triggers are generic phrases around AI video reports. This can cause the skill to activate unintentionally in loosely related conversations, leading to unexpected external data access or report generation without clear user intent.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README says users can 'directly use natural language descriptions' and gives short trigger examples like '看看视频号 AI 热点' and '视频号 AI 日报'. While somewhat domain-related, the file does not clearly define exact trigger constraints, activation boundaries, or negative examples, which can make invocation behavior ambiguous in normal conversation.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill advertises operational behavior that includes network access, environment-variable use, shell execution, and file read/write, but the manifest does not declare any permissions or allowed-tools scope. That removes an important transparency and consent boundary, making it easier for a user or orchestrator to invoke capabilities with broader system impact than the metadata suggests.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest description says the skill should be used when the user needs "AI 视频号日报、视频号AI热点、AI视频号内容、视频号信息源". Several of these phrases, especially "AI视频号内容" and "视频号信息源", are broad topical descriptions rather than specific invocation triggers, which can overlap with ordinary user requests and make activation boundaries unclear.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The manifest and user-facing instructions are entirely in Chinese and describe outputs such as a Chinese-titled daily report, but there is no statement that the skill is China/Chinese-specific or that users may choose another language. Under the language/locale policy, forcing a specific language without opt-in can be a natural-language policy issue.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The markdown mentions subscription commands but does not clearly warn that enabling subscription installs a local scheduled task and writes recurring reports to disk. Hidden persistence and disk writes reduce informed consent and can surprise users with ongoing execution, local artifacts, and repeated network activity.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The HTML template explicitly sets the document language to "zh-CN", which hard-codes a specific locale. Under the policy, locale restrictions should either be user-selectable or clearly justified as region-specific; this file provides neither.

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_sph_ai.py (reported line 38)May include surrounding context.

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

PLIST_LABEL = "com.qoder.wechat-channels-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_sph_ai.py (reported line 39)May include surrounding context.

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

PLIST_LABEL = "com.qoder.wechat-channels-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_sph_ai.py (reported line 418)May include surrounding context.

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

PLIST_LABEL = "com.qoder.wechat-channels-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_sph_ai.py (reported line 434)May include surrounding context.

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

PLIST_LABEL = "com.qoder.wechat-channels-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_sph_ai.py (reported line 438)May include surrounding context.

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

PLIST_LABEL = "com.qoder.wechat-channels-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_sph_ai.py (reported line 493)May include surrounding context.

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

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

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

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill advertises report generation but also installs persistent scheduled execution through LaunchAgents or crontab. Persistence changes the trust model significantly because the code will continue running automatically and repeatedly access network resources and local files after the initial invocation.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
94% confidence
Finding

This function explicitly installs a recurring scheduled task. In the context of a content-reporting skill, adding OS-level persistence increases risk because ongoing execution continues without fresh user review and expands the attack surface if the script or remote service is later compromised.

Content

Scanner excerpt · scripts/fetch_sph_ai.py (reported line 417)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
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_sph_ai.py (reported line 418)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-wechat-channels-ai-feed.log")

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_sph_ai.py (reported line 433)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-wechat-channels-ai-feed.log")

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_sph_ai.py (reported line 434)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-wechat-channels-ai-feed.log")

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_sph_ai.py (reported line 435)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-wechat-channels-ai-feed.log")

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_sph_ai.py (reported line 459)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-wechat-channels-ai-feed.log")

Static analysis

No suspicious patterns detected.