Back to skill

Security audit

星座服务

Security checks for vulnerabilities and agentic risk

Overview

This horoscope skill is not clearly malicious, but it needs review because it stores an API key in a local .env file, sends birth and location details to a third-party API, and contains confusing copied Gaokao service identifiers.

Review before installing. Only provide a Xiaobenyang API key you are comfortable storing in plaintext .env, avoid running the skill in a project directory with unrelated secrets in .env, and do not provide exact birth time or coordinates unless you accept sending that data to the external Xiaobenyang API.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (17)

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill directs the agent to read environment/config state, persist an API key to local configuration, and call external network APIs, yet the skill declares no permissions. This creates a transparency and governance gap: users and platforms may not realize the skill can store secrets, access files, and make outbound requests, which increases the chance of unsafe deployment or misuse.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The configuration is clearly for an unrelated XBY/Gaokao service while the skill claims to be a horoscope service. This mismatch is dangerous because it can mislead users into providing credentials to a different backend than advertised, creating a supply-chain and trust-boundary issue even if no overt exfiltration is shown in this file.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The skill persists API credentials into a local .env file even though a horoscope query service does not inherently require permanent credential storage. Storing secrets on disk increases the chance of accidental disclosure through backups, source control, shared workspaces, or later reads by unrelated code in the same environment.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill instructs the agent to collect an API key from the user and persist it via configuration, but it does not disclose storage behavior, retention, scope of use, or handling precautions. That omission can lead users to provide sensitive credentials without informed consent and increases the risk of accidental exposure or insecure secret management.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The rising-sign feature requests precise birth date, time, and geolocation, which together constitute sensitive personal data and can be identifying. The skill does not warn users about the sensitivity of this data, whether it is stored or transmitted, or how it is protected, creating privacy risk disproportionate to an entertainment-oriented use case.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The function writes the supplied API key to .env and updates the process environment without any user-facing warning or confirmation. This is risky because users may believe they are providing a transient key while the skill silently creates a persistent secret that other local tools or future sessions can access.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The `get_rising_sign` function sends precise birth date, birth time, and latitude/longitude to an external API via `call_api`, which constitutes transmission of sensitive personal data. In a horoscope context this is expected for functionality, but the file shows no visible consent flow, privacy notice, data minimization, or validation, so users may unknowingly disclose information that can reveal location and personal profile details.

Credential Access

High
Category
Privilege Escalation
Content
default_year: int = 2025

    def model_post_init(self, __context):
        # 强制从 .env 文件读取 XBY_APIKEY
        env_path = Path(".env")
        if env_path.exists():
            content = env_path.read_text(encoding="utf-8")
Confidence
92% confidence
Finding
The code explicitly and forcibly reads XBY_APIKEY from a local .env file in post-init, bypassing normal scoped configuration expectations. In the context of a misrepresented horoscope skill, this makes credential collection and reuse more dangerous because the skill actively seeks a secret for a different named service than advertised.

Credential Access

High
Category
Privilege Escalation
Content
def model_post_init(self, __context):
        # 强制从 .env 文件读取 XBY_APIKEY
        env_path = Path(".env")
        if env_path.exists():
            content = env_path.read_text(encoding="utf-8")
            for line in content.splitlines():
Confidence
92% confidence
Finding
Opening and reading the entire .env file to search for XBY_APIKEY expands access to all secrets stored there, not just those needed through narrowly scoped configuration APIs. In a misleadingly branded skill, this broad secret-file access increases the risk of credential exposure or future abuse if the code evolves or logs are added.

Credential Access

High
Category
Privilege Escalation
Content
def save_api_key_to_env(api_key: str) -> bool:
    """将API key保存到.env文件"""
    try:
        env_path = Path(".env")
        lines = []
        if env_path.exists():
            lines = env_path.read_text(encoding="utf-8").splitlines()
Confidence
94% confidence
Finding
This function is dedicated to saving an API key into .env, creating durable local secret storage in the project directory. That is risky because such files are often copied, backed up, or accidentally committed, and this persistence is not justified by the stated low-sensitivity horoscope functionality.

Credential Access

High
Category
Privilege Escalation
Content
def set_api_key(api_key: str) -> bool:
    """设置API key并持久化到.env"""
    if not api_key or not api_key.strip():
        return False
    api_key = api_key.strip()
Confidence
93% confidence
Finding
The set_api_key helper is designed to persist a provided credential to .env rather than merely configuring runtime state. This normalizes long-term storage of secrets for a skill whose declared purpose does not justify it, increasing exposure if the host environment is shared or inspected.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
Confidence
96% confidence
Finding
The dependency is specified with a lower bound only (`requests>=2.31.0`), which allows future versions to be installed without review and can also permit resolution to a known-bad minimum version. In a network-facing MCP service, this increases supply-chain and reproducibility risk because builds may drift or pull vulnerable releases.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
Confidence
93% confidence
Finding
`pydantic>=2.7.0` is unpinned, so installations are not reproducible and may silently pick up breaking or insecure upstream releases. While not an immediate exploit by itself, it is a real supply-chain hardening weakness.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
Confidence
93% confidence
Finding
`pydantic-settings>=2.2.0` is not pinned to an exact reviewed version, which weakens build integrity and makes deployments less predictable. This is especially relevant for configuration-handling libraries because unexpected behavior changes can affect how secrets and settings are loaded.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
Confidence
95% confidence
Finding
`python-dotenv>=1.0.1` is unpinned and can resolve to unreviewed versions, creating supply-chain and reproducibility risk. Because this package influences environment-variable loading, unexpected upstream changes can affect secret handling and startup behavior.

Known Vulnerable Dependency: requests==2.31.0 — 5 advisory(ies): CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi); CVE-2026-25645 (Requests has Insecure Temp File Reuse in its extract_zipped_paths() utility func) +2 more

Medium
Category
Supply Chain
Confidence
98% confidence
Finding
The requirement `requests>=2.31.0` permits installation of `requests` 2.31.0, which the scanner identifies as having multiple published advisories. In an MCP service that likely makes outbound HTTP requests, flaws in the HTTP client can affect credential handling, TLS/session verification, or other network-security properties, making this materially more dangerous than a generic library issue.

Known Vulnerable Dependency: python-dotenv==1.0.1 — 1 advisory(ies): CVE-2026-28684 (python-dotenv: Symlink following in set_key allows arbitrary file overwrite via )

Low
Category
Supply Chain
Confidence
91% confidence
Finding
The requirement `python-dotenv>=1.0.1` allows the vulnerable 1.0.1 release to be installed, and the cited advisory concerns symlink-following behavior in `set_key` that could enable arbitrary file overwrite in certain usage patterns. This is context-dependent and only becomes exploitable if the skill actually invokes vulnerable write/update functionality on attacker-influenced paths, but it remains a real dependency risk.

Static analysis

No suspicious patterns detected.