Back to skill

Security audit

身份证识别OCR

Security checks for vulnerabilities and agentic risk

Overview

This appears to be an ID-card OCR skill, but it sends sensitive identity documents to an external API and stores API keys locally without enough disclosure or safeguards.

Review before installing. Use this only if users understand that full ID-card image links or Base64 images may be sent to the Xiaobenyang service, and that the API key is stored in a local plaintext .env file. Do not use it for regulated or third-party identity documents unless consent, retention, deletion, and credential-protection requirements are handled outside the skill.

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)

other

Error
Location
scripts/tools.py:17
Finding

ID-card images are transmitted to a third-party API without an explicit consent step

Content
View full analysis

Vulnerability Details

File Location: scripts/tools.py:17-21, scripts/tools.py:36-40, scripts/call_api.py:50-75, and the missing consent requirement in SKILL.md:8-106
Vulnerability Type: Undisclosed Sensitive Data Transmission
Risk Level: High

Complete Code Snippet

scripts/tools.py:17-21:

python
    arguments = {
        "dataUrl": dataUrl
    }
    
    return call_api("1826285519177738", "ocr_id_card", arguments)

scripts/tools.py:36-40:

python
    arguments = {
        "dataBase64": dataBase64
    }
    
    return call_api("1826285519177738", "ocr_id_card_for_data_base64", arguments)

scripts/call_api.py:50-75:

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),
                timeout=settings.timeout_seconds,
            )

Technical Analysis

The two OCR functions forward either an ID-card image URL or the complete Base64-encoded image to https://mcp.xiaobenyang.com/api. Such images may expose a person's name, address, date of birth, national identification number, issuing authority, photograph, and document validity period.

HTTPS protects the data in transit, but it does not address whether the user has been adequately informed that the document is being disclosed to an external service. The documented workflo ...[truncated 1638 chars]

Remediation
View remediation

Remediation Suggestions

  1. Require affirmative consent immediately before each document upload.
  2. Clearly disclose the external recipient, endpoint, transmitted data, processing purpose, retention period, deletion procedure, and privacy policy.
  3. Do not treat API-key enrollment as consent to transmit a specific identity document.
  4. Minimize transmitted data by cropping or redacting fields that are not required for the requested operation.
  5. Offer local OCR or an explicitly configured trusted endpoint where practical.
  6. Define and enforce retention and deletion requirements with the service provider.
  7. Avoid logging request bodies, Base64 input, document URLs, OCR results, or identification numbers.
  8. Add a confirmation gate such as: “This image will be sent to the configured Xiaobenyang service for processing. Continue?”
  9. Validate that the endpoint remains HTTPS and document the trust boundary in SKILL.md.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/config.py:46
Finding

API key is persisted in a plaintext environment file without enforced restrictive permissions

Content
View full analysis

Vulnerability Details

File Location: scripts/config.py:46-67
Vulnerability Type: Plaintext Credential Storage
Risk Level: Medium

Complete Code Snippet

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

save_api_key_to_env stores the API credential directly in plaintext in .env. Path.write_text neither requests a restrictive file mode nor verifies that the target is a regular file owned by the expected user. For a newly created file, effective permissions depend on the process umask. For an existing file, potentially permissive permissions remain unchanged.

The implementation also performs a non-atomic read-modify-write operation and does not reject symbolic links. In a directory writable by another local principal, a maliciously prepared .env symlink could redirect the write to another file writable by the running user. The directly demonstrated confidentiality issue is plaintext credential storage without enforced access controls; symlink exploitation depends on deployment directory permissions.

Attack Path

  1. The user provides a valid API key through the documented setup workflow.
  2. `s ...[truncated 1202 chars]
Remediation
View remediation

Remediation Suggestions

  1. Prefer an operating-system keyring, managed secret store, or runtime-only secret injection instead of persistent plaintext storage.
  2. If file storage is unavoidable, create the file atomically with mode 0600 and verify ownership and permissions before every read or update.
  3. Open the destination with protections against symbolic-link traversal, such as O_NOFOLLOW where supported, and verify that it is a regular file.
  4. Write through a securely created temporary file in the same directory, apply restrictive permissions, flush it, and atomically replace the destination.
  5. Ensure .env is excluded from source control, package archives, telemetry, debugging output, and backups that do not provide equivalent secret protection.
  6. Store the secret in a user-specific configuration directory rather than the current working directory.
  7. Provide credential rotation and revocation guidance in case a key is exposed.
  8. Apply least-privilege API scopes and usage limits to reduce the consequences of credential theft.
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

The documentation for an ID-card OCR skill also instructs the model to read and persist API keys via configuration and .env-related mechanisms, and references a mismatched 'gaokao' project structure. For a skill handling highly sensitive identity documents, undisclosed credential persistence and unrelated configuration management materially expand risk and indicate poor separation of concerns.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documentation for an ID-card OCR skill also instructs the model to read and persist API keys via configuration and .env-related mechanisms, and references a mismatched 'gaokao' project structure. For a skill handling highly sensitive identity documents, undisclosed credential persistence and unrelated configuration management materially expand risk and indicate poor separation of concerns.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

This skill processes extremely sensitive personal data from national ID cards, yet the documentation does not warn users that images, base64 payloads, and extracted identity fields may be sent to an external API or potentially stored during processing. Lack of informed consent, privacy notice, retention limits, and transmission disclosure is especially dangerous because misuse or breach could enable identity theft, fraud, and regulatory non-compliance.

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

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code force-reads a local secret-bearing .env file and extracts XBY_APIKEY manually, which creates unnecessary secret access behavior for a skill advertised as OCR functionality. In the context of a document-processing skill that may handle highly sensitive PII, broad local secret access expands the trust boundary and raises the risk of unintended credential exposure or abuse.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

This line begins manual access to a local .env file specifically to retrieve an API key, introducing direct credential-reading logic into a skill whose stated purpose is OCR. Manual secret harvesting code increases the chance of over-collection, unsafe parsing, and unauthorized access to locally stored credentials.

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

Checking for and opening the .env file as part of normal skill initialization enables local secret discovery behavior beyond what an OCR utility should need. Because the skill context involves sensitive identity documents, combining PII processing with local credential access makes the overall behavior more dangerous and harder to justify.

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

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

This OCR skill includes functionality to persist and manage an external API credential in a local .env file, which is outside the expected scope for simple ID-card recognition configuration and increases secret-handling risk. Storing credentials on disk and mutating process environment variables can expose the key to other local users, accidental commits, backups, or unrelated components, especially when the skill processes sensitive identity documents.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

This function explicitly writes an API key into a local .env file, creating plaintext credential persistence in the project directory. That exposes the secret to accidental disclosure via source control, logs, backups, multi-user systems, or later compromise of the host, and is especially risky in an OCR skill handling government ID data.

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

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

This function transmits highly sensitive personal data from an ID-card image to an external API via call_api, but the file contains no visible consent, disclosure, minimization, or trust-boundary controls. Because ID cards contain government-issued identifiers and other PII, sending them to a third-party service creates substantial privacy, compliance, and data-handling risk if users are unaware or if the remote service is not strictly governed.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

This function sends a base64-encoded ID-card image to an external API, which is equivalent to sending the full underlying document image and all embedded PII. Base64 encoding is not a protection mechanism, so without clear warning, consent, and data-governance safeguards, the skill exposes users to significant privacy and regulatory risk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill declares no explicit tool scope or permission boundaries despite documented capabilities to read/write environment configuration, persist API keys, and call external network services. In practice this creates an over-privileged integration surface where a seemingly simple OCR skill can access broader local and remote resources than users would reasonably expect.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
76% confidence
Finding

The entire skill is written as Chinese-only documentation and names the skill specifically for Chinese ID-card OCR, but it does not explicitly state that the locale/language restriction is intentional nor provide user opt-in or alternatives. Under the policy, forcing a specific language or locale without choice or clear justification can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The example tool invocation references an unrelated school-search function, which contradicts the OCR-only purpose and suggests the routing layer may be copied from a broader tool-calling template. In a sensitive-data skill, such ambiguity increases the chance of unintended tool invocation, parameter leakage, or accidental transmission of user data to the wrong backend.

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 caller-controlled params and the API credential to an external service with no validation, minimization, consent gate, or destination safety checks. In the context of an ID-card OCR skill, the transmitted data is highly sensitive PII, so silent forwarding of full document contents or extracted identity fields to an upstream provider creates significant privacy, compliance, and data-exposure risk if misused, misconfigured, or pointed at an untrusted endpoint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The function persists an API key to .env in plaintext without any visible warning, consent flow, or indication to the user that the credential will be stored locally. This can lead to accidental long-term retention of secrets, leakage through source control or filesystem access, and user misunderstanding about how their credentials are handled.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

L091 将项目目录写为 xiaobenyang_gaokao_skill/,这与全文关于“身份证识别OCR”的技能用途明显不一致,属于文档对代码/技能身份的主动性误导。虽然这不直接证明运行时代码执行了别的行为,但该内联文档确实与技能声明意图相矛盾。

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 future installs may resolve to different versions over time. This weakens reproducibility and can unintentionally introduce vulnerable or breaking releases through the supply chain, especially for a skill that likely handles sensitive identity data and may make outbound API calls.

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

The manifest references requests without pinning an exact version, while the package has multiple known advisories. Because the actual installed version is unknown, you cannot verify whether the deployment includes a fixed release, which is a supply-chain risk for a skill that may transmit OCR data or credentials to external services.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

pydantic>=2.7.0 allows installation of any later version, making builds non-reproducible and leaving the deployed package version uncertain. This can expose the skill to newly introduced vulnerabilities or behavior changes in a library often used for parsing and validation of potentially attacker-controlled input.

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

pydantic has known advisories, but the unpinned requirement prevents determining whether a safe or affected version will be installed. Since this library validates and parses application data, unresolved version ambiguity can leave the skill exposed to parser-related denial-of-service or validation issues.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

pydantic-settings>=2.2.0 is unpinned, so dependency resolution may pull different versions across environments. For a package involved in configuration and secret loading, this increases supply-chain and configuration-handling risk because vulnerable or incompatible versions may be installed without review.

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

pydantic-settings has a known advisory history, and without version pinning there is no assurance that the installed release contains the necessary fixes. Because settings libraries can interact with secrets and filesystem-based configuration sources, uncertainty here is security-relevant even if no direct exploit path is shown in this file alone.

Content

No source excerpt is available for this finding.