Back to skill

Security audit

银行卡识别OCR

Security checks for vulnerabilities and agentic risk

Overview

This bank-card OCR skill is mostly coherent, but it sends sensitive card imagery to an external API and persists an API key in plaintext without enough privacy, retention, or output-redaction guidance.

Review before installing. Only use this skill if you are comfortable sending bank-card images or image URLs to the XiaoBenYang API and storing the API key in a local plaintext .env file. Avoid submitting cards with security codes or unnecessary personal details, rotate the API key if exposed, and prefer a version that masks card numbers, documents retention/privacy terms, and uses a secret manager instead of plaintext .env storage.

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:53
Finding

API Key Persisted in a Plaintext File Without Explicit Permission Controls

Content
View full analysis

Vulnerability Details

File Location: scripts/config.py:53-60
Vulnerability Type: Plaintext credential storage
Risk Level: Medium

Vulnerable Code

python
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

Technical Analysis

The supplied API key is written directly to .env as plaintext. The implementation does not explicitly create the file with restrictive permissions or verify the permissions of an existing file. Its confidentiality therefore depends on the process umask, existing filesystem permissions, deployment environment, backup configuration, and repository hygiene.

The update is also performed directly rather than through a securely created temporary file followed by an atomic replacement. While this primarily creates an integrity and reliability concern, the principal security issue is persistent plaintext credential storage.

Attack Path

  1. A user provides a valid API key as required by the skill.
  2. set_api_key() invokes save_api_key_to_env().
  3. The key is written to the project working directory in .env.
  4. A local user or process with permission to read that file, a backup collector, or a repository operation that includes .env obtains the credential.
  5. The exposed key is used to make unauthorized requests to the XiaoBenYang API until it is revoked.

Exploitation requires access to the .env file or to a copy of it; this code does not itself grant such access.

Impact Assessment

Disclosure grants the attacker the API authorization associated with XBY_APIKEY. This may permit unauthorized API usage, consumption of account quotas, access to responses available to that API identity, and charges or servi ...[truncated 125 chars]

Remediation
View remediation

Remediation Suggestions

  • Prefer an operating-system credential manager, orchestrator secret, or session-only environment variable instead of persistent plaintext storage.
  • If file persistence is required, create the file with owner-only permissions such as 0600 and reject or correct an existing file with broader permissions.
  • Write updates through a securely created temporary file in the same directory, apply restrictive permissions, and atomically replace the destination.
  • Ensure .env is excluded from source control, build artifacts, diagnostics, and backups that are not approved to contain secrets.
  • Avoid printing exception details that could reveal sensitive paths or values.
  • Document credential rotation and immediately revoke keys suspected of exposure.

other

Warning
Location
scripts/call_api.py:44
Finding

Bank-Card Images Are Transmitted to an External Service

Content
View full analysis

Vulnerability Details

File Locations: scripts/tools.py:17-20, scripts/tools.py:36-39, and scripts/call_api.py:44-72
Vulnerability Type: External disclosure of sensitive financial imagery
Risk Level: Medium

Vulnerable Code

python
# scripts/tools.py:17-20
arguments = {
    "dataUrl": dataUrl
}

return call_api("1826285517101066", "ocr_bank_card", arguments)
python
# scripts/tools.py:36-39
arguments = {
    "dataBase64": dataBase64
}

return call_api("1826285517101066", "ocr_bank_card_for_data_base64", arguments)
python
# scripts/call_api.py:44-72
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",
}

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

Technical Analysis

The skill sends either a bank-card image URL or the complete Base64-encoded image to https://mcp.xiaobenyang.com/api. A bank-card image can contain a primary account number, cardholder name, expiration date, bank identity, and other sensitive information.

The project documentation states that an API is called, but it does not prominently explain the financial-data disclosure, identify applicable retention behavior, or require explicit user consent immediately before upload. No local redaction or data minimization is performed. The claimed OCR and Luhn validation are delegated entirely to the external service rather than implemented locally.

For URL-based input, the external processor receives the supplied URL and may retrieve the image from that location. For Base64 input, the complete image is inc ...[truncated 1132 chars]

Remediation
View remediation

Remediation Suggestions

  • Display a clear disclosure naming the external recipient and obtain explicit user consent immediately before transmission.
  • Provide the processor's privacy policy, retention period, deletion procedure, data residency information, and security responsibilities.
  • Implement local OCR and Luhn validation where feasible to avoid transmitting card imagery.
  • Crop or redact all image content not essential to the requested operation.
  • Never request or retain security codes, PINs, or unrelated identity information.
  • Avoid logging request bodies, Base64 content, card numbers, or raw upstream responses containing card data.
  • Define and enforce deletion and retention controls with the external processor.
  • Apply appropriate payment-card and privacy compliance controls for the intended deployment environment.

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Dependencies Use Open-Ended Version Constraints Without a Lockfile or Hashes

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1-4
Vulnerability Type: Non-reproducible dependency resolution
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 uses an open-ended minimum-version constraint. A future installation can therefore select releases that were not present during review. The project provides no lockfile and no package hashes to ensure that installations resolve to previously reviewed artifacts.

The package names shown are not evident typosquatting names, and the audit did not identify a currently malicious dependency. The risk arises from mutable and non-reproducible resolution: a compromised, vulnerable, or incompatible future release could be selected automatically.

Attack Path

  1. The skill is installed or rebuilt at a later date.
  2. The package resolver selects the newest versions satisfying the >= constraints.
  3. One selected release contains a newly introduced vulnerability or has been compromised through the package supply chain.
  4. Dependency installation or runtime import executes the affected package code in the skill's environment.
  5. That code receives the privileges of the installation or runtime process.

This path depends on a vulnerable or compromised allowed release becoming available; no such specific release was established during this audit.

Impact Assessment

Potential impact is bounded by the privileges of the process installing or running the skill. A compromised dependency could access application data, environment variables, the persisted API key, submitted card images, network connectivity, and writable files available to that process. The current manifest alone does not demonstrate active compromise.

Remediation
View remediation

Remediation Suggestions

  • Pin dependencies to reviewed exact versions in a reproducible lockfile.
  • Use package hashes and hash verification during installation.
  • Generate locks separately for supported Python versions and deployment platforms when necessary.
  • Run automated vulnerability and license scanning in continuous integration.
  • Review and deliberately update dependencies on a controlled schedule.
  • Install packages from an approved package index and prevent unintended fallback to untrusted indexes.
  • Run the application with least privilege so a compromised dependency has limited access.
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 (32)

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

The skill’s stated purpose omits that it reads API keys from .env/environment variables, writes secrets back to .env, updates process environment variables, and manages external service configuration. For a workflow handling bank-card imagery and secrets, undisclosed secret persistence and config mutation materially increase the risk of credential leakage, misuse, or cross-session exposure.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill’s stated purpose omits that it reads API keys from .env/environment variables, writes secrets back to .env, updates process environment variables, and manages external service configuration. For a workflow handling bank-card imagery and secrets, undisclosed secret persistence and config mutation materially increase the risk of credential leakage, misuse, or cross-session exposure.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file implements a generic upstream API invocation client that can call arbitrary MCP tools via caller-controlled tool_name, mcp_id, and params, which does not match the declared purpose of bank-card OCR and Luhn validation. This capability expansion is dangerous because it can enable unintended remote actions, data access, or proxying through a trusted skill boundary, especially when users expect a narrowly scoped OCR utility.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code exposes a generic remote tool-calling primitive by placing unvalidated tool_name and mcp_id into request headers and forwarding arbitrary JSON parameters upstream. In the context of a skill advertised as bank-card OCR, this mismatch increases risk because the skill may be granted trust, permissions, or sensitive inputs inappropriate for a general-purpose remote execution/invocation wrapper.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The configuration clearly targets a different skill domain than the declared bank-card OCR purpose: it uses a gaokao-specific env prefix, a hard-coded MCP identifier, and API-key management unrelated to local OCR/Luhn validation. This mismatch is dangerous because it can hide undeclared external service use and credential collection behind an innocuous bank-card OCR description, increasing the risk of covert data exfiltration or user deception.

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

The model_post_init method force-reads XBY_APIKEY from a local .env file regardless of the declared bank-card OCR scope. In a skill that may process sensitive card data, this undisclosed credential access is more concerning because it suggests hidden dependence on remote services and creates opportunities for secret harvesting or misuse.

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

The explicit existence check and subsequent read of .env is part of active credential retrieval logic, not passive configuration. Combined with the skill-purpose mismatch, this increases the likelihood that the skill is accessing secrets unrelated to its advertised OCR functionality.

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

This function is explicitly designed to persist an API key into a local .env file, creating durable plaintext secret storage. In the context of a bank-card OCR skill, that is especially risky because it introduces unnecessary secret-retention behavior alongside processing of highly sensitive financial information.

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 even though its documented/project capabilities include environment access, file read/write, and network use. In an agent setting, missing scope boundaries increases the chance of over-privileged execution, unauthorized secret handling, and unintended external data transfer.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill asks users to provide an API key and processes bank-card images but provides no warning about privacy, retention, storage, or third-party transmission. Because bank-card images and API credentials are highly sensitive, the absence of consent and handling guidance significantly raises the risk of exposing financial and authentication data.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation includes an example tool call to a school-search function unrelated to bank-card OCR. In agent systems, inconsistent tooling examples can cause the model to invoke unintended functions or normalize broader-than-expected capabilities, which is especially risky when the skill handles sensitive financial data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill instructs the agent to directly display raw API/OCR output to the user, which may include full card numbers, issuer details, metadata, or other sensitive fields. Exposing unfiltered raw responses increases the likelihood of leaking financial data in logs, transcripts, screenshots, or downstream tools.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The class docstring identifies the code as a gaokao skill rather than a bank-card OCR skill. In isolation this looks minor, but in this context it reinforces a broader identity mismatch that can mislead reviewers and users about what the component actually does and what data it may send or store.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This skill claims to perform bank-card OCR and Luhn validation, yet it includes persistent API credential storage in a local .env file. For a capability handling sensitive financial data, introducing durable credential handling without clear necessity expands the attack surface and can enable unauthorized reuse of secrets or undisclosed backend access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code writes API credentials directly into a local .env file and updates process environment state without any user-facing warning or consent flow. Persisting secrets this way can expose them through backups, source-control mistakes, multi-user systems, or other local file disclosure paths.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This function sends bank card image data to an external API via call_api without any visible disclosure, consent flow, or indication of data handling safeguards in this file. Because bank card images can contain highly sensitive financial information, silent transmission to a third party creates material privacy, compliance, and data exposure risk if users are not explicitly informed.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This function transmits base64-encoded bank card image content to an external API, which is still raw sensitive financial image data despite the encoding. Sending such data off-box without an in-code warning, consent mechanism, or evident privacy controls increases the chance of unauthorized disclosure, regulatory violations, and downstream misuse by the external processor.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

L091 将项目结构写为 xiaobenyang_gaokao_skill/,但当前技能整体内容是银行卡 OCR,不是高考查询。虽然这不直接展示代码行为,但属于内联文档对技能身份的明显错误描述,容易造成开发与集成时的意图混淆。

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency is specified with a lower-bound range instead of an exact version, which makes builds non-reproducible and can unintentionally pull in newly released versions with security or compatibility regressions. In a skill that may process sensitive financial data, weak dependency control increases supply-chain risk even though the manifest itself does not prove active 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
91% confidence
Finding

The manifest does not pin requests, and the package has multiple known advisories, so it is impossible to determine from this file whether deployments are using a patched or vulnerable release. For a banking-card OCR skill, HTTP client flaws can matter because network requests may involve sensitive data, credentials, or remote service interaction.

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 major-compatible release to be installed, which prevents reproducible deployments and may introduce vulnerable or breaking versions without review. This is a supply-chain hygiene issue rather than evidence of direct malicious behavior.

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 not pinned, the file cannot establish whether the runtime version includes fixes for known vulnerabilities such as denial-of-service issues. In a service that parses externally supplied OCR or metadata inputs, parser-level bugs can become more relevant if untrusted data is validated at scale.

Content

No source excerpt is available for this finding.