Back to skill

Security audit

vietnam-invoice

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent invoice-verification purpose, but it handles sensitive invoice data with insecure network and logging practices that should be reviewed before use.

Install only if users are comfortable sending invoice content and related business data to the named external services. Before production use, require TLS verification, redact logs, pin dependencies, add explicit consent/privacy guidance, and treat results as advisory until the authenticity logic validates material invoice fields against the official record.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/verify_vl.py:191
Finding

TLS Certificate Validation Disabled for Tax-Service Requests

Content
View full analysis
dict: resp = _request( requests.get, CAPTCHA_URL, retries=REQUEST_RETRIES, verify=False, timeout=15, ) return resp.json() ``` ```python resp = _request( requests.get, QUERY_URL, retries=REQUEST_RETRIES, params=params, verify=False, timeout=60, ) ``` ### Technical Analysis The script explicitly disables TLS certificate verification for requests to the Vietnamese tax service. It also globally suppresses the warning that would normally alert operators to this unsafe behavior. HTTPS encryption without certificate validation does not authenticate the remote server. An attacker able to intercept network traffic can present an arbitrary certificate, terminate the connection, and return attacker-controlled CAPTCHA or invoice-query responses. This behavior is unnecessary for the declared functionality and exceeds the minimum acceptable network trust model. A legitimate tax-service integration should authenticate the remote service using the operating system's trusted certificate store or a specifically configured trusted CA. ### Attack Path 1. A user runs the invoice-verification Skill over an attacker-controlled or compromised network. 2. The attacker intercepts traffic directed to the tax-service host. 3. The attacker presents an untrusted TLS certificate. 4. Because `verify=False` is set, the script accepts the certificate without warning. 5. The attacker returns a fabricated CAPTCHA response or invoice-query response. 6. The script parses the fabricated JSON and may report an altered invoice-authenticity result. ### Impact Assessment ...[truncated 624 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/verify_vl.py:194
Finding

Untrusted Remote SVG Rendered as Active Browser Content

Content
View full analysis
bytes: with sync_playwright() as p: browser = p.chromium.launch(channel="msedge", headless=True) page = browser.new_page(viewport={"width": 250, "height": 60}) page.set_content( f'{svg}' ) el = page.query_selector("svg") png = el.screenshot() if el else page.screenshot(full_page=True) browser.close() return png ``` ### Technical Analysis The CAPTCHA SVG returned by a remote service is interpolated directly into an HTML document and rendered by a full browser. SVG is active content and can contain scripts, event handlers, links, embedded documents, and external-resource references. No sanitization, Content Security Policy, request interception, or external-resource blocking is applied. The risk is amplified by the disabled certificate verification on the CAPTCHA request, which enables a network attacker to substitute malicious SVG content. Although browser isolation reduces some local impact, rendering attacker-controlled active content unnecessarily expands the attack surface. A browser exploit could affect the process running the Skill, while ordinary SVG features may trigger unsolicited outbound requests without requiring a browser vulnerability. ### Attack Path 1. An attacker controls or intercepts the CAPTCHA response. 2. The attacker replaces the expected SVG with SVG containing scripts, event handlers, or references to attacker-controlled resources. 3. `_svg_to_png` inserts the SVG directly into an HTML document. 4. Playwright launches Microsoft Edge and renders the attacker-controlled content. 5. Embedded active content executes in the browser context or initiat ...[truncated 758 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/verify_vl.py:284
Finding

Sensitive Invoice and CAPTCHA Data Written to Standard Error

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/verify_vl.py:240
Finding

Invoice Authenticity Decision Is Not Bound to Material Document Fields

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/requirements.txt:1
Finding

Dependencies Are Not Reproducibly Pinned or Integrity-Verified

Content
View full analysis
=2.28.0 openai>=1.0.0 playwright>=1.50.0 PyMuPDF>=1.24.0 Pillow>=10.0.0 ``` The documented installation command is: ```bash pip install -r "${CLAUDE_SKILL_DIR}/scripts/requirements.txt" playwright install msedge ``` ### Technical Analysis Every Python dependency uses an open-ended minimum version and no package hashes. A future installation can therefore resolve to versions that were not reviewed during this audit. This does not prove that any currently named package is malicious. However, it creates a supply-chain weakness because package behavior can change after review, installations are not reproducible, and integrity is delegated entirely to the package index and current dependency resolver. The separate browser installation is also not tied to a reviewed browser artifact in the project manifest. ### Attack Path 1. A future package version or transitive dependency becomes compromised, malicious, or unexpectedly incompatible. 2. A user follows the documented installation command. 3. `pip` resolves an unreviewed version satisfying the broad `>=` constraint. 4. Package installation or import executes attacker-controlled or vulnerable code. 5. The code runs with the privileges of the user or service account installing or invoking the Skill. ### Impact Assessment A compromised dependency may execute arbitrary code with the privileges of the installing or runtime account. Depending on that account's permissions, impact could include: - Reading invoice files and environment variables. - Accessing `VL_API_KEY`, `CJY_USER`, and `CJY_PASS`. - Modifying files accessible to the user. - Sending data over the network. - Altering invoice-verification results. No evidence in the audited files establishes an active dependency-compromise event; this finding con ...[truncated 85 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (17)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script sends invoice images and extracted invoice fields to third-party services, including the VL model provider and a CAPTCHA-solving provider, without any explicit user-facing consent, warning, or data-minimization guard. In this skill context, invoices can contain sensitive financial, tax, and business information, so silent transmission to external services increases privacy, compliance, and data-handling risk.

Content

No source excerpt is available for this finding.

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
99% confidence
Finding

Using requests with verify=False disables TLS certificate validation, allowing man-in-the-middle interception or tampering with responses from the tax API CAPTCHA endpoint. In this skill, that could let an attacker manipulate verification flow, observe invoice-related traffic, or feed malicious content into downstream processing while the code also suppresses HTTPS warnings globally.

Content

Scanner excerpt · scripts/verify_vl.py (reported line 191)May include surrounding context.

python
# ==================== 验证码 & 验真 ====================

def _get_captcha() -> dict:
    resp = _request(requests.get, CAPTCHA_URL, retries=REQUEST_RETRIES, verify=False, timeout=15)
    return resp.json()

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
99% confidence
Finding

Disabling TLS verification on the invoice query request exposes the core authenticity-check transaction to man-in-the-middle attacks. An attacker on the network path could read sensitive invoice identifiers, alter query parameters or responses, and cause false authenticity results, which is especially dangerous because this skill is specifically used to validate tax invoices.

Content

Scanner excerpt · scripts/verify_vl.py (reported line 296)May include surrounding context.

python
print(f"  请求参数: {json.dumps(params, ensure_ascii=False)}", file=sys.stderr)

        resp = _request(requests.get, QUERY_URL, retries=REQUEST_RETRIES,
                        params=params, verify=False, timeout=60)
        print(f"  响应状态: {resp.status_code}", file=sys.stderr)

        if not resp.text.strip():

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill instructs users to send invoice files and extracted invoice data to external third-party services for vision extraction and verification, but it does not clearly disclose that potentially sensitive financial documents and metadata will leave the local environment. This creates a real privacy and data-governance risk, especially if invoices contain personal data, tax identifiers, company financial details, or regulated business information.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The document is entirely written in Chinese while describing Vietnamese invoice fields, with no indication that alternative languages are supported or that the language choice is optional. This can violate a language/locale policy when users are not given a choice or the locale restriction is not explicitly justified.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency specification uses a lower-bound only constraint for requests, which makes builds non-reproducible and can pull in different versions over time. This increases supply-chain risk and leaves it unclear whether a deployed environment includes a vulnerable or incompatible release.

Content

Scanner excerpt · scripts/requirements.txt (reported line 1)May include surrounding context.

text
requests>=2.28.0
openai>=1.0.0
playwright>=1.50.0
PyMuPDF>=1.24.0

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

Requests has multiple published advisories, but the manifest does not pin a version, so there is no way to verify whether the installed release is affected or fixed. In a skill that likely performs network requests to a tax API, this uncertainty directly increases the chance of deploying a vulnerable HTTP client.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The openai package is not pinned to a specific version, so installations may resolve to different releases in different environments. This weakens reproducibility and can introduce unreviewed security or breaking changes through dependency updates.

Content

Scanner excerpt · scripts/requirements.txt (reported line 2)May include surrounding context.

text
requests>=2.28.0
openai>=1.0.0
playwright>=1.50.0
PyMuPDF>=1.24.0
Pillow>=10.0.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

Using playwright>=1.50.0 allows any newer version to be installed, which reduces build determinism and may introduce unexpected behavior or newly introduced vulnerabilities. For an automation-capable library, unreviewed version drift can materially change runtime security characteristics.

Content

Scanner excerpt · scripts/requirements.txt (reported line 3)May include surrounding context.

text
requests>=2.28.0
openai>=1.0.0
playwright>=1.50.0
PyMuPDF>=1.24.0
Pillow>=10.0.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

PyMuPDF is specified with only a minimum version, so the actual installed version is uncontrolled and may vary by environment. Because this library processes documents, version ambiguity increases the risk of inheriting parser-related vulnerabilities or unstable behavior.

Content

Scanner excerpt · scripts/requirements.txt (reported line 4)May include surrounding context.

text
requests>=2.28.0
openai>=1.0.0
playwright>=1.50.0
PyMuPDF>=1.24.0
Pillow>=10.0.0

Unverifiable Dependency: PyMuPDF has 2 known advisory(ies) (CVE-2026-3029 (PyMuPDF has a path traversal in _main_.py); CVE-2026-3029 (PyMuPDF has a path traversal in _main_.py)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
94% confidence
Finding

PyMuPDF has known advisories, and because the requirement is unpinned, the security posture of the installed package cannot be determined from this file. This is more relevant here because the skill processes invoice PDFs, making a document-parsing library part of the attack surface for untrusted user-supplied files.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

Pillow is also unpinned, meaning installations can silently adopt different image-processing versions over time. Since image parsers are frequent targets for memory corruption and resource exhaustion issues, this creates avoidable supply-chain and patch-verification risk.

Content

Scanner excerpt · scripts/requirements.txt (reported line 5)May include surrounding context.

text
openai>=1.0.0
playwright>=1.50.0
PyMuPDF>=1.24.0
Pillow>=10.0.0

Unverifiable Dependency: Pillow has 16 known advisory(ies) (CVE-2016-2533 (Pillow buffer overflow in ImagingPcdDecode); CVE-2023-50447 (Arbitrary Code Execution in Pillow); CVE-2021-27922 (Pillow Uncontrolled Resource Consumption) +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
96% confidence
Finding

Pillow has numerous historical advisories, and without version pinning it is impossible to confirm whether deployments use a patched release. This is more dangerous in this skill because invoice verification may involve processing user-provided images, so vulnerable image parsing could expose the system to code execution, denial of service, or memory corruption flaws.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

All user-facing documentation and CLI guidance in the file are written in Chinese, and the skill does not offer a language/locale choice or explain why Chinese is mandatory. Under the stated policy, forcing a specific language without user opt-in can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/verify_vl.py (reported line 418)May include surrounding context.

python
if args.direct:
        # 直接验真模式
        for key in ("nbmst", "khhdon", "shdon", "khmshdon", "hdon"):
            if not getattr(args, key):
                _error_exit(f"直接验真模式需要 --{key} 参数")
        _check_env(direct_mode=True)
        result = verify_direct(

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill asks users to configure multiple service credentials via environment variables but does not warn about proper secret handling, storage, or leakage risks. While environment variables are common, omitting guidance increases the chance that users will expose credentials in shell history, logs, screenshots, shared profiles, or support transcripts.

Content

No source excerpt is available for this finding.