T09 · Insecure Skill Coding Practices
- Location
scripts/field_extractor.py:83- Finding
Invoice Data Can Be Transmitted to an Unrestricted VLM Endpoint
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly matches its invoice-processing purpose, but it handles sensitive financial documents with an unenforced local-only network boundary and unsafe spreadsheet output handling.
Review before installing. Use only in an isolated virtual environment, keep OLLAMA_API fixed to a loopback Ollama endpoint, avoid proxy inheritance, and do not process invoices from untrusted sources until spreadsheet formula sanitization and dependency locking are added.
scripts/field_extractor.py:83Invoice Data Can Be Transmitted to an Unrestricted VLM Endpoint
scripts/ledger_builder.py:18Spreadsheet Formula Injection Through Untrusted Invoice Fields and Filenames
scripts/requirements.txt:1Unpinned and Unverified Third-Party Dependencies
描述强调的是一个完整的本地离线发票识别与台账生成系统,核心能力应包括对图片/PDF进行OCR、字段抽取、版面定位及台账汇总。实际代码片段仅是一个验证脚本,负责对已提取好的字段做规则校验、类型判断和月份提取。它与发票处理场景相关,但只覆盖了后处理中的一小部分,无法支撑所宣称的主要功能。因此存在明显的描述与代码行为不一致。不过,代码没有显示任何对外传输或越权访问行为。
Referenced artifact was not completely inspected
运行脚本前确认依赖已装:`pip install -r scripts/requirements.txt`,且 Ollama 已加载本地多模态模型(默认 `qwen2.5vl:7b`,可用环境变量 `VLM_MODEL` / `OLLAMA_API` 覆盖)。
README 将“整理发票”直接作为聊天输入触发词,但未说明是否仅在特定代理、特定上下文或特定文件夹选择流程下才会激活。该短语属于常见办公表达,容易与普通对话需求重叠,增加误触发风险。
“财税咨询”是高频、泛化的自然语言表达,README 未说明该触发是否要求已有台账文件、是否仅限本套工具内调用,或哪些类似说法不应触发。缺少范围约束会使技能调用条件不清晰。
Without declared permissions the skill's intent is opaque and cannot be validated.
The trigger phrases are broad business-language terms like '整理发票' and '票据汇总', which can overlap with normal conversation and cause unintended activation. In this skill's context, accidental triggering could lead to file-processing workflows, terminal execution, or requests for sensitive invoice directories, increasing the chance of unintentional handling of financial data.
The function reads the full image file, base64-encodes it, and sends it via HTTP to config.OLLAMA_API. Although the docstring says a local Ollama model is used, there is no explicit user-facing warning, confirmation, logging, or comment disclosing that invoice contents will be transmitted to another service for processing.
The code transmits full invoice image contents, base64-encoded, to whatever URL is configured in config.OLLAMA_API using HTTP requests, without any in-function validation that the endpoint is truly local. In a financial-document processing skill, misconfiguration or malicious configuration could route sensitive invoice data to a remote service, causing data leakage of billing, tax, and vendor information.
"format": VLM_SCHEMA,
"stream": False,
}
r = requests.post(config.OLLAMA_API, json=payload, timeout=180)
r.raise_for_status()
return json.loads(r.json()["message"]["content"])
The OCR client is initialized with lang="ch", which hard-codes a specific language/locale behavior. Under the policy, forcing a language without user opt-in or clear documented justification is a natural-language policy violation.
The skill is explicitly described as fully local and offline, yet it depends on requests, a general-purpose HTTP client. In a privacy-sensitive invoice-processing tool, this creates a credible path for unexpected network egress, dependency drift toward online behavior, or hidden exfiltration of financial data, even if the file alone does not prove active misuse.
This code uses Chinese-only natural-language strings in the module docstring and all validation messages, which effectively forces a specific language/locale for users. The file does not provide any opt-in, fallback, or documented justification that the skill is intentionally restricted to a Chinese-language or region-specific workflow.
README 中明确写到 PaddleOCR 首次会自动下载“中文识别模型”,整体文档与交互也默认固定为中文,但未说明这是可配置选项或仅适用于中文票据场景。按规则,这类语言/locale 约束若无选择机制或明确限定,构成自然语言政策风险。
The file uses Chinese-language comments and Chinese ledger header strings exclusively, with no indication that language selection is configurable or user-driven. Under the policy, hard-coding a specific language/locale without opt-in can be a natural-language policy violation.
Natural-language strings, extraction labels, and the VLM prompt are all fixed in Chinese, which constrains the skill to a specific language/locale without any visible opt-in or user choice. Under the stated policy, forcing a specific language can be a locale-policy violation unless explicitly justified or made optional.
This code creates the output directory and saves an Excel workbook to the user-supplied path, which is a file write operation affecting local data. There is no confirmation prompt, print/log message, or explanatory comment/docstring beyond the brief Chinese summary, so the write behavior is not clearly disclosed within this file.
Using paddleocr>=2.7.0 allows any future version above the minimum to be installed, making builds non-reproducible and weakening supply-chain control. This can silently introduce breaking changes or vulnerable releases into a tool that processes sensitive local financial documents.
paddleocr>=2.7.0
paddlepaddle>=2.6.0
PyMuPDF>=1.23.0
opencv-python>=4.8.0
Using paddlepaddle>=2.6.0 permits uncontrolled upgrades and makes it impossible to know which exact package version will be installed. For a complex native/ML dependency with known advisories, this increases exposure to vulnerable or incompatible releases.
paddleocr>=2.7.0
paddlepaddle>=2.6.0
PyMuPDF>=1.23.0
opencv-python>=4.8.0
openpyxl>=3.1.0
paddlepaddle has known advisories, and because the manifest does not pin a specific version, it is impossible to verify whether installation will select a fixed or affected release. In a local document-processing tool, vulnerable native/ML components could be triggered by crafted inputs or unsafe file handling paths.
Using PyMuPDF>=1.23.0 leaves the installed version unconstrained above a floor, reducing reproducibility and allowing vulnerable releases to be pulled in later. Because this library parses PDFs, version uncertainty is especially risky when handling untrusted invoice files.
paddleocr>=2.7.0
paddlepaddle>=2.6.0
PyMuPDF>=1.23.0
opencv-python>=4.8.0
openpyxl>=3.1.0
requests>=2.31.0
PyMuPDF has reported advisories, and the unpinned requirement prevents verification that a safe version is used. Because this skill parses PDFs from invoices, any parser-level issue becomes more relevant: hostile or malformed PDFs are a realistic input in this context.
Using opencv-python>=4.8.0 allows unreviewed future versions into the environment. Since image parsing libraries often have memory-safety issues, this weakens supply-chain assurance for a tool that ingests potentially untrusted invoice images.
paddleocr>=2.7.0
paddlepaddle>=2.6.0
PyMuPDF>=1.23.0
opencv-python>=4.8.0
openpyxl>=3.1.0
requests>=2.31.0
opencv-python has multiple advisories, and the lack of version pinning means the actual installed version may be vulnerable. Since the tool ingests external images for OCR, image-parsing flaws could be reachable through malicious invoice files.
Using openpyxl>=3.1.0 means the exact installed package may vary over time, undermining reproducible secure builds. In a ledger-generation workflow, this can introduce unexpected parser/export behavior or vulnerable releases without code changes.
paddlepaddle>=2.6.0
PyMuPDF>=1.23.0
opencv-python>=4.8.0
openpyxl>=3.1.0
requests>=2.31.0
openpyxl has known advisory history, and without an exact version it cannot be confirmed whether the deployed build is safe. While the risk is somewhat limited in a ledger-export role, spreadsheet/XML parsing issues can still matter if the tool imports or manipulates untrusted workbook content.
Using requests>=2.31.0 leaves the HTTP library version open-ended, making builds non-deterministic and complicating assurance around network behavior and known CVEs. In an allegedly offline financial-processing skill, that uncertainty is more concerning than in a normal networked application.
PyMuPDF>=1.23.0
opencv-python>=4.8.0
openpyxl>=3.1.0
requests>=2.31.0
No suspicious patterns detected.