Back to skill

Security audit

AC Milan Match Monitor

Security checks for vulnerabilities and agentic risk

Overview

This AC Milan match notifier has some under-documented sports/news behavior, but I found no evidence of credential access, exfiltration, destructive actions, or hidden privilege escalation.

Install only if you are comfortable with a scheduled Python script contacting ESPN and Google News, producing Chinese-language AC Milan match summaries, and using a local schedule.json file. The author should update SKILL.md to mention Google News, the YouTube search link, and the optional schedule update script.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (17)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The description mostly matches the core behavior of checking whether AC Milan played yesterday and being silent when no match is found, and it does use ESPN without authentication. However, it is not accurately represented overall because the code does more than the description states and uses additional resources. Specifically, it first depends on a local schedule.json file to determine whether to proceed, so it is not purely an ESPN-only check. It also accesses Google News RSS and creates a YouTube highlights search link, expanding the skill beyond simply sending the result. These are material undeclared capabilities and resource accesses, so this should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description says the skill checks whether AC Milan played yesterday and sends the result, remaining silent if no match. The code does something materially different: it queries ESPN scoreboard ranges for future dates, keeps only upcoming Milan matches, and stores them in schedule.json as a fixture list. It does not inspect yesterday's games, does not extract scores/results, and does not send a push/notification. It also performs local file write/update behavior that is not declared. Comments and logic indicate a weekly schedule-maintenance script, which conflicts with the stated daily 8:30 result-checking purpose.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding

The skill instructs the agent to run a local Python script via shell and to place files in the skill folder, but it declares no explicit tool scope or permissions. This creates an authorization gap: a reviewer or runtime may treat the skill as low-risk while it still expects code execution and filesystem interaction, increasing the chance of unintended shell or file-write capability exposure.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The natural-language docstring and all user-facing output strings are fixed in Chinese, which can violate language/locale policy when no choice or opt-in is provided. There is no indication that the skill is region-specific or intentionally restricted to Chinese-speaking users.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The docstring states '有则查结果+集锦+新闻' immediately after identifying ESPN public API as the data source, which implies those items are obtained from ESPN. In reality, the implementation builds a YouTube search link for highlights and queries Google News RSS for news, so the documentation misrepresents what the code actually does.

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

python
def get_name(abbr):
    return TEAM_ABBR.get(abbr, abbr)

r = subprocess.run(
    ["/usr/bin/curl", "-s",
     "https://site.api.espn.com/apis/site/v2/sports/soccer/ita.1/teams/103/schedule?limit=5"],
    capture_output=True, text=True, timeout=15

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill description says it checks whether AC Milan played and sends the result, but the implementation also contacts Google News and outputs YouTube search links. This mismatch expands external data flows and user-visible behavior beyond what the manifest promises, which can undermine informed consent and trust in an automated skill.

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

python
news_query = f"AC+Milan+{opp_name}+Serie+A".replace(" ", "+")
rss_url = f"https://news.google.com/rss/search?q={news_query}&hl=en&gl=US&ceid=US:en"

news_r = subprocess.run(
    ["/usr/bin/curl", "-s", "-L", "--max-time", "10", rss_url],
    capture_output=True, text=True, timeout=15
)

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script's behavior materially differs from the declared skill purpose: instead of only checking whether AC Milan played yesterday, it fetches and persists a 6-month future schedule. This kind of scope drift is dangerous because it expands data handling and execution behavior beyond what operators expect, which can hide unwanted functionality or cause users to grant trust under false pretenses.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The embedded documentation says the script runs weekly at 07:00 for schedule maintenance, while the skill metadata describes a daily 08:30 result-checker. Contradictory operational descriptions can mislead deployers about when code runs and what it does, reducing the chance that unexpected persistence or network activity is noticed during review.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The module docstring is written entirely in Chinese and later data mappings/output are localized to Chinese, indicating the skill is designed to operate in a specific language/locale. The file does not provide any user opt-in or alternative language handling, which can violate language/locale policy when no justified region-specific constraint is stated.

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

python
]

for start, end in end_dates:
    r = subprocess.run(
        ["/usr/bin/curl", "-s",
         f"https://site.api.espn.com/apis/site/v2/sports/soccer/ita.1/scoreboard?limit=100&dates={start}-{end}"],
        capture_output=True, text=True, timeout=15

Vague Triggers

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This markdown file says the skill is "Perfect for daily 8:30 AM cron push" but does not clearly constrain when it should or should not be invoked beyond a general scheduled use. For a manifest-like description, this can be interpreted broadly without explicit trigger boundaries or negative examples.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill makes an external request to ESPN but does not clearly warn that using the public API reveals network metadata such as the caller's IP address and request timing. While common for networked skills, failing to disclose outbound communication can undermine user expectations and privacy review, especially in automated cron contexts.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The note field is written entirely in Chinese and specifies Beijing time, which imposes a language and locale assumption in natural-language content. There is no indication that users can choose another language or locale, nor that this file is explicitly limited to a China-specific audience.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The script invokes curl to contact ESPN and later Google News, which transmits request metadata to external services. While the module docstring mentions ESPN as a data source, there is no visible user-facing print, prompt, or warning in the executable flow disclosing these outbound network calls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The additional Google News request is less clearly implied by the skill description than the ESPN match lookup, so it introduces undisclosed third-party network access beyond the core advertised function. In an agent context, hidden external calls can matter because they change data-sharing boundaries and behavior users may not expect.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.