Back to skill

Security audit

Lottery Predictor

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches a lottery-analysis purpose, but it ships an under-disclosed payment module with a hardcoded SkillPay bearer key and remote payment/account calls.

Review before installing. The lottery analysis code is local and includes clear gambling disclaimers, but the package also contains under-disclosed payment/account code with an exposed shared API key. Install only if the publisher removes or rotates the embedded credential, documents any payment service use, and makes payment checks fail closed with explicit user control.

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 SkillPay Bearer Credential Exposed in Source Code

Content
View full analysis

Vulnerability Details

File Location: payment.py:11-13, with credential use at payment.py:24-40 and payment.py:64-74
Vulnerability Type: Hard-coded authentication secret
Risk Level: High

Vulnerable Code

python
# SkillPay API configuration
SKILLPAY_API_KEY = "[REDACTED HARDCODED sk_ CREDENTIAL]"
SKILLPAY_BASE_URL = "https://api.skillpay.io/v1"
SKILL_SLUG = "shenmeng-lottery-predictor"

The credential is subsequently placed into outbound authorization headers:

python
headers = {
    "Authorization": f"Bearer {SKILLPAY_API_KEY}",
    "Content-Type": "application/json"
}

data = {
    "skill_slug": SKILL_SLUG,
    "price": PRICE_PER_CALL
}

response = requests.post(
    f"{SKILLPAY_BASE_URL}/verify",
    headers=headers,
    json=data,
    timeout=10
)

It is also used by the balance request:

python
headers = {
    "Authorization": f"Bearer {SKILLPAY_API_KEY}",
    "Content-Type": "application/json"
}

response = requests.get(
    f"{SKILLPAY_BASE_URL}/balance",
    headers=headers,
    timeout=10
)

The credential value is redacted from this report to avoid further disclosure. The audited source contains the complete plaintext bearer token.

Technical Analysis

A static bearer credential is embedded directly in a distributable source file. Anyone who can download, inspect, archive, or fork the Skill can recover the token without executing the code. Because bearer authentication treats possession of the token as proof of authority, an attacker can submit authenticated requests independently of the Skill.

Sending an authentication token to the intended API over HTTPS may be necessary for payment verification, but distributing a shared secret with the package is not necessary and violates least-secret and credential-lifecycle practices. The lottery-analysis functionality itself operates locally and does not require this credential ...[truncated 1586 chars]

Remediation
View remediation

Remediation Suggestions

  1. Immediately revoke and rotate the exposed SkillPay credential.
  2. Remove the token from source code, package history, release archives, examples, and test fixtures.
  3. Load credentials from a protected environment variable or secrets manager:
    python
    SKILLPAY_API_KEY = os.environ.get("SKILLPAY_API_KEY")
    if not SKILLPAY_API_KEY:
        raise RuntimeError("SKILLPAY_API_KEY is not configured")
    
  4. Prefer short-lived, per-installation or per-user tokens rather than one shared package-wide credential.
  5. Restrict the token to only the required endpoint, Skill identifier, operation, and billing amount.
  6. Ensure balance-reading authority is excluded unless it is strictly required.
  7. Add automated secret scanning to source-control and release pipelines.
  8. Document the external payment service, transmitted fields, destination, and authentication requirements before enabling network access.

T09 · Insecure Skill Coding Practices

Warning
Location
payment.py:54
Finding

Payment Verification Fails Open on Network or Processing Errors

Content
View full analysis

Vulnerability Details

File Location: payment.py:54-57
Vulnerability Type: Fail-open authorization control
Risk Level: Medium

Vulnerable Code

python
except Exception as e:
    print(f"⚠️  支付验证出错: {e}")
    # 错误时不阻止使用,记录日志即可
    return True

Within the complete verification flow, True represents successful authorization:

python
if response.status_code == 200:
    result = response.json()
    if result.get("verified"):
        return True
    else:
        balance = result.get("balance", 0)
        required = result.get("required", PRICE_PER_CALL)
        print(f"⚠️  余额不足: 当前 {balance} USDT, 需要 {required} USDT")
        print(f"💳 充值链接: {result.get('payment_url', '请访问 SkillPay 官网充值')}")
        return False
else:
    print(f"⚠️  支付验证失败: {response.status_code}")
    return False

except Exception as e:
    print(f"⚠️  支付验证出错: {e}")
    # 错误时不阻止使用,记录日志即可
    return True

Technical Analysis

require_payment() returns True whenever an exception occurs. Exceptions can result from a timeout, DNS failure, refused connection, missing requests dependency, TLS processing failure, malformed JSON response, or other runtime errors. The function therefore converts an indeterminate verification result into successful payment authorization.

This violates the fail-closed principle for access-control and payment gates. A successful authorization decision must only follow an authenticated response that explicitly states that payment is verified.

The current predictor and evolution modules do not call require_payment(), so this vulnerable control is dormant in the audited package's core execution paths. It becomes directly exploitable if a caller follows the module documentation and uses this function as a prerequisite for paid functionality.

Attack Path

  1. An application integrates require_payment() and grants paid functionality when it returns True. ...[truncated 1034 chars]
Remediation
View remediation

Remediation Suggestions

  1. Fail closed: return False or raise a dedicated verification exception for every indeterminate result.
  2. Only return True after validating an authenticated, schema-compliant response containing an explicit verified: true value.
  3. Replace the broad exception handler with specific handlers for timeout, transport, JSON parsing, and response-validation failures.
  4. Keep authorization failure separate from temporary service unavailability:
    python
    class PaymentVerificationUnavailable(Exception):
        pass
    
    try:
        response = requests.post(...)
        response.raise_for_status()
        result = response.json()
    except (requests.RequestException, ValueError) as exc:
        raise PaymentVerificationUnavailable(
            "Payment status could not be verified"
        ) from exc
    
    return result.get("verified") is True
    
  5. Ensure callers deny the paid operation when verification is unavailable rather than treating service failure as authorization.
  6. Validate response types and required fields before making an authorization decision.
  7. Add tests for timeouts, DNS failures, malformed JSON, unexpected status codes, and missing verified fields.
  8. If offline access is required, use a separately designed, signed, time-limited entitlement rather than silently approving failed online verification.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared purpose is lottery analysis, but the package structure references a payment module and the finding states it performs payment verification, balance retrieval, third-party billing calls, and uses a hardcoded secret key. This hidden functionality is dangerous because it expands the trust boundary far beyond user expectations and introduces credential exposure plus unauthorized financial/account interactions.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The docstring states payment must be verified before use, but the exception handler returns True on any verification error. This creates a fail-open authorization bypass where network failures, API errors, or intentionally induced exceptions can unlock paid functionality without successful payment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README title and description are entirely in Chinese and present the skill as a general-purpose lottery analysis tool, but do not offer any language choice or explain that the skill is intended only for a Chinese-speaking or China-specific audience. 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
89% confidence
Finding

The skill declares no explicit tool permissions even though the documented functionality and referenced files imply file read/write and network access. Missing scope declarations weaken least-privilege controls and can let a host grant broader capabilities than users expect, especially since the skill also stores history and fetches external data.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This markdown file uses Chinese throughout the description, usage instructions, disclaimers, and examples, but does not indicate that the language is optional or provide an alternative locale. Under the policy criteria, forcing a specific language without user opt-in is a natural-language locale violation.

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 all user-facing text are presented only in Chinese, indicating the skill is designed to operate in a single language without any opt-in or alternative locale support. This is a natural-language policy concern because the file imposes a language choice on users rather than offering one.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

A live payment API key is hardcoded directly in source code and then used for authenticated outbound requests. Anyone with code access can extract and misuse the credential to query balances, invoke payment APIs, impersonate the skill, or incur financial and operational harm.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · payment.py (reported line 13)May include surrounding context.

python
# SkillPay API 配置
SKILLPAY_API_KEY = "sk_f03aa8f8bbcf79f7aa11c112d904780f22e62add1464e3c41a79600a451eb1d2"
SKILLPAY_BASE_URL = "https://api.skillpay.io/v1"
SKILL_SLUG = "shenmeng-lottery-predictor"
PRICE_PER_CALL = 0.01  # USDT

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest describes a lottery prediction and historical analysis tool for Chinese lottery games, but this file implements external payment verification and balance retrieval against SkillPay. Monetization logic is not mentioned in the skill description, so the actual behavior materially exceeds the described analytics/recommendation purpose.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

For a skill presented as a lottery history analysis and recommendation tool, contacting a third-party payment API to verify charges and inspect account balance is not an obvious functional requirement of number analysis itself. This adds a financial/account capability unrelated to the stated end-user analytical purpose.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · payment.py (reported line 35)May include surrounding context.

python
"price": PRICE_PER_CALL
        }
        
        response = requests.post(
            f"{SKILLPAY_BASE_URL}/verify",
            headers=headers,
            json=data,

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest description is written entirely in Chinese and the tags are Chinese-specific, indicating a language-specific experience with no visible opt-in or alternative language support. Under the stated policy, forcing a specific language without user choice is a natural-language policy concern unless the locale restriction is documented and justified.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The docstring and inline comment at L489-L490 state that real usage should fetch data from an API, implying actual historical-data retrieval behavior. However, the function body never performs any API access and instead fabricates random draws and match data, which contradicts the documented intent of loading data from a real source.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The function posts skill and pricing data to the SkillPay verify endpoint, but there is no confirmation prompt or upfront notice that the skill will contact an external payment service before use. The existing prints only appear after insufficient balance or errors, so they do not serve as advance disclosure of the network operation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.