Back to skill

Security audit

手写文本OCR

Security checks for vulnerabilities and agentic risk

Overview

This OCR skill appears to call the advertised remote service, but it stores an API key in plaintext and has enough copied or mismatched gaokao instructions to require careful review before use.

Install only if you trust xiaobenyang with both your API key and the handwritten images you submit. Use a limited or revocable API key, avoid sensitive forms or signatures unless remote processing is acceptable, and remove the plaintext .env key when finished.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/config.py:42
Finding

API Key Persisted in a Plaintext File Without 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 function stores the supplied API key as plaintext in a working-directory-relative `.env` file. It does not explicitly set restrictive file permissions, validate that the destination is a regular file rather than a symbolic link, or ensure that the file is stored outside a source repository. For a newly created file, effective permissions depend on the process umask. For an existing file, `Path.write_text()` retains the existing file's permission model. Consequently, the key may be readable by other local users or processes when the surrounding environment or existing permissions are permissive. The use of a relative path also means the destination changes with the process working directory. This can unintentionally place the credential inside a repository, shared directory, backup scope, or other location not intended for secret storage. ### Attack Path 1. A user supplies an API key as required by the Skill workflow. 2. The Skill calls `set_api_key()`, whi ...[truncated 1102 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Open-Ended Dependency Constraints Allow Unreviewed Future Releases

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. The resolver may therefore install any future version satisfying the lower bound. No lock file or package hashes are present to establish a reproducible, reviewed dependency set. This does not prove that any currently named package is malicious or vulnerable. However, it creates a supply-chain weakness: future installation behavior can change without changes to the audited project, and a compromised, malicious, or incompatible future release could be selected automatically. ### Attack Path 1. The project is installed or rebuilt after a newer dependency release becomes available. 2. The package resolver selects that release because it satisfies the open-ended `>=` constraint. 3. The selected package is downloaded without verification against an audit-approved hash. 4. If the release is compromised or introduces exploitable behavior, its code executes during installation, import, or normal Skill operation with the privileges of the Agent process. Exploitation therefore requires compromise or unsafe behavior in an allowed upstream release or in the package-distribution channel; no such compromise was confirmed during this audit. ### Impact Assessment A malicious dependency would execute with the same operating-system permissions as the process installing or running the Skill. Depending on those permissions, it could read accessible credentials and files, alter application behavior, make network requests, or tamper with runtime data. The practical scope depends on the Agent's sandboxing, filesystem permissions, network access, and installation account. The current code alone does not grant elevated privileg ...[truncated 7 chars]
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 (33)

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

The skill is presented as handwriting OCR, but the referenced behavior includes reading and persisting API keys, modifying environment state, and using a gaokao-oriented service layout. This discrepancy suggests code reuse or repurposing without proper hardening, increasing the risk of hidden behaviors, credential misuse, and user deception about what the skill actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill is presented as handwriting OCR, but the referenced behavior includes reading and persisting API keys, modifying environment state, and using a gaokao-oriented service layout. This discrepancy suggests code reuse or repurposing without proper hardening, increasing the risk of hidden behaviors, credential misuse, and user deception about what the skill actually does.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The module’s behavior materially contradicts the declared handwritten OCR purpose: it is configured for an unrelated gaokao service endpoint and includes logic to read, set, and persist an external API key. In a skill whose stated function is local OCR, collecting and storing credentials for an unrelated remote service is highly suspicious and could enable covert credential harvesting or unauthorized outbound service access.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
84% confidence
Finding

Configuring automatic loading from a .env file introduces credential access behavior in a skill that is supposed to perform handwritten OCR. In this context, secret ingestion is unnecessary on its face and increases the chance that sensitive values are consumed or propagated by code unrelated to the declared feature.

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

This code explicitly reads credentials from .env and environment variables and persists them back to disk, despite the advertised skill being handwritten text recognition. In this context, credential handling is unjustified and dangerous because it broadens the attack surface for secret theft, persistence, and misuse without a clear functional need tied to OCR.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The code manually opens and parses the .env file to extract XBY_APIKEY, bypassing normal typed settings handling and creating a direct credential access path. Manual secret scraping is especially suspicious here because it targets a specific API key unrelated to the advertised OCR function, suggesting deliberate credential collection behavior.

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

This line accesses the .env file as a raw source of secrets, enabling the skill to inspect local credentials outside the bounds of its stated OCR purpose. In a mismatched skill, such direct file-based secret access is dangerous because it can support stealthy credential harvesting or persistence.

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

The code prioritizes an environment variable containing an API key and assigns it into application state, extending credential handling for an unrelated service. Although reading environment variables is common, in this skill context it still represents unjustified secret access that could facilitate misuse or accidental leakage.

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

This function is explicitly designed to save an API key into a .env file, creating persistence for a secret unrelated to the skill’s declared OCR capability. Persisting harvested or user-supplied credentials to disk can make compromise durable and expands the blast radius if the host or repository is later exposed.

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

The skill declares no explicit tool scope or permission boundaries even though it appears to rely on environment access, file read/write, and network capabilities. In an agent setting, missing scope declarations can allow broader-than-expected access and make review and enforcement of least privilege much harder.

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, but does not explain storage, retention, or exposure risks. This can lead users to disclose credentials without informed consent, and persisting secrets to .env may make them readable by other tools, processes, or future sessions.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The tool-call example references a gaokao school-search function unrelated to OCR, which is a strong indicator of copied or inconsistent instructions. In agent skills, such inconsistencies can cause the model to invoke the wrong tool, send user data to an unintended backend, or expose capabilities outside the advertised use case.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill accepts image URLs or base64 image contents for OCR but does not warn users that this data will be transmitted to an external service. Because handwritten notes, signatures, and forms often contain sensitive personal or financial information, lack of disclosure materially increases privacy and compliance risk.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Instructing the agent to directly display raw API output can reveal sensitive OCR results such as signatures, IDs, addresses, or form contents without filtering. It may also expose upstream metadata, internal error details, or echoed user inputs that should not be shown verbatim.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

This code reads an API key, places it in request headers, and POSTs the user-supplied params to a remote API. Although errors and success are logged, there is no confirmation prompt, print statement, or warning comment/docstring disclosing that user/system data and credentials will be transmitted off-box.

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 module as configuration for a gaokao skill, directly conflicting with the manifest’s handwritten OCR description. Such identity mismatch is a strong indicator of repurposed or deceptive code, increasing the risk that the skill is performing hidden actions unrelated to the declared functionality.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The function persists an API key into a local .env file automatically, with no user-facing confirmation, warning, or disclosure of the storage location. This is risky because users may unknowingly leave long-lived credentials on disk where they can be exposed through source control, backups, logs, or local compromise.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The function sends user-supplied image data to an external API via call_api, but this file provides no disclosure, consent mechanism, or indication that potentially sensitive handwriting content leaves the local environment. Handwritten notes, forms, and signatures commonly contain personal or confidential information, so undisclosed remote transmission creates a real privacy and data-handling risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This function transmits raw base64-encoded image content to an external API, which may include highly sensitive handwritten material such as IDs, signatures, or personal notes. Base64 is only an encoding, not protection, so absent explicit warning and consent, the code exposes users to unanticipated data sharing and privacy compromise.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

L091 将项目结构标记为 xiaobenyang_gaokao_skill/,但本文件其余部分均描述的是“手写文本OCR”技能。虽然这不直接证明代码行为异常,但属于文档层面对技能身份和用途的明显矛盾,可能导致调用方或维护者误解其真实意图。

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency is specified with a lower-bound constraint only, which allows installation of different future versions over time. This weakens build reproducibility and can unintentionally pull in a vulnerable or breaking release if the dependency supply chain changes.

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

requests has known advisories, but the manifest does not pin the installed version, so it is impossible to verify whether a safe or affected release will be used. In practice this means the project could resolve to a vulnerable version in some environments, especially if builds are not locked.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

Using an unpinned minimum version for pydantic means the resolved package version may vary across environments and over time. This increases supply-chain risk because a newly published vulnerable or incompatible version could be installed without any manifest change.

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

pydantic has published security advisories, and because the dependency is not pinned, the actual installed version cannot be validated from this manifest alone. That uncertainty creates a real but low-severity risk of deploying an affected version unintentionally.

Content

No source excerpt is available for this finding.