Back to skill

Security audit

菲律宾地理编码服务

Security checks for vulnerabilities and agentic risk

Overview

This skill is a Philippine geography lookup tool, but it has mismatched Gaokao/XiaoBenYang remnants and persists an API key in a local plaintext .env file.

Review this before installing. Verify that the XiaoBenYang service and MCP identifier are the intended provider for Philippine PSGC data, use a limited or disposable API key, avoid shared or version-controlled workspaces, and check or remove the generated .env file after use. The publisher should clean up the Gaokao remnants, restrict the API destination and allowed tool names, avoid plaintext key persistence, and pin dependencies.

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 (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/config.py:40
Finding

API Key Persisted in a Plaintext Environment File

Content
View full analysis

Vulnerability Details

File Location: scripts/config.py, lines 40-59
Vulnerability Type: Plaintext storage of sensitive credentials
Risk Level: Medium

Vulnerable Code

python
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()
        found = False
        new_lines = []
        for line in lines:
            if line.startswith("XBY_APIKEY="):
                new_lines.append(f"XBY_APIKEY={api_key}")
                found = True
            else:
                new_lines.append(line)
        if not found:
            new_lines.append(f"XBY_APIKEY={api_key}")
        env_path.write_text("\n".join(new_lines) + "\n", encoding="utf-8")
        os.environ["XBY_APIKEY"] = api_key
        return True
    except Exception as e:
        print(f"保存API key失败: {e}")
        return False

Technical Analysis

The function stores a user-supplied API key directly in a plaintext .env file. Path.write_text() does not explicitly enforce owner-only permissions, so the resulting access permissions depend on the process umask or permissions of an existing file. The file is also rewritten directly rather than through an atomic, permission-controlled replacement.

Any local account or process with permission to read the project directory may recover the credential. The file may also be exposed through backups, workspace synchronization, artifact collection, or accidental source-control commits.

Attack Path

  1. The Skill asks the user to provide an API key.
  2. The Agent invokes scripts.config.set_api_key().
  3. set_api_key() invokes save_api_key_to_env().
  4. The function writes XBY_APIKEY=<secret> to .env as plaintext.
  5. A local process, another user with directory access, a ...[truncated 505 chars]
Remediation
View remediation

Remediation Suggestions

  • Prefer a platform-managed secret store, operating-system keychain, or runtime-only environment injection instead of filesystem persistence.
  • If file persistence is unavoidable, create the secret file with owner-only permissions such as 0600.
  • Write updates atomically to a permission-controlled temporary file and then replace the destination.
  • Ensure .env is excluded from source control, build artifacts, diagnostic bundles, and backups where possible.
  • Document credential rotation procedures and recommend immediate rotation if the workspace is exposed.
  • Avoid retaining the key longer than required and never include it in logs or error messages.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/call_api.py:49
Finding

Configurable API Endpoint Allows Credential Exfiltration

Content
View full analysis

Vulnerability Details

File Locations: scripts/config.py, lines 9-15; scripts/call_api.py, lines 49-66
Vulnerability Type: Unvalidated credential destination
Risk Level: Medium

Vulnerable Code

python
model_config = SettingsConfigDict(
    env_prefix="XBY_GAOKAO_",
    env_file=".env",
    env_file_encoding="utf-8",
    extra="ignore",
)

# API配置
base_url: str = "https://mcp.xiaobenyang.com"
python
url = f"{settings.base_url}/api"
mcp_id = mcp_id or settings.mcp_id

api_key = get_api_key()
if not api_key:
    raise UpstreamError("API密钥未设置,请先调用 set_api_key()")

headers = {
    "XBY-APIKEY": api_key,
    "func": tool_name,
    "mcpid": mcp_id,
    "Content-Type": "application/json",
}

# data = {k: str(v) if v is not None else "" for k, v in params.items()}

t0 = time.time()
try:
    resp = self._session.post(
        url=url,
        headers=headers,
        data=json.dumps(params),

Technical Analysis

SettingsConfigDict permits settings to be supplied through the XBY_GAOKAO_ environment prefix and .env. Consequently, XBY_GAOKAO_BASE_URL can replace the default API endpoint. call_tool() constructs a URL from that value and sends the API key in the custom XBY-APIKEY header without validating the scheme or destination hostname.

The implementation does not enforce HTTPS or restrict requests to mcp.xiaobenyang.com. An attacker who can modify process environment variables or the applicable .env file can redirect credentials and geographic query data to an attacker-controlled endpoint.

Attack Path

  1. An attacker obtains the ability to influence the Skill's environment or .env configuration.
  2. The attacker sets XBY_GAOKAO_BASE_URL to an attacker-controlled URL, such as https://attacker.example.
  3. The application initializes settings.base_url from that value.
  4. A user invokes any geographic lookup tool.
  5. `c ...[truncated 663 chars]
Remediation
View remediation

Remediation Suggestions

  • Hard-code the credential-bearing API origin when endpoint customization is not required.
  • Otherwise, parse the configured URL and enforce an explicit allowlist containing only the expected hostname and port.
  • Reject non-HTTPS schemes, embedded credentials, unexpected ports, malformed hosts, and URLs containing unapproved path components.
  • Disable redirects for credential-bearing requests or validate every redirect destination before forwarding custom authentication headers.
  • Separate development endpoints from production credentials so a production key is never sent to a test or user-configurable server.
  • Treat modifications to .env and deployment environment variables as security-sensitive configuration changes.

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Unbounded Dependency Versions Create Supply-Chain Risk

Content
View full analysis

Vulnerability Details

File Location: requirements.txt, lines 1-4
Vulnerability Type: Non-reproducible and insufficiently constrained dependencies
Risk Level: Low

Vulnerable Code

text
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1

Technical Analysis

Every dependency has only a minimum version and no upper bound, exact pin, or integrity hash. A future installation can therefore resolve to releases that were not present during this audit. This makes builds non-reproducible and increases exposure to compromised upstream releases, unexpected behavior changes, or newly introduced vulnerabilities.

No currently listed package was identified as malicious from the reviewed project content. The finding concerns the dependency-management policy and the uncontrolled acceptance of future versions.

Attack Path

  1. A user or deployment pipeline installs dependencies from requirements.txt at a later date.
  2. The package resolver selects the newest versions satisfying the lower bounds.
  3. A selected release contains a supply-chain compromise, exploitable vulnerability, or incompatible security behavior.
  4. The affected code is installed and subsequently imported or executed by the Skill.
  5. The compromise receives the privileges of the process running the installation or Skill.

Impact Assessment

Impact depends on the behavior of the selected dependency release. In the worst case, a compromised dependency could access the Skill process environment, plaintext API key, local files available to the process, and outbound network connectivity. The reviewed requirements do not themselves establish that such a compromised release currently exists.

Remediation
View remediation

Remediation Suggestions

  • Pin each dependency to a specifically reviewed version.
  • Generate and verify cryptographic hashes for distributions, for example by using a locked requirements file with hash enforcement.
  • Use a controlled dependency update process that includes vulnerability scanning and changelog review.
  • Separate direct dependencies from a fully resolved lock file while preserving reproducible production installations.
  • Regularly update pinned versions after security review rather than automatically accepting all future releases.
  • Configure installation to use trusted package indexes and prevent dependency-confusion sources.
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 (27)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

This second mismatch finding is substantive: the skill persists a user-supplied XBY_APIKEY locally and references a gaokao/xiaobenyang configuration that is unrelated to Philippine geographic coding. That combination indicates undisclosed credential handling and off-purpose service access, which raises the risk of credential misuse, user deception, and unauthorized data transmission.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This second mismatch finding is substantive: the skill persists a user-supplied XBY_APIKEY locally and references a gaokao/xiaobenyang configuration that is unrelated to Philippine geographic coding. That combination indicates undisclosed credential handling and off-purpose service access, which raises the risk of credential misuse, user deception, and unauthorized data transmission.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The implementation does not behave like a PSGC geography service; instead it is a generic proxy that forwards arbitrary tool names, parameters, and an API key to a third-party '小笨羊MCP' endpoint. This mismatch is dangerous because users and reviewers may trust the skill as a benign geography data connector while it can route data and actions to an unrelated external service, enabling covert data exfiltration or unauthorized tool invocation.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The class docstring identifies this as a '高考Skill配置' while the package claims to be a Philippines geocoding service, which is a strong provenance and purpose mismatch. Such inconsistencies are dangerous because they suggest code reuse from an unrelated project, raising the risk of hidden functionality, mis-scoped credentials, or supply-chain deception in a skill users would otherwise trust as narrowly scoped.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/config.py (reported line 13)May include surrounding context.

python
model_config = SettingsConfigDict(
        env_prefix="XBY_GAOKAO_",
        env_file=".env",
        env_file_encoding="utf-8",
        extra="ignore",
    )

Credential Access

High
Category
Privilege Escalation
Confidence
75% confidence
Finding

The code forcibly reads XBY_APIKEY directly from .env during post-init, bypassing the normal scoped env_prefix behavior and creating custom secret-parsing logic for a credential unrelated to the declared XBY_GAOKAO_ prefix. In the context of a supposedly simple geocoding skill, this increases suspicion and expands secret-handling surface area unnecessarily, making accidental exposure or misuse more likely.

Content

Scanner excerpt · scripts/config.py (reported line 31)May include surrounding context.

python
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")

Credential Access

High
Category
Privilege Escalation
Confidence
75% confidence
Finding

Checking for and reading the .env file directly is part of a custom credential access path that is unnecessary for a narrowly scoped geocoding skill. Although it is not exfiltration by itself, it broadens the code's ability to inspect local secret-bearing files and contributes to unsafe secret management practices.

Content

Scanner excerpt · scripts/config.py (reported line 32)May include surrounding context.

python
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():

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/config.py (reported line 39)May include surrounding context.

python
if line.startswith("XBY_APIKEY="):
                    self.api_key = line.split("=", 1)[1].strip()
                    break
        # 如果环境变量有值,覆盖 .env 的值
        env_val = os.getenv("XBY_APIKEY", "")
        if env_val:
            self.api_key = env_val

Credential Access

High
Category
Privilege Escalation
Confidence
94% confidence
Finding

This function explicitly persists an API key to a local .env file, creating a durable credential artifact on disk. In a skill whose advertised purpose is only PSGC data access, secret persistence is unusually dangerous because it expands the blast radius from transient runtime use to long-term local exposure through filesystem access, backups, or accidental publication.

Content

Scanner excerpt · scripts/config.py (reported line 48)May include surrounding context.

python
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()

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill declares no explicit tool scope or permissions despite requiring environment access, local file reads/writes, and network calls. In an agent setting, this weakens least-privilege controls and can allow broader-than-necessary capability use, especially because the skill also handles credentials and outbound API access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill instructs the agent to ask the user for an API key and persist it via set_api_key without warning about storage location, retention, or access controls. That is dangerous because users may disclose sensitive credentials without informed consent, and local persistence increases the risk of accidental exposure or later misuse.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The workflow example tells the model to call a school-search function in a skill purportedly for Philippine geocoding. In agent systems, contradictory operational instructions increase the chance of wrong-tool invocation, unintended external requests, and leakage of user input to unrelated services.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The class and function docstrings explicitly reference calling '小笨羊MCP' tools/API, which directly contradicts the advertised Philippines PSGC service. In the context of a skill distributed under a different identity, this inconsistency is a strong indicator of deceptive repurposing or hidden functionality, increasing the risk that operators will authorize network access or secrets under false assumptions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code sends params to a remote endpoint and includes an API key in request headers, which can transmit user or system data off-host. Although the module has internal logging and docstrings, there is no confirmation prompt or user-facing warning that data and credentials are being used in an outbound network call.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module persists an API key to a local .env file and updates process environment state, which exceeds the expected read-only behavior of a geographic data access skill. Storing secrets on disk without clear necessity, consent, or secure storage controls increases the chance of credential leakage through source directories, backups, logs, or accidental inclusion in version control.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code can modify the local .env configuration file by overwriting or appending XBY_APIKEY entries, giving the skill write access to local configuration unrelated to PSGC data retrieval. That local state modification is not justified by the stated purpose and can silently alter the runtime environment or leave sensitive credentials persisted beyond the current session.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The function writes API credentials to .env without any user-facing warning that the secret will be stored persistently on disk. Users may reasonably expect temporary configuration, so silent persistence increases the risk of later exposure through repository commits, shared workspaces, backups, or other local access.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

文档前文一直说明这是“菲律宾地理编码服务”,但项目结构处却写成 xiaobenyang_gaokao_skill/,语义上对应的是高考/招生类技能。虽然这不直接证明代码行为异常,但属于明显的意图级文档矛盾,可能导致维护者误解技能来源和用途。

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency specification uses a lower-bound version (requests>=2.31.0) rather than pinning to an exact version, which makes builds non-reproducible and can unintentionally pull in a vulnerable or incompatible release later. In a server-side MCP skill that depends on network access, this increases supply-chain uncertainty even though the file itself does not prove exploitation.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); 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) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
90% confidence
Finding

The manifest includes requests without an exact version pin, while the package has multiple known advisories across releases. Because the resolved installed version is unknown from this file alone, the project may end up using an affected version, especially in environments that install latest-compatible packages.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

pydantic>=2.7.0 is not pinned to a specific release, so installations may resolve to different versions over time. That weakens reproducibility and leaves uncertainty about whether a future resolved version contains a known security flaw or breaking behavior affecting validation logic.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1

Unverifiable Dependency: pydantic has 4 known advisory(ies) (CVE-2021-29510 (Use of "infinity" as an input to datetime and date fields causes infinite loop i); CVE-2024-3772 (Pydantic regular expression denial of service); CVE-2021-29510 (Pydantic is a data validation and settings management using Python type hinting.) +1 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
88% confidence
Finding

pydantic has known advisories in some versions, but this requirements entry does not identify which version will actually be installed beyond a minimum bound. That creates unverifiable exposure and is especially relevant because pydantic commonly processes untrusted input and application settings.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

Using pydantic-settings>=2.2.0 without an exact pin permits uncontrolled version drift. Because this package influences configuration and secrets handling, an unsafe future version could affect how environment or secret sources are processed.

Content

Scanner excerpt · requirements.txt (reported line 3)May include surrounding context.

text
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1

Unverifiable Dependency: pydantic-settings has 1 known advisory(ies) (CVE-2026-58203 (pydantic-settings: NestedSecretsSettingsSource follows symlinks outside secrets_)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
87% confidence
Finding

The dependency on pydantic-settings is not pinned, and the package has at least one listed advisory affecting some versions. Since this library is tied to configuration and secret loading, uncertain version resolution can expose the service to risky filesystem or secrets-handling behavior if an affected release is installed.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

python-dotenv>=1.0.1 is unpinned, so future installations may silently adopt newer releases with security or behavior changes. Since dotenv libraries often interact with local configuration files and environment variables, version uncertainty can affect configuration integrity or expose the project to newly introduced issues.

Content

Scanner excerpt · requirements.txt (reported line 4)May include surrounding context.

text
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1