Back to skill

Security audit

document-parser

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it claims, but it sends user-selected documents and optional API credentials to a remote parser over a default plaintext HTTP endpoint.

Install only if you are comfortable sending chosen PDFs, images, or Word documents to the configured parsing service. Do not use the default HTTP endpoint for sensitive documents or API keys; prefer a trusted HTTPS endpoint, understand who operates it and how data is retained, and use revocable credentials. Pin or lock dependencies before deploying in a controlled environment.

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

Error
Location
index.py:15
Finding
Documents and Bearer Credentials Are Transmitted Over Plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `index.py:15`, `index.py:50-94`, `index.py:112-124` **Vulnerability Type**: Plaintext transmission of sensitive information **Risk Level**: High ### Vulnerable Code ```python DEFAULT_BASE_URL = "http://47.111.146.164:8088" ``` ```python config = get_config() base_url = config["base_url"].rstrip("/") api_url = f"{base_url}{DEFAULT_API_PATH}" # API Key is optional if not config["api_key"]: print("[WARN] No API Key configured; attempting request directly...") if not Path(file_path).exists(): return {"error": f"File does not exist: {file_path}"} headers = {} if config["api_key"]: headers["Authorization"] = f"Bearer {config['api_key']}" try: with open(file_path, "rb") as f: files = {"file": (Path(file_path).name, f)} data: dict = { "layout_analysis_en": 1 if layout_analysis else 0, "table_reco_en": 1 if table_recognition else 0, "seal_reco_en": 1 if seal_recognition else 0, } if output_format and output_format != "json": data["md_image_format"] = "url" if page_range: data["page_range"] = page_range response = requests.post( api_url, headers=headers, files=files, data=data, timeout=120 ) ``` ```python def get_task_status(task_id): """Query task status""" config = get_config() if not config["api_key"]: return {"error": "API Key is not configured"} try: response = requests.get( f"{config['base_url']}/{task_id}", headers={"Authorization": f"Bearer {config['api_key']}"} ) return response.json() except Exception as e: return {"error": f"Status query failed: {str(e)}"} ``` ### Technical Analysis The default service endpoint uses unencrypted HTTP. The `parse_document` function sends the entire user-selected document as a multipart uplo ...[truncated 2301 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the default endpoint with an HTTPS URL backed by a valid certificate and stable domain name. 2. Reject plaintext endpoints by default: ```python from urllib.parse import urlparse parsed = urlparse(base_url) if parsed.scheme != "https": raise ValueError("DOCUMENT_PARSER_BASE_URL must use HTTPS") ``` 3. Keep TLS certificate verification enabled. Do not introduce `verify=False` or suppress certificate warnings. 4. If private deployments genuinely require HTTP, require an explicit insecure-mode opt-in and display a prominent warning. Bearer credentials should still never be sent over plaintext HTTP. 5. Clearly disclose before use that complete documents are uploaded to a third-party or operator-controlled service. 6. Consider requiring explicit user confirmation before uploading a document, especially when the default remote service is used. 7. Document the service operator, retention policy, supported data regions, access controls, and deletion process. 8. Use narrowly scoped, revocable, and short-lived API credentials where supported. 9. Add integration tests that fail if the default endpoint or configured production endpoint uses a non-HTTPS scheme. 10. Set a timeout on the status request and call `response.raise_for_status()` before processing its body. ]]>

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding
Dependencies Are Installed Without Exact Version or Integrity Pinning<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1-3` **Vulnerability Type**: Unbounded dependency resolution and missing package integrity verification **Risk Level**: Low ### Vulnerable Code ```text requests>=2.28.0 python-docx>=0.8.11 Pillow>=9.0.0 ``` The documented installation procedure executes: ```bash pip install -r requirements.txt ``` ### Technical Analysis All dependencies use minimum-version constraints without upper bounds or exact pins. Consequently, installations performed at different times may resolve to different, unreviewed package releases. No lockfile or cryptographic hashes are supplied to verify that installed artifacts match versions reviewed with the Skill. No evidence was found that the named dependencies are currently malicious. The confirmed weakness is that dependency selection and artifact integrity are not reproducible or constrained to reviewed releases. If a future release, package-index account, distribution artifact, or dependency in the transitive chain becomes compromised, a routine installation could execute attacker-controlled package installation or runtime code. ### Attack Path 1. A user or deployment system follows the documented installation command. 2. The package resolver queries the configured Python package index. 3. Because only minimum versions are specified, the resolver may select any newer compatible release available at installation time. 4. If a selected release or transitive dependency has been compromised, its installation or imported runtime code executes in the installation or Skill process context. 5. The malicious dependency consequently obtains the same file, environment, and network access available to that process. This path depends on a compromised or malicious dependency release; the audit found no evidence of such a release in the reviewed project itself. ### Impact Assessment A compromised dependency could execute with the privileges of the user or service inst ...[truncated 530 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin dependencies to versions that have been tested and reviewed: ```text requests==<reviewed-version> python-docx==<reviewed-version> Pillow==<reviewed-version> ``` 2. Generate a lockfile that includes the full transitive dependency graph. 3. Use cryptographic hashes and install with `pip --require-hashes` where practical. 4. Regenerate pins through a controlled update process rather than accepting arbitrary future releases. 5. Run automated vulnerability and provenance checks against both direct and transitive dependencies. 6. Obtain packages only from an approved package index over HTTPS. 7. Test dependency updates in an isolated environment before publishing a new Skill release. 8. Remove dependencies that are not used by the implementation. In the reviewed code, `python-docx` and `Pillow` are declared but not imported directly. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (17)

Tainted flow: 'api_url' from os.environ.get (line 55, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
if page_range:
                data["page_range"] = page_range
            
            response = requests.post(
                api_url,
                headers=headers,
                files=files,
Confidence
99% confidence
Finding
The skill uploads arbitrary local files to a remote endpoint whose base URL can be overridden via environment variables or config, and the default is plain HTTP. This enables silent exfiltration of document contents to an attacker-controlled or intercepted service, including sensitive files processed by the agent.

Tainted flow: 'config' from os.environ.get (line 21, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Content
return {"error": "未配置 API Key"}
    
    try:
        response = requests.get(
            f"{config['base_url']}/{task_id}",
            headers={"Authorization": f"Bearer {config['api_key']}"}
        )
Confidence
95% confidence
Finding
The request target is built from environment/config-controlled base_url and user-controlled task_id, then sent with the Bearer API key. This can direct authenticated requests to an arbitrary host, causing credential leakage and server-side request forgery behavior if the skill runs in a trusted environment.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The default behavior points document uploads to a raw IP address over HTTP, which is an insecure and opaque remote destination for potentially sensitive local files. In an agent skill context, this is especially dangerous because users may expect local parsing, but the skill actually transmits documents off-host without transport security.

Missing User Warnings

High
Confidence
98% confidence
Finding
The code sends document contents to a remote service without a strong, user-facing warning and does so over potentially insecure HTTP transport. This creates confidentiality and integrity risks for uploaded documents and is amplified by the skill context, where local file access may include highly sensitive content.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The README instructs users to configure a custom API endpoint and submit local documents for parsing, but it does not warn that document contents may be transmitted off-host to a remote service. Because this skill handles potentially sensitive PDFs, images, and Word files, users could unknowingly exfiltrate confidential data to an untrusted or insecure endpoint.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README describes document parsing features and shows configuration of a remote API endpoint, but it does not clearly warn that uploaded PDFs, images, or Word files may be transmitted to an external service for processing. Because these files can contain sensitive business or personal data, the lack of an explicit disclosure can cause users to unknowingly exfiltrate confidential content to a third-party server.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill explicitly configures a remote parsing endpoint and instructs users to submit local PDF, image, and Word files, but it does not warn that document contents will be transmitted to an external service. This creates a real confidentiality and privacy risk because users may unknowingly upload sensitive documents, and the endpoint uses plain HTTP, which further increases exposure in transit.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
Natural-language strings in the module description and user-facing CLI messages are presented only in Chinese, with no option for the user to choose another language. This creates a language policy issue because the skill implicitly enforces a locale instead of offering or documenting language selection.

Context-Inappropriate Capability

Medium
Confidence
79% confidence
Finding
The skill loads an API key from DOCUMENT_PARSER_API_KEY and merges settings from a local config.json file. For an unknown-purpose skill, accessing host environment secrets and local configuration is an additional capability that is not justified by any stated intent.

Natural-Language Policy Violations

Low
Confidence
82% confidence
Finding
整个技能说明均以中文编写,未声明这是面向特定中文用户群体的区域性技能,也未提供其他语言选项。按照语言/区域策略,这可能构成默认强制特定语言而缺少用户选择。

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The file presents all user-facing instructions in Chinese, effectively forcing a specific language for users without any opt-in or explanation. Under the policy, a language-specific constraint should either be optional for the user or explicitly documented and justified.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.28.0
python-docx>=0.8.11
Pillow>=9.0.0
Confidence
97% confidence
Finding
The dependency is specified with a lower-bound version only, which allows installation of any newer release and makes builds non-reproducible. This increases supply-chain risk because different environments may resolve to different versions, including versions with breaking changes or newly introduced vulnerabilities.

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
92% confidence
Finding
Requests has known advisories, but because the manifest does not pin a version, there is no reliable way to determine whether installations will use a fixed or vulnerable release. The danger comes from unverifiable dependency state and possible exposure to known flaws if an affected version is resolved.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.28.0
python-docx>=0.8.11
Pillow>=9.0.0
Confidence
97% confidence
Finding
Using an unpinned python-docx version permits arbitrary newer versions to be installed, preventing reproducible builds and making it hard to verify whether known vulnerable releases are excluded. This is a classic supply-chain hygiene issue rather than direct malicious behavior, but it can expose deployments to avoidable risk.

Unverifiable Dependency: python-docx has 2 known advisory(ies) (CVE-2016-5851 (Improper Restriction of XML External Entity Reference in python-docx); CVE-2016-5851 (python-docx before 0.8.6 allows context-dependent attackers to conduct XML Exter)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
90% confidence
Finding
python-docx has historical advisories, including XML-related issues, and the unpinned requirement means a vulnerable version could still be installed depending on resolver behavior and environment. This is especially relevant for document-processing components, which often handle untrusted files.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.28.0
python-docx>=0.8.11
Pillow>=9.0.0
Confidence
97% confidence
Finding
Pillow is also unpinned, so dependency resolution may pull different versions over time across systems. Because image-processing libraries frequently receive security fixes, leaving the version open-ended makes it harder to ensure a safe and tested release is consistently installed.

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
94% confidence
Finding
Pillow has multiple known security advisories, and leaving it unpinned makes it impossible to verify that only patched versions are installed. Given that image libraries often parse complex, attacker-controlled file formats, resolving to a vulnerable Pillow release could enable denial of service or worse in some environments.

Static analysis

Detected: suspicious.install_untrusted_source

Install source points to URL shortener or raw IP.

Warn
Code
suspicious.install_untrusted_source
Location
config.example.json:2