Back to skill

Security audit

Paddleocr Doc Parsing Radeon

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to be a real cloud document-parsing wrapper, but it can upload sensitive documents over unencrypted HTTP and fetch arbitrary URLs without enough guardrails.

Review before installing. Do not use this skill for confidential, regulated, financial, personal, or internal documents unless you control and trust the parsing endpoint. Configure only an HTTPS endpoint, avoid arbitrary --file-url inputs from untrusted users, and assume uploaded documents and parser responses may be visible to the endpoint operator and any network observer if HTTP is used.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/layout_caller.py:50
Finding

Server-Side Request Forgery Through Unrestricted Document URLs

Content
View full analysis
str: """Download a file from a URL and return its base64 encoding.""" import httpx from lib import _http_timeout_from_env, DEFAULT_TIMEOUT timeout = _http_timeout_from_env("PADDLEOCR_DOC_PARSING_TIMEOUT", float(DEFAULT_TIMEOUT)) with httpx.Client(timeout=timeout) as client: resp = client.get(url) resp.raise_for_status() return base64.b64encode(resp.content).decode("utf-8") ``` The caller passes the user-controlled URL directly to this function: ```python if args.file_url: file_data = _fetch_as_base64(args.file_url) else: file_data = _read_as_base64(args.file_path) ``` ### Technical Analysis The `--file-url` argument is accepted without validating the URL scheme, hostname, destination port, or resolved IP address. The application then performs an HTTP request from the network context of the machine running the skill. An attacker can provide URLs targeting resources that are not directly accessible from the attacker's own network, including: - Loopback services such as `127.0.0.1` - Private network addresses - Link-local services - Cloud instance metadata endpoints - Internal administration or monitoring services The response is loaded into memory, Base64-encoded, and passed to `parse_document()`. When a supported-looking path or an explicit `--file-type` is provided, the downloaded content is subsequently submitted to the configured OCR endpoint. ### Attack Path 1. An attacker persuades the Agent to parse a crafted URL, for example an internal service URL or a cloud metadata URL. 2. The URL is accepted through `--file-url`. 3. `_fetch_as_base64()` makes the request from the Agent host without checking whether the resolved address is private, loopback, link-local, or otherwise ...[truncated 857 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/lib.py:86
Finding

Sensitive Documents Can Be Uploaded Over Plaintext HTTP

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/layout_caller.py:50
Finding

Unbounded Remote Download Can Cause Memory Exhaustion

Content
View full analysis
str: """Download a file from a URL and return its base64 encoding.""" import httpx from lib import _http_timeout_from_env, DEFAULT_TIMEOUT timeout = _http_timeout_from_env("PADDLEOCR_DOC_PARSING_TIMEOUT", float(DEFAULT_TIMEOUT)) with httpx.Client(timeout=timeout) as client: resp = client.get(url) resp.raise_for_status() return base64.b64encode(resp.content).decode("utf-8") ``` ### Technical Analysis The remote response is accessed through `resp.content`, which materializes the complete body in memory. No maximum download size, streaming byte limit, or `Content-Length` validation is applied. The response is then Base64-encoded. Base64 increases the data size by approximately one third, and the conversion may temporarily retain multiple in-memory copies: - The downloaded byte body - The Base64-encoded byte sequence - The decoded Python string - The subsequent JSON request representation A malicious server can return a very large or indefinitely generated body. The request timeout limits elapsed time but does not provide a reliable memory limit. ### Attack Path 1. An attacker supplies a URL under their control through `--file-url`. 2. The server responds with a very large document or generated response body. 3. `httpx` buffers the entire response when `resp.content` is accessed. 4. The skill creates additional in-memory copies during Base64 and JSON conversion. 5. Available memory is exhausted, causing the skill or its host process to slow down, terminate, or be killed by the operating system. ### Impact Assessment Exploitation can cause denial of service for the skill process and potentially other workloads sharing the same host or container. The exact scope depends on operating-syst ...[truncated 184 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code is broadly related to document parsing, so the general domain matches. However, the description overstates what the supplied code itself does. The implementation is only an API client/wrapper around an externally provided /layout-parsing endpoint. It requires environment configuration for the endpoint, posts base64 file data, and returns the raw API result plus concatenated markdown text. It does not itself perform OCR, layout analysis, formula recognition, or structured extraction beyond relaying whatever the external service returns. Most notably, the description says 'No API key required' and frames this as a free cloud capability, but the code explicitly handles 403 authentication failures and depends on an externally configured service endpoint, which may not be openly accessible. Therefore the declared description is not fully accurate to the actual behavior of the code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This is a material description-behavior mismatch. The description advertises a document parsing/OCR capability with rich extraction features for PDFs and images, but the code shown only optimizes image files for size using Pillow. Its primary purpose is preprocessing/compression, not document understanding. While the script mentions PaddleOCR in help text and suggests a later processing step, that does not implement the declared parsing behavior here. This is more than a supporting detail because the entire supplied code chunk centers on a different function: file optimization.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

There is a clear material mismatch. The description promises an OCR/document-understanding system with structured extraction from PDFs/images, but the code only splits PDFs by specified page ranges and saves a new PDF. It does not call any OCR model, cloud service, AMD Radeon resource, or parsing pipeline, nor does it extract content in Markdown/JSON. The actual primary purpose is PDF page subsetting, which is unrelated to the declared skill purpose.

Content

No source excerpt is available for this finding.

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

The skill encourages users to submit local files or URLs to a remote cloud endpoint, but it does not prominently warn that document contents are transmitted to a third-party service. This can expose sensitive PDFs, invoices, financial reports, or other private documents without informed user consent, especially because the text emphasizes 'free' and 'no API key required' rather than data-handling risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The schema explicitly documents that OCR output is automatically written to a file in the system temporary directory and only printed by path to stderr unless the caller opts out with --stdout. Because this skill processes documents that may contain sensitive business, financial, or personal data, automatic temp-file persistence can expose extracted contents to other local users, backup/indexing processes, or leave recoverable artifacts after use.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The library sends base64-encoded document contents to a remote endpoint via client.post(api_url, json=params, headers=headers) but this file provides no user-facing disclosure, consent check, or data-classification guard before transmission. Because the skill handles potentially sensitive documents such as invoices, financial reports, and scanned records, silent exfiltration to a configured external service creates a real privacy and compliance risk even if the behavior is functionally intended.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.