T09 · Insecure Skill Coding Practices
- Location
scripts/call_api.py:56- Finding
Configurable API Endpoint Enables API Key and OCR Data Disclosure
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This OCR skill is a plausible remote API wrapper, but it asks for and stores an API key in plaintext and can send images and the key to a configurable remote endpoint without clear safeguards.
Review before installing. This skill sends your image URL or full base64 image to XiaoBenYang's remote API and stores your API key in a local .env file. Use it only in a trusted workspace, avoid sensitive documents unless you accept that remote processing, and rotate the API key if the project directory or .env may have been shared.
scripts/call_api.py:56Configurable API Endpoint Enables API Key and OCR Data Disclosure
scripts/config.py:45API Key Persisted in Plaintext Without Enforced Restrictive File Permissions
Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.
The skill is presented as OCR, but it also reads, writes, and persists API keys through environment and .env management. That behavior materially expands the security scope from image processing to secret handling and local configuration mutation, which is not transparently disclosed to users.
The skill is presented as OCR, but it also reads, writes, and persists API keys through environment and .env management. That behavior materially expands the security scope from image processing to secret handling and local configuration mutation, which is not transparently disclosed to users.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
model_config = SettingsConfigDict(
env_prefix="XBY_GAOKAO_",
env_file=".env",
env_file_encoding="utf-8",
extra="ignore",
)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
model_config = SettingsConfigDict(
env_prefix="XBY_GAOKAO_",
env_file=".env",
env_file_encoding="utf-8",
extra="ignore",
)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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")
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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")
The code writes the API key into a local .env file and also exports it into the process environment, creating multiple persistence locations for a sensitive secret. This increases the likelihood of credential leakage through file disclosure, backups, logs, misconfigured packaging, or reuse by unrelated components running in the same process.
This function is explicitly designed to persist an API key into a .env file, which creates a durable plaintext secret on disk. In the context of an OCR skill, that capability is unnecessary and dangerous because it broadens the skill from document processing into local credential storage, making accidental disclosure or later abuse much more likely.
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()
The skill exposes capabilities implying environment access, file read/write, and network use, but does not declare an explicit tool scope or permissions boundary. That increases the chance of over-privileged execution and makes it harder for reviewers or the runtime to constrain what the skill may access.
The natural-language content throughout the skill is entirely in Chinese and presents the skill as operating in that locale, but there is no explicit opt-in, language selection, or justification that this is a region-specific tool. Under SQP-3, forcing a specific language without user choice can be a policy violation.
The skill instructs the model to ask the user for an API key and then persist it via configuration writes. Collecting secrets in-band through the chat flow and storing them locally increases the risk of accidental disclosure, improper retention, logging exposure, and reuse outside the user's expectations.
The documentation mixes OCR with unrelated school-search/gaokao references, indicating copied or inconsistent workflow instructions. Such inconsistencies can cause the agent to call unintended functions or mask broader functionality than users expect.
The workflow explicitly instructs use of an unrelated search_schools function despite the declared OCR toolset. Contradictory invocation guidance increases the risk of unintended tool use and suggests the skill specification may not reliably describe what the agent should execute.
The skill asks users to provide image URLs or base64 image data to a remote OCR service without warning that image contents may contain sensitive information and will be transmitted externally. In OCR contexts, uploaded images often contain personal, financial, or confidential text, so lack of notice increases privacy and compliance risk.
The instruction to directly display raw API/OCR output can expose sensitive extracted text from uploaded images without review or minimization. Since OCR commonly processes IDs, invoices, screenshots, and documents, raw output presentation may leak more personal or confidential data than necessary.
This code sends request parameters to an external API and includes an API key in headers, which is a safety-relevant network operation. While the module has internal logging for success/error paths, there is no user-facing warning, confirmation, or explanatory comment/docstring disclosing that user-supplied data and credentials are transmitted off-system.
The OCR skill claims a narrow text-recognition purpose, but this module adds persistent API-key management functionality unrelated to simple OCR input processing. Expanding a skill's capabilities to read, store, and expose external service credentials increases attack surface and creates an unnecessary secret-handling pathway that could be abused by other code in the skill.
The function sends a user-supplied image URL to an external OCR API, but this file provides no disclosure, consent mechanism, or indication of where the image data will be processed. Because images may contain sensitive personal, financial, or business information, silent transfer to a third party creates a real privacy and data-handling risk.
This function transmits raw base64-encoded image contents directly to an external API, which can expose the full contents of sensitive documents or screenshots without any warning in this file. Base64 input often represents locally sourced files rather than public URLs, so the privacy impact is heightened because users may reasonably expect the data to remain local unless clearly informed otherwise.
The dependency specification uses a lower bound (requests>=2.31.0) rather than an exact pin or constrained lockfile, which makes builds non-reproducible and can cause installation of later releases with undiscovered or newly introduced vulnerabilities. In a security-sensitive skill that may process external inputs and make network requests, supply-chain uncertainty increases operational risk even though the manifest itself is not directly exploitable.
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
The manifest does not pin requests, and the package has multiple known advisories across versions, so security posture cannot be verified from this file. In an OCR skill, requests is likely used for remote API access or downloads, making dependency ambiguity more relevant because network-facing code often handles attacker-controlled destinations or content.
pydantic is declared with an open-ended minimum version, so deployments may resolve to different versions over time. That weakens reproducibility and makes it impossible to determine from this file alone whether the installed version includes fixes for known issues such as denial-of-service bugs.
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
pydantic has known advisories in some versions, but the unpinned requirement prevents verification that deployed instances are patched. Since OCR skills often parse structured settings and user-provided metadata, leaving the version unresolved can expose the service to parser-level denial-of-service or validation flaws.
pydantic-settings is also unpinned, so future installs may pull different releases with different security properties. For configuration-loading libraries, this matters because parsing and secrets-handling behavior can change and potentially expose the application to known package-level flaws.
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
No suspicious patterns detected.