Back to skill

Security audit

法国个人所得税计算服务

Security checks for vulnerabilities and agentic risk

Overview

This French tax skill is mostly coherent, but it stores an API key in plaintext and sends sensitive tax inputs to a configurable remote service with limited disclosure and controls.

Review this skill before installing. Use it only if you trust the XiaoBenYang service and are comfortable sending tax-related inputs to it. Prefer a throwaway or restricted API key, avoid storing it in a shared workspace, inspect or delete the generated .env file after use, and do not allow untrusted environment variables or .env contents to override the API endpoint.

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

Warning
Location
scripts/config.py:14
Finding

Configurable API Endpoint Enables Credential and Financial Data Exfiltration

Content
View full analysis

Vulnerability Details

File Location: scripts/config.py:14-18 and scripts/call_api.py:53-66
Vulnerability Type: Unvalidated configurable network destination
Risk Level: Medium

Vulnerable Code

scripts/config.py:14-18:

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

scripts/config.py:21-23:

python
base_url: str = "https://mcp.xiaobenyang.com"
mcp_id: str = "1820705335657482"
api_key: str = ""

scripts/call_api.py:53-66:

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",
}

scripts/call_api.py:72-77:

python
resp = self._session.post(
    url=url,
    headers=headers,
    data=json.dumps(params),
    timeout=settings.timeout_seconds,
)

Technical Analysis

The Settings model permits fields to be overridden through environment variables prefixed with XBY_GAOKAO_ or through the .env file. Consequently, XBY_GAOKAO_BASE_URL can replace the expected XiaoBenYang endpoint.

Before adding the API key to the XBY-APIKEY request header, call_tool() does not validate that the effective URL uses HTTPS or that its hostname is exactly an approved XiaoBenYang domain. All tool parameters are also serialized into the request body. These parameters can include net taxable income, household composition, tax queries, and report contents.

An attacker capable of influencing the process environment or the Skill's .env file can therefore redirect requests to a server under the attacker's control. The request will disclose both the API credential and user-supplied financial informa ...[truncated 1247 chars]

Remediation
View remediation

Remediation Suggestions

  1. Make the production API endpoint immutable if runtime customization is unnecessary.
  2. If endpoint configuration is required, parse it with urllib.parse.urlsplit and enforce:
    • The https scheme.
    • An exact approved hostname, such as mcp.xiaobenyang.com.
    • The expected port.
    • No embedded user information.
  3. Maintain an explicit destination allowlist rather than using suffix or substring comparisons.
  4. Disable automatic cross-origin redirects for authenticated requests, or validate the destination of every redirect before forwarding credentials.
  5. Separate credential-bearing request configuration from general environment-controlled settings.
  6. Add tests proving that HTTP URLs, lookalike domains, unapproved ports, and cross-origin redirects are rejected before the API key is attached.
  7. Document that financial and household parameters are transmitted to the approved third-party API and obtain appropriate user consent.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/config.py:44
Finding

API Key Is Persisted in a Plaintext File Without Enforced Access Permissions

Content
View full analysis

Vulnerability Details

File Location: scripts/config.py:44-65
Vulnerability Type: Insecure 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

scripts/config.py:68-78:

python
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()
    if not save_api_key_to_env(api_key):
        return False
    # 更新全局 settings 实例
    settings.api_key = api_key
    return True

Technical Analysis

set_api_key() always delegates to save_api_key_to_env(), which writes the API credential directly into a plaintext .env file in the current working directory. Path.write_text() does not explicitly enforce owner-only permissions. The resulting permissions depend on the process umask or the permissions of a pre-existing file.

The code also retains the credential across sessions even when persistent storage may not be necessary. In a shared workspace, permissive container, archived project directory, or incorrectly configured host, another lo ...[truncated 1293 chars]

Remediation
View remediation

Remediation Suggestions

  1. Prefer a platform secret manager, operating-system keychain, or session-scoped environment variable instead of project-directory persistence.
  2. Do not persist the key by default; request explicit user consent if persistence is necessary.
  3. If file storage is unavoidable:
    • Create the file atomically with owner-only mode 0600.
    • Verify and correct the permissions of existing files before writing.
    • Avoid following symbolic links.
    • Write to a protected configuration directory outside the project tree.
    • Use an atomic replacement strategy that preserves restrictive permissions.
  4. Reject carriage returns, newline characters, and null bytes in supplied credentials before serialization.
  5. Add .env to .gitignore and relevant packaging and backup exclusion lists.
  6. Document credential location, retention behavior, rotation, and deletion procedures.
  7. Provide a function that securely removes the persisted credential and clears the in-memory and process-environment copies.
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 (34)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill advertises income-tax calculation and bracket retrieval, but its toolset is much broader, including tax forms, procedures, deadlines, law search, article lookup, caching, and report generation. While not inherently malicious, the broader operational scope weakens user consent and makes misuse or unexpected data handling more likely.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill advertises income-tax calculation and bracket retrieval, but its toolset is much broader, including tax forms, procedures, deadlines, law search, article lookup, caching, and report generation. While not inherently malicious, the broader operational scope weakens user consent and makes misuse or unexpected data handling more likely.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill advertises income-tax calculation and bracket retrieval, but its toolset is much broader, including tax forms, procedures, deadlines, law search, article lookup, caching, and report generation. While not inherently malicious, the broader operational scope weakens user consent and makes misuse or unexpected data handling more likely.

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

The code explicitly reads .env and extracts XBY_APIKEY outside the standard settings mechanism, giving the application direct access to a stored credential. This is dangerous because it normalizes custom secret handling, makes auditing harder, and supports undeclared external service access in a tool whose stated purpose does not obviously require such credential retrieval.

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

Opening and reading the .env file directly is part of a custom credential access path that exposes secrets to application logic. In a seemingly simple tax calculator skill, this hidden secret access is more suspicious because it departs from minimal functionality and can facilitate unauthorized use of external services if the host environment contains sensitive credentials.

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

This function persists an API key to .env in plaintext, creating long-lived local credential storage. If the file is readable by other users, captured in backups, logged, or accidentally committed, the external API credential can be stolen and abused, making this more dangerous than simple in-memory handling.

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

The skill declares broad capabilities implied by its workflow and project structure (environment access, file read/write, and network use) but does not define an explicit tool scope such as permissions or allowed-tools. This increases the attack surface because an agent may exercise more authority than users expect, especially when combined with credential collection and external API access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill explicitly asks the user for an API key and persists it via configuration, but does not warn about storage duration, plaintext handling, who can access it, or whether it will be transmitted externally. This creates a credential-handling risk because users may disclose secrets without informed consent and the key may be stored insecurely.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill combines secret collection and persistence with instructions to present raw returned data directly to the user. In practice, upstream responses can contain sensitive content, reflected secrets, debug details, or excessive metadata, so unfiltered display creates a realistic natural-language data leakage path.

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 and project structure reference unrelated gaokao functions and directory names, which strongly suggests copy-pasted instructions from a different skill. In a security context, such inconsistencies are dangerous because they can mask unintended tool calls, confuse operators, and indicate insufficient review of code paths that may still point to unrelated backends or data domains.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The instructions explicitly tell the model to directly display result['raw'] after formatting, without any filtering or validation. If the external API returns sensitive metadata, stack traces, echoed credentials, or unexpected content, the skill may disclose it to the user verbatim.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The function accesses a credential via get_api_key() and places it into the XBY-APIKEY request header for an external HTTP call. The file lacks any user-facing warning or clear descriptive comment/docstring that the skill reads stored credentials and transmits them to a remote service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code sends the caller-provided params payload over the network via POST, which may include user or system data. While the module logs success and errors internally, it does not provide a user-facing warning, confirmation, or explanatory comment/docstring disclosing that data is transmitted to an external service.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code adds secret management and persistence behavior that is not clearly necessary for a French tax calculation service. Persisting an external API key to a local .env file broadens the attack surface by creating a reusable credential store on disk, which could be exposed through local file disclosure, accidental commits, backups, or multi-tenant environments.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Writing the API key into .env creates a plaintext credential at rest, which is a common source of secret leakage. In the context of a tax calculator, this capability is not obviously justified and is therefore more suspicious because it enables durable credential retention unrelated to the stated user-facing function.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The docstring states the skill retrieves information specifically from official French government websites, and multiple functions are similarly described as handling French tax information only. This creates a locale-specific behavior without any visible user choice, opt-in, or justification in the file, which matches the language/locale policy concern.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest describes a service focused on calculating French personal income tax from net taxable income and household composition, with dynamic retrieval of current tax brackets. In addition to those expected functions, this file exposes unrelated capabilities for tax forms, procedures, deadlines, tax-law article search, general web tax-topic retrieval, and report generation, which materially broadens the skill's behavior beyond the declared scope.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The generate_tax_report tool accepts an output_file parameter and forwards it directly to a backend API, introducing a file-generation capability that exceeds the core tax-calculation purpose. If the downstream API writes to arbitrary paths or uses unsafe filename handling, this could enable unauthorized file creation or overwrite in the execution environment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

This skill's title, description, and operating instructions are written in Chinese, which effectively forces a specific language for users and integrators. The file does not offer an opt-in language choice or explain that the Chinese-only presentation is required for a specific regional or organizational context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The skill describes obtaining data from external websites and APIs but does not clearly warn users that requests and possibly user-supplied tax topics or identifiers will be transmitted over the network. This is a transparency and privacy issue, particularly in a tax context where query content may reveal sensitive personal or legal interests.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The dependency specifier requests>=2.31.0 is unpinned, so builds may resolve to different versions over time. This weakens reproducibility and can unintentionally introduce a vulnerable or breaking release from the supply chain.

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

requests has known advisories, and because the manifest does not pin an exact version, it is impossible to verify from this file whether the installed release is affected. The main risk is uncertainty and accidental installation of a vulnerable version, not proof that the current deployment is exploitable.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The dependency specifier pydantic>=2.7.0 allows any later version, which makes deployments non-reproducible and may pull in a vulnerable release without review. In security-sensitive services, this increases supply-chain exposure even if no specific exploit is present in the file itself.

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