Back to skill

Security audit

JSON-RPC服务

Security checks for vulnerabilities and agentic risk

Overview

The skill has a real JSON-RPC wrapper, but it also persists an API key locally and sends user-supplied targets through a third-party service with unclear scoping and disclosure.

Install only if you are comfortable giving this skill a Xiaobenyang API key, storing that key in a local .env file, and sending JSON-RPC target URLs and parameters through the Xiaobenyang service. Prefer rotating or test-scoped credentials, avoid sensitive/internal server URLs, and review or patch URL validation, endpoint pinning, and key storage before production use.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/tools.py:6
Finding

Unrestricted JSON-RPC Target Enables Server-Side Request Forgery

Content
View full analysis
Dict[str, Any]: """ Call any JSON-RPC method on a server with parameters. A user would prompt: Call method on with params Args: server: Server URL method: JSON-RPC method name to call params: Stringified Parameters to pass to the method Returns: """ arguments = { "server": server, "method": method, "params": params } return call_api("1777316659903491", "rpc_call", arguments) def rpc_discover( server: str ) -> Dict[str, Any]: """ This uses JSON-RPC to call `rpc.discover` which is part of the OpenRPC Specification for discovery for JSON-RPC servers. A user would prompt: What JSON-RPC methods does this server have? Args: server: Server URL Returns: """ arguments = { "server": server } return call_api("1777316659903491", "rpc_discover", arguments) ``` ### Technical Analysis Both public tool functions accept an arbitrary `server` value and forward it to the Xiaobenyang API without validating its scheme, hostname, resolved IP address, port, or redirect behavior. The remote service is then instructed to make a JSON-RPC request to that destination. This creates an SSRF-style proxy. Although the network request to the target is performed by the upstream service rather than by the local process, an attacker can attempt to make that service contact destinations that should not be externally accessible. Potential targets include loopback addresses, private network ranges, link-local addresses, cloud metadata services, and internal administrative endpoints ...[truncated 1408 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/config.py:43
Finding

API Key Is Persisted in a Plaintext File Without Explicit Permission Hardening

Content
View full analysis
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 API key is written in plaintext to a relative `.env` path. The implementation does not explicitly create the file with owner-only permissions, verify that the destination is a regular file, reject symbolic links, use an application-owned configuration directory, or perform an atomic replacement. Consequently, effective file permissions depend on the process umask and any properties of a pre-existing `.env` file. Because the path is relative to the current working directory, the credential may also be stored in an unintended shared or version-controlled directory. The use of `Path.write_text()` on an attacker-prepared symbolic link can redirect the write to another file writable by the current process. This does not itself elevate privileges, but it can disclose the key or overwrite a selected writable file with environment-file content. ### Attack Path 1. The Skill runs in a shared, attacker-influenced, or version-controlled working directory. ...[truncated 1002 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/call_api.py:50
Finding

Configurable API Endpoint Can Redirect the API Key to an Untrusted or Plaintext Destination

Content
View full analysis
HttpResult: """调用小笨羊MCP工具""" 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), timeout=settings.timeout_seconds, ) ``` The endpoint is externally configurable in `scripts/config.py`, lines 9-17: ```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" mcp_id: str = "1820705335657482" api_key: str = "" ``` ### Technical Analysis `SettingsConfigDict` allows `base_url` to be overridden through the `XBY_GAOKAO_BASE_URL` environment variable or the settings `.env` source. `call_tool()` then appends `/api` and sends the `XBY-APIKEY` header to that endpoint. No validation requires HTTPS or pins the hostname to `mcp.xiaobenyang.com`. Therefore, a poisoned environment or configuration can redirect the production API key and all submitted JSON-RPC request data to an attacker-controlled host. An `http://` override also transmits the credential and payload without TLS protection. Requests verifies TLS certificates by default for HTTPS destinations, but that does not ...[truncated 1242 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Open-Ended Dependency Ranges Prevent Reproducible and Integrity-Verified Installation

Content
View full analysis
=2.31.0 pydantic>=2.7.0 pydantic-settings>=2.2.0 python-dotenv>=1.0.1 ``` ### Technical Analysis Every dependency uses an open-ended minimum-version constraint. Installation can therefore select any future release satisfying the lower bound. The project does not provide a lock file or package hashes to ensure that reviewers and users install the same dependency artifacts. The listed package names appear consistent with legitimate packages; no typosquatting or known malicious package was established by this audit. The risk arises from uncontrolled future updates, compromised package releases, dependency behavior changes, or newly introduced transitive dependencies. ### Attack Path 1. A future direct or transitive dependency release is compromised or introduces unsafe behavior. 2. The release still satisfies the project's open-ended version constraint. 3. A user installs or rebuilds the Skill after that release becomes available. 4. The package resolver selects the newer unreviewed release. 5. Malicious or vulnerable package code executes during installation or when imported by the Skill. This is a supply-chain exposure path rather than evidence that the currently declared packages are malicious. ### Impact Assessment Impact depends on the behavior of the selected compromised dependency. Python package code can execute with the privileges of the installing or running user, potentially exposing files, environment variables, API keys, and network access available to that process. The lack of deterministic versioning also creates availability and compatibility risk because future breaking changes may be installed without source changes in this project. ]]>
Remediation
View remediation
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 (28)

Tp2

High
Category
MCP Tool Poisoning
Confidence
85% confidence
Finding

Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

A second documented mismatch indicates the skill manages local configuration and .env API keys while not actually implementing the claimed OpenRPC/MCP server features. Misrepresentation of functionality increases the chance of unsafe deployment decisions, overbroad permissions, and accidental exposure of locally stored credentials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

A second documented mismatch indicates the skill manages local configuration and .env API keys while not actually implementing the claimed OpenRPC/MCP server features. Misrepresentation of functionality increases the chance of unsafe deployment decisions, overbroad permissions, and accidental exposure of locally stored credentials.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill advertises JSON-RPC/OpenRPC behavior but instructs the model to use unrelated API-key-gated scripts and domain-specific tooling. This is a classic skill-description integrity problem: the model may be induced to request, store, and use secrets for a service that does not match the user's expectations, creating opportunities for credential harvesting or covert data exfiltration.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The workflow and project structure document a different external API skill than the claimed JSON-RPC service. In context, this makes the skill more dangerous because the contradiction is not superficial: it affects what endpoints are called, what credentials are requested, and what data handling the user should expect.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

This configuration module is materially inconsistent with the stated JSON-RPC/MCP server purpose and instead manages credentials for an unrelated external gaokao service. In a skill ecosystem, that kind of scope drift is dangerous because it expands the trust boundary, introduces secret-handling behavior users would not expect, and may enable exfiltration or misuse of external-service credentials.

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
90% confidence
Finding

The code explicitly reads the .env file and extracts XBY_APIKEY manually, bypassing normal settings abstraction and increasing direct secret-handling inside application logic. That makes credential access broader and easier to repurpose, especially in a skill whose stated purpose does not require direct secret file parsing.

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
90% confidence
Finding

Opening and reading .env directly to locate a specific API key is an unnecessary credential access path and increases exposure of secrets in code that should not need file-level secret parsing. In context, this is more concerning because the skill is presented as a JSON-RPC service, not a credential-management utility.

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

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code can modify and persist an external API key locally by writing directly to .env, which exceeds what is reasonably expected for a JSON-RPC method discovery/invocation server. This creates a credential persistence surface that could be abused by other code paths, plugins, or attackers with indirect access to set or replace secrets for later use.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
94% confidence
Finding

This function is dedicated to saving an API key into .env, creating a persistent plaintext credential store under application control. In the context of a purported JSON-RPC service, that is an unexpectedly powerful credential-management capability and raises the risk of secret leakage, tampering, and abuse.

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
91% confidence
Finding

The skill declares no explicit tool scope or permissions while its documented/project capabilities include environment access, local file read/write, and network access. In an agent setting, this weakens least-privilege boundaries and makes it easier for the skill to access secrets, persist sensitive data, or reach arbitrary remote endpoints without clear user-visible constraints.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill lacks a clear warning that user-supplied server URLs, method names, and parameters will be transmitted to external JSON-RPC endpoints. This can expose sensitive internal URLs, credentials embedded in params, or proprietary data to third-party services, especially if users assume processing is local or limited to discovery.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

This code reads a sensitive credential via get_api_key() and sends it in the XBY-APIKEY request header during a network call. Although the code logs request outcomes, there is no confirmation prompt, user-facing disclosure, or explanatory comment/docstring warning that a secret and request data will be transmitted to an external service.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Settings 类的文档字符串明确表述该模块是“小笨羊高考Skill配置”,而清单将该技能描述为 JSON-RPC/MCP 服务器。这里不是单纯文档不完整,而是文档主动指向了不同的技能/用途,显示出代码意图与技能声明存在直接分歧。

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Persisting an API key to a .env file without any user-facing warning or confirmation can expose secrets through local file disclosure, source-control accidents, backups, or multi-user environments. Because the write happens programmatically, users may not realize a credential has been stored long-term on disk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
63% confidence
Finding

The file is written as a Chinese-only skill and instructs the model to present API results directly, but it does not offer the user any language or locale choice. Under the policy, forcing a specific language without opt-in can be a natural-language policy violation unless the locale constraint is clearly documented and justified.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency specification uses a lower-bound version constraint instead of pinning to an exact version, which makes builds non-reproducible and can result in different packages being installed over time. In a server-side MCP/JSON-RPC service, this increases supply-chain risk and makes it harder to ensure that vulnerable or incompatible releases are not introduced during deployment.

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
91% confidence
Finding

The manifest does not pin requests, and the package has multiple published advisories, so it is impossible to verify from this file whether deployments are using a safe or affected release. In an MCP/JSON-RPC server, HTTP client behavior may be security-relevant, making this uncertainty more concerning than in a purely offline tool.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

Using pydantic>=2.7.0 allows any newer release to be installed, which weakens reproducibility and prevents assurance about exactly which code is running in production. For a JSON-RPC server that likely parses external input, uncontrolled dependency drift can expose the service to newly introduced bugs or known vulnerable versions.

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

Because pydantic is unpinned and has known advisories, the current manifest cannot establish whether the deployed version is patched. This is meaningful in a JSON-RPC service because pydantic is commonly used to validate untrusted input, so a vulnerable version could affect request parsing reliability or enable denial-of-service conditions.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The pydantic-settings package is specified with a minimum version only, so future installs may pull different releases with different security properties. Because settings libraries can influence how secrets and configuration are loaded, version ambiguity increases the risk of accidentally consuming a flawed release.

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
86% confidence
Finding

The file leaves pydantic-settings unpinned despite known advisories, so there is no assurance that a deployed build avoids affected versions. Since configuration-loading components can interact with secrets and filesystem paths, unresolved version ambiguity creates avoidable security uncertainty.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

python-dotenv is not pinned to a specific version, so installations may vary over time and could unexpectedly include vulnerable or behavior-changing releases. In services that load environment files or manipulate configuration, this can contribute to supply-chain exposure and unpredictable runtime behavior.

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