Back to skill

Security audit

Ocr Benchmark

Security checks for vulnerabilities and agentic risk

Overview

This OCR benchmarking skill is mostly coherent, but it can upload user-selected images and an optional OCR token to cloud or arbitrary configured endpoints without strong disclosure or endpoint validation.

Review before installing if you may process sensitive documents, product images, personal data, or regulated content. Use only approved cloud providers and a trusted HTTPS PaddleOCR endpoint, avoid setting PADDLEOCR_TOKEN for untrusted destinations, and consider installing in an isolated virtual environment with pinned dependencies.

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

Warning
Location
scripts/run_benchmark.py:183
Finding
Unrestricted PaddleOCR Endpoint Can Expose Image Data and Authentication Tokens<![CDATA[ ## Vulnerability Details **File Location**: `scripts/run_benchmark.py:183-201` **Vulnerability Type**: Arbitrary external endpoint and insecure transport handling **Risk Level**: Medium ### Vulnerable Code ```python def ocr_paddleocr(image_path, model_id=None): import requests endpoint = os.environ.get('PADDLEOCR_ENDPOINT', '') if not endpoint: raise RuntimeError('PADDLEOCR_ENDPOINT not set — PaddleOCR is optional, set env var to enable') token = os.environ.get('PADDLEOCR_TOKEN', '') with open(image_path, 'rb') as f: img_b64 = base64.b64encode(f.read()).decode() t0 = time.time() resp = requests.post( endpoint, json={'image': img_b64}, headers={'Authorization': f'token {token}'} if token else {}, timeout=30, ) latency = round(time.time() - t0, 2) resp.raise_for_status() ``` ### Technical Analysis The PaddleOCR endpoint is read directly from the `PADDLEOCR_ENDPOINT` environment variable and passed to `requests.post` without validating its scheme, hostname, port, or trust boundary. The code therefore permits arbitrary destinations, including untrusted external servers, internal network services, and plaintext `http://` endpoints. The complete selected image is Base64-encoded and placed in the request body. Base64 is a transport encoding and does not provide encryption or confidentiality. If `PADDLEOCR_TOKEN` is configured, it is also sent in the `Authorization` header. When a plaintext HTTP endpoint is used, network observers may recover both the image and token. Sending image contents to a remote OCR provider is consistent with the Skill's declared functionality and is documented in `SKILL.md`; therefore, the encoding is not itself evidence of covert exfiltration. The vulnerability is that the implementation does not enforce secure transport or constrain the destination. This exceeds a safe least-privilege design because a configuration change can redirect ...[truncated 1596 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse the endpoint with `urllib.parse.urlparse` before making the request. 2. Require the `https` scheme and reject plaintext HTTP, embedded URL credentials, fragments, and unsupported schemes. 3. Maintain an explicit allowlist of approved PaddleOCR hostnames where deployment requirements permit it. 4. Resolve the hostname and reject loopback, link-local, private, multicast, and reserved IP ranges unless access to a specifically approved internal service is required. 5. Require explicit user confirmation or a dedicated opt-in flag before transmitting an image to an external endpoint. 6. Clearly warn users that image contents leave the local system and that Base64 is not encryption. 7. Never attach `PADDLEOCR_TOKEN` unless the destination has passed scheme and hostname validation. 8. Consider certificate pinning or private certificate-authority validation for controlled enterprise endpoints. 9. Use a narrowly scoped, revocable OCR token and rotate it immediately if disclosure is suspected. 10. Document the approved endpoint and data-retention policy so users can make an informed decision before submitting sensitive images. ]]>

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding
Open-Ended Dependency Constraints Prevent Reproducible and Integrity-Verified Installation<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1-4` **Vulnerability Type**: Unpinned third-party dependencies and missing artifact integrity verification **Risk Level**: Low ### Vulnerable Code ```text boto3>=1.34.0 google-genai>=1.0.0 python-pptx>=0.6.21 requests>=2.31.0 ``` The documented installation command in `SKILL.md` is: ```bash pip install -r requirements.txt ``` ### Technical Analysis Every dependency uses an open-ended minimum version. Consequently, installation can resolve to any future release satisfying the lower bound rather than to the versions tested during development or reviewed during this audit. The project also provides no lock file or package hashes. Pip therefore cannot verify that the exact expected distributions were installed beyond the normal protections offered by the configured package index and TLS. This creates non-reproducible builds and increases exposure to compromised future releases, account takeover of an upstream package, or unexpected compatibility and security regressions. The package names observed in the project are established packages, and the reviewed source contains no evidence that the author intentionally selected malicious or typosquatted dependencies. This finding concerns insufficient supply-chain hardening rather than a confirmed malicious package. ### Attack Path 1. A user follows the documented command `pip install -r requirements.txt`. 2. Pip queries the configured package index and selects the newest releases that satisfy the open-ended lower bounds. 3. A future dependency release is compromised, malicious, or otherwise unsafe, or the user's package-index configuration resolves an unintended artifact. 4. Pip downloads and installs that artifact because neither an exact version nor an expected cryptographic hash is enforced. 5. The dependency's installation or runtime behavior executes within the user's Python environment and receives the privileges of the user running t ...[truncated 614 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Generate a lock file containing exact, tested dependency versions and all transitive dependencies. 2. Record cryptographic hashes for accepted distributions and install with `pip install --require-hashes`. 3. Prefer exact constraints such as `package==tested.version` in release artifacts rather than unrestricted `>=` constraints. 4. Build and test dependency updates in an isolated environment before changing the lock file. 5. Use a trusted package index and explicitly control index configuration in automated build environments. 6. Run dependency vulnerability and provenance checks in continuous integration. 7. Install and execute the Skill in a dedicated virtual environment under a non-privileged user. 8. Review dependency updates regularly so exact pinning does not leave known vulnerabilities unpatched. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (10)

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

Critical
Category
Data Flow
Content
img_b64 = base64.b64encode(f.read()).decode()

    t0 = time.time()
    resp = requests.post(
        endpoint,
        json={'image': img_b64},
        headers={'Authorization': f'token {token}'} if token else {},
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill documents capabilities that involve reading local files, writing results, accessing environment variables, and making outbound network requests to Bedrock, Google AI Studio, and an optional external PaddleOCR endpoint, but it does not declare any explicit tool scope or permissions. This creates a trust and containment gap: a user or platform may not have a clear, enforceable statement of what the skill is allowed to access, increasing the chance of over-broad file, secret, or network exposure.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The documentation explains setup and model usage but does not clearly warn that supplied images and extracted OCR content are transmitted to third-party services, including cloud model providers and a user-configured external PaddleOCR endpoint. Users may unknowingly send sensitive documents, packaging, or personal data off-device, creating privacy, confidentiality, and compliance risk in contexts where images contain regulated or proprietary information.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The script sends image data to Bedrock, Gemini, and optionally PaddleOCR, but it does not provide an explicit runtime warning or consent gate before transmitting potentially sensitive images off-host. In an OCR benchmarking context, users may process packaging, documents, or other images that contain confidential or regulated data, so silent external transmission creates a real privacy and compliance risk.

External Transmission

Medium
Category
Data Exfiltration
Content
img_b64 = base64.b64encode(f.read()).decode()

    t0 = time.time()
    resp = requests.post(
        endpoint,
        json={'image': img_b64},
        headers={'Authorization': f'token {token}'} if token else {},
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Unpinned Dependencies

Low
Category
Supply Chain
Content
boto3>=1.34.0
google-genai>=1.0.0
python-pptx>=0.6.21
requests>=2.31.0
Confidence
96% confidence
Finding
The dependency is specified with only a lower bound, which allows installation of any newer version, including versions with breaking changes or newly introduced security issues. While this file alone does not prove exploitation, unpinned dependencies reduce build reproducibility and increase supply-chain risk over time.

Unpinned Dependencies

Low
Category
Supply Chain
Content
boto3>=1.34.0
google-genai>=1.0.0
python-pptx>=0.6.21
requests>=2.31.0
Confidence
96% confidence
Finding
Using an unpinned version for google-genai means the environment may resolve to different package releases across installs. That creates a supply-chain and stability risk because a future release could introduce a vulnerable dependency, insecure behavior, or compatibility issue without any code change in the skill.

Unpinned Dependencies

Low
Category
Supply Chain
Content
boto3>=1.34.0
google-genai>=1.0.0
python-pptx>=0.6.21
requests>=2.31.0
Confidence
95% confidence
Finding
The python-pptx package is not pinned to a specific version, so installations are not reproducible and may silently pick up risky or incompatible releases. In a report-generation skill, this is mainly a supply-chain hygiene issue rather than an immediately exploitable flaw, but it is still a valid weakness.

Unpinned Dependencies

Low
Category
Supply Chain
Content
boto3>=1.34.0
google-genai>=1.0.0
python-pptx>=0.6.21
requests>=2.31.0
Confidence
99% confidence
Finding
Requests is declared with only a minimum version, so dependency resolution may select an affected release or a future release with undiscovered issues. Because this skill likely performs network operations against external APIs, an unsafe or vulnerable HTTP client can have more practical impact than a purely local library issue.

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
The manifest does not pin requests, and that package has multiple known advisories across historical versions, so it is impossible to verify from this file whether the installed version is safe. In a tool that communicates with cloud OCR providers over HTTP, uncertainty around the HTTP client version increases the chance of credential leakage, TLS/verification issues, or other request-handling weaknesses if an affected release is resolved.

Static analysis

No suspicious patterns detected.