Back to skill

Security audit

Football Betting Analyzer

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches a football betting-analysis purpose, but it includes high-impact billing code with a hardcoded payment API key and weak user-control boundaries.

Review carefully before installing. This skill can provide football and odds analysis, but it also includes payment logic that can charge a SkillPay account, sends a user ID to an external billing service, and ships a plaintext billing API key. Do not install unless you trust the publisher, understand the 0.01 USDT per-call model, and are comfortable with Chinese-only betting-related output and the local file-write helper risk.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
payment.py:11
Finding

Hard-Coded Billing API Credential Exposed in Source Code

Content
View full analysis

Vulnerability Details

File Location: payment.py, lines 11-18
Vulnerability Type: Hard-coded secret and reusable API credential
Risk Level: High

Vulnerable Code

python
BILLING_API_URL = "https://skillpay.me"
BILLING_API_KEY = "sk_f03aa8f8bbcf79f7aa11c112d904780f22e62add1464e3c41a79600a451eb1d2"
SKILL_ID = "a6b430c1-2bef-4879-b60b-4ad25d086577"
SKILL_NAME = "football-betting-analyzer"
PRICE_PER_CALL = 0.01  # USDT

HEADERS = {
    "X-API-Key": BILLING_API_KEY,
    "Content-Type": "application/json"
}

The credential is subsequently transmitted in requests such as:

python
resp = requests.post(
    f"{BILLING_API_URL}/api/v1/billing/charge",
    headers=HEADERS,
    json={
        "user_id": user_id,
        "skill_id": SKILL_ID,
        "amount": PRICE_PER_CALL,
    },
    timeout=10
)

Technical Analysis

The billing API key is embedded directly in distributed source code. Any user who downloads, installs, or otherwise obtains the project can extract and reuse it outside the intended Skill execution context.

This also conflicts with _meta.json, which declares SKILLPAY_API_KEY as the expected environment-based credential source. Although requests are sent over HTTPS, transport encryption does not protect a secret already exposed in the local package.

The same static credential is attached to balance, charge, and payment-link requests. The actual severity of unauthorized operations depends on the billing service's server-side authorization controls, but client-side code cannot keep a shared secret confidential.

Attack Path

  1. An attacker obtains a copy of the publicly distributed or locally installed Skill.
  2. The attacker opens payment.py and extracts BILLING_API_KEY.
  3. The attacker constructs requests to the fixed SkillPay billing endpoints using the extracted value in the X-API-Key header.
  4. The attacker supplies chosen user IDs, ...[truncated 889 chars]
Remediation
View remediation

Remediation Suggestions

  1. Immediately revoke and rotate the exposed API key.

  2. Remove the credential from source code and version-control history.

  3. Load the key from the declared environment variable and fail closed when it is absent:

    python
    BILLING_API_KEY = os.environ.get("SKILLPAY_API_KEY")
    if not BILLING_API_KEY:
        raise RuntimeError("SKILLPAY_API_KEY is required")
    
  4. Never distribute a privileged shared secret in client-side Skill packages. Prefer short-lived, user-scoped tokens or a trusted server-side billing proxy.

  5. Restrict the replacement credential to the exact Skill ID and minimum required billing operations.

  6. Enforce authorization, permitted amounts, user-to-session binding, replay protection, and rate limits on the billing server.

  7. Avoid logging the credential or complete authenticated request headers.

  8. Add automated secret scanning to CI and pre-commit checks.

  9. Review billing logs for unauthorized use of the exposed key.

T09 · Insecure Skill Coding Practices

Error
Location
utils.py:220
Finding

Path Traversal and Arbitrary File Overwrite Through Unvalidated Output Filename

Content
View full analysis

Vulnerability Details

File Location: utils.py, lines 220-229
Vulnerability Type: Path traversal and unrestricted file write
Risk Level: High

Vulnerable Code

python
def save_analysis_to_file(analysis: Dict, filename: Optional[str] = None) -> str:
    """保存分析结果到文件"""
    if filename is None:
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f"analysis_{timestamp}.json"

    filepath = os.path.join(os.path.dirname(__file__), "outputs", filename)
    os.makedirs(os.path.dirname(filepath), exist_ok=True)

    with open(filepath, "w", encoding="utf-8") as f:
        json.dump(analysis, f, ensure_ascii=False, indent=2)

    return filepath

Technical Analysis

The function accepts a caller-controlled filename and joins it to the intended outputs directory without validating the resulting path. Python's path handling permits .. traversal components, and an absolute filename can cause earlier path components to be discarded.

The function then creates parent directories and opens the resolved path in write mode. Write mode truncates an existing file before storing attacker-influenced JSON content. No canonical-path containment check, filename allowlist, symlink protection, or exclusive-creation policy is applied.

Exploitation requires an attacker to control the filename argument through a caller or integration. The reviewed project does not expose this function directly through a network endpoint, so exploitability depends on how the package is embedded or invoked.

Attack Path

  1. An attacker gains control of the filename passed to save_analysis_to_file.
  2. The attacker supplies a traversal path such as ../../../target.json or an absolute path to a writable file.
  3. os.path.join constructs a path outside the intended outputs directory.
  4. os.makedirs creates attacker-selected parent directories where permissions allow.
  5. `open(f ...[truncated 916 chars]
Remediation
View remediation

Remediation Suggestions

  1. Reject absolute paths and filenames containing directory separators or traversal components.

  2. Restrict filenames to a conservative allowlist, such as letters, digits, underscores, hyphens, and a .json suffix.

  3. Resolve both the output directory and destination path, then verify containment before writing:

    python
    from pathlib import Path
    import re
    
    output_dir = (Path(__file__).parent / "outputs").resolve()
    output_dir.mkdir(parents=True, exist_ok=True)
    
    if not re.fullmatch(r"[A-Za-z0-9_-]+\.json", filename):
        raise ValueError("Invalid output filename")
    
    destination = (output_dir / filename).resolve()
    if output_dir not in destination.parents:
        raise ValueError("Output path escapes the permitted directory")
    
  4. Generate filenames internally when caller-selected names are unnecessary.

  5. Use exclusive creation mode ("x") when overwriting is not required.

  6. If existing files must be replaced, write to a securely created temporary file in the same directory and atomically rename it.

  7. Protect against symlink redirection with platform-appropriate no-follow file-opening controls.

  8. Run the Skill under a minimally privileged account with write access limited to its dedicated output directory.

  9. Add tests covering ../, absolute paths, nested separators, encoded traversal forms, and symlink targets.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (37)

Tainted flow: 'user_id' from os.environ.get (line 96, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · payment.py (reported line 29)May include surrounding context.

python
def check_balance(user_id: str) -> float:
    """查询用户余额"""
    try:
        resp = requests.get(
            f"{BILLING_API_URL}/api/v1/billing/balance",
            params={"user_id": user_id},
            headers=HEADERS,

Tainted flow: 'user_id' from os.environ.get (line 96, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
94% confidence
Finding

The code performs a charge request to an external service using a user identity taken from an environment variable, with no integrity check that the value is authentic or bound to the actual caller. In a multi-tenant or untrusted runtime, an attacker who can influence SKILLPAY_USER_ID could trigger charges against another account or force misbilling.

Content

Scanner excerpt · payment.py (reported line 48)May include surrounding context.

python
返回: {"ok": bool, "balance": float, "payment_url": str|None}
    """
    try:
        resp = requests.post(
            f"{BILLING_API_URL}/api/v1/billing/charge",
            headers=HEADERS,
            json={

Tainted flow: 'user_id' from os.environ.get (line 96, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · payment.py (reported line 79)May include surrounding context.

python
def get_payment_link(user_id: str, amount: float = 5.0) -> str:
    """生成充值链接"""
    try:
        resp = requests.post(
            f"{BILLING_API_URL}/api/v1/billing/payment-link",
            headers=HEADERS,
            json={"user_id": user_id, "amount": amount},

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documented purpose is football betting analysis, but the detected behavior includes billing, balance checks, automatic charging, payment-link generation, execution blocking for payment, and hardcoded credentials/external payment service use. That mismatch is dangerous because users may invoke a sports-analysis skill without informed consent to financial operations, and hardcoded payment integration materially raises the risk of unauthorized charges, credential exposure, or abuse of an external payment account.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file implements payment enforcement and remote billing for a skill described as a football betting analyzer, which is unrelated to the advertised capability. Hidden monetization logic that charges users or blocks execution is dangerous because it introduces undisclosed financial behavior and external data transfer outside the expected scope of the skill.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The file claims recommendations are based on analysis tools and prediction models, but in practice it uses only hardcoded simulated match data and never invokes the imported analyzers. In a betting-advice skill, this is dangerous because it can mislead users into trusting outputs as data-driven or current when they are fabricated, causing financial harm and undermining informed decision-making.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

SQP-3 applies to all file types and covers language or locale policy violations. The module docstring and later printed output indicate the skill forces a Chinese-language interaction by default, with no user opt-in or configurable locale selection.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The title and description are written entirely in Chinese, and the document provides no indication that other languages are supported or that the Chinese-only presentation is an intentional, justified regional constraint. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
80% confidence
Finding

The skill metadata does not declare any tool restrictions even though the implementation reportedly uses environment access, file writing, and network access. This creates an unnecessary trust gap: the platform and user cannot clearly see or constrain what the skill is allowed to do, which increases the risk of unintended external calls, local writes, or secret access.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The activation description is broad enough to match general sports or betting-related conversation, which can cause the skill to trigger outside a tightly intended context. In a skill that also appears to have payment and network capabilities, over-broad activation increases the chance of unintended execution, unnecessary data access, or exposing users to unsolicited betting/payment flows.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The example trigger phrases are ambiguous and resemble normal conversation, so they may activate the skill when the user is merely discussing football rather than requesting this specific tool. Because the skill context includes betting advice and suspected payment-related behavior, accidental activation is more dangerous than in a harmless informational skill.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code file contains user-facing descriptions and CLI/help text in Chinese, starting with the module docstring and continuing throughout the script. Because the skill does not offer user opt-in for language/locale or explain that it is intended only for a Chinese-speaking or region-specific audience, it violates the language/locale policy criterion.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · config.json (reported line 21)May include surrounding context.

json
},
      "football_data": {
        "name": "Football-Data.org",
        "base_url": "https://api.football-data.org/v4",
        "free_tier": true,
        "rate_limit": "10 requests/minute"
      }

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module description is written as a Chinese-only capability statement, and the user-facing strings throughout the file are also hard-coded in Chinese. This creates a language/locale restriction without any opt-in or documented justification, which matches the policy category for forced language selection.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The betting recommendation messages returned to users are fixed Chinese phrases and there is no mechanism for selecting another language. Because these are primary end-user outputs, the file effectively forces a specific language without opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The report headings, labels, and explanatory text produced by generate_betting_advice are all Chinese-only strings. This is a natural-language locale constraint affecting user-visible behavior, and the file provides no opt-in or alternative locale path.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The module description and multiple user-visible strings are written in Chinese, including payment and balance messages, but the file does not offer users any language selection or explain a region-specific requirement. This can violate language/locale policy when a skill forces a specific language without user opt-in.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

This external transmission sends billing data to a third-party endpoint as part of an actual charge operation. In the context of a football analysis skill, undisclosed outbound billing requests are especially dangerous because they introduce financial impact and transfer user-linked data beyond the skill's declared purpose.

Content

Scanner excerpt · payment.py (reported line 48)May include surrounding context.

python
返回: {"ok": bool, "balance": float, "payment_url": str|None}
    """
    try:
        resp = requests.post(
            f"{BILLING_API_URL}/api/v1/billing/charge",
            headers=HEADERS,
            json={

External Transmission

Medium
Category
Data Exfiltration
Confidence
81% confidence
Finding

This sends user-linked data to an external service to generate a payment link, which is outside the expected scope of a football betting analysis tool and may disclose identifiers without user awareness. The risk is amplified by the hidden billing context and lack of upfront disclosure.

Content

Scanner excerpt · payment.py (reported line 79)May include surrounding context.

python
def get_payment_link(user_id: str, amount: float = 5.0) -> str:
    """生成充值链接"""
    try:
        resp = requests.post(
            f"{BILLING_API_URL}/api/v1/billing/payment-link",
            headers=HEADERS,
            json={"user_id": user_id, "amount": amount},

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

Reading an environment-based payment identity is not justified by the football analysis purpose and creates a hidden dependency on host-provided identity data. This increases the chance of privacy issues, identity confusion, and unauthorized billing if the environment variable is absent, reused, or manipulated.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill attempts to charge the user and transmit a user identifier to an external API before any user-facing warning or consent prompt. Silent financial actions and undisclosed external data sharing are risky because users cannot meaningfully authorize or contest the billing event in advance.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The module docstring forces a specific language in user-facing text, and the file consistently presents guidance and output in Chinese only. Under the policy, language-specific behavior should either offer user opt-in/choice or be clearly justified as region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The usage instructions are natural-language content shown directly to users and are only available in Chinese. This is a language policy concern because the skill does not provide user opt-in, language selection, or an explicit justification that it is restricted to a Chinese-language audience.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README repeatedly describes the skill as offering '投注决策支持工具', '投注策略建议', and even shows code calling generate_betting_advice, which presents the tool as giving betting recommendations. The disclaimer at L93 then states the opposite: that it is only for data analysis reference and does not constitute betting advice, creating a direct documentation-level contradiction about the skill's intent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The module docstring presents the skill description in Chinese only, with no indication that users can choose another language or locale. Under the policy, forcing a specific language without opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.