Back to skill

Security audit

WiseOCR

Security checks for vulnerabilities and agentic risk

Overview

WiseOCR is a disclosed cloud OCR tool, but it needs Review because unsafe output-name handling can write outside the intended folder and the README encourages persistent plaintext API-key storage.

Install only if you are comfortable sending selected documents to WiseDiag's cloud service. Do not use it for confidential, financial, identity, credential, minor-related, or regulated documents. Prefer setting WISEDIAG_API_KEY only for the current session or through a secret manager, and avoid passing untrusted values to --name or --output until output path validation is fixed.

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/wiseocr.py:169
Finding

Unrestricted Output Name Allows Directory Traversal and File Overwrite

Content
View full analysis
None: """Save OcrResult to a markdown file.""" markdown = data.get("markdown", "") total_pages = data.get("total_pages", 1) elapsed = data.get("elapsed_seconds", 0) usage = data.get("usage") or {} print(f"[*] Total pages: {total_pages}") print(f"[*] Processing time: {elapsed:.1f}s") if usage: print(f"[*] Usage: prompt_tokens={usage.get('prompt_tokens')}, " f"completion_tokens={usage.get('completion_tokens')}, " f"ocr_pic_size={usage.get('ocr_pic_size')}, " f"total_tokens={usage.get('total_tokens')}") out_path = output_dir / f"{stem}.md" out_path.write_text(markdown, encoding="utf-8") print(f"[+] Markdown saved: {out_path}") ``` The value passed as `stem` originates from the command-line `--name` argument without validation: ```python stem = name if name else p.stem _save_result(resp.json(), out_dir, stem) ``` ```python parser.add_argument( "-n", "--name", help="Output filename stem (recommended when input file is renamed/copied)" ) ``` ### Technical Analysis The `--name` argument is described as a filename stem, but the implementation accepts path separators, `..` traversal components, and absolute paths. When a relative value such as `../../notes` is supplied, joining it with `output_dir` does not constrain the resulting path to that directory. If an absolute path is supplied, `pathlib` discards the preceding output directory entirely. The subsequent `Path.write_text()` call creates or truncates the resolved destination. The implementation also does not reject ...[truncated 1762 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Open-Ended and Unhashed Dependency Constraints Create Supply-Chain Risk

Content
View full analysis
=2.28.0 pypdf>=3.0.0 ``` The documented installation command consumes these open-ended constraints directly: ```bash pip install -r requirements.txt ``` ### Technical Analysis Both dependencies use minimum-version constraints with no upper bound, exact version pin, lock file, or package hash. Consequently, installations performed at different times can resolve to different package versions, including future releases that were not present during this audit. Python package installation can execute package build logic, and imported dependencies run with the same permissions as the Skill process. An unreviewed, compromised, or incompatible future release could therefore affect confidentiality, integrity, or availability. No typosquatted package name, untrusted package index, malicious dependency, or currently compromised release was identified in the audited files. The finding concerns insufficient dependency integrity and reproducibility controls rather than evidence that the listed packages are malicious. ### Attack Path 1. A user follows the documented installation command at a later date. 2. The Python package resolver selects versions newer than those reviewed when the Skill was published. 3. If a selected release is compromised or contains a relevant vulnerability, its installation or import runs within the user’s environment. 4. The affected package receives the permissions of the installing or executing process. 5. Malicious or vulnerable dependency behavior could then access documents handled by the Skill, the WiseDiag API key present in the environment, network resources, or files accessible to that process. This path depends on a future compromised or vulnerable dependency release; the audit found no evidence that the current package na ...[truncated 556 chars]
Remediation
View remediation
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
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (13)

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/wiseocr.py (reported line 118)May include surrounding context.

python
fh = open(file_path, "rb")
            multipart = [("file", (file_path.name, fh, _mime(file_path.name)))]

            resp = requests.post(
                endpoint,
                files=multipart,
                params=params,

Tainted flow: 'multipart' from open (line 116, file read) → requests.post (network output)

High
Category
Data Flow
Confidence
80% confidence
Finding

File contents flow to a network sink. This may indicate data exfiltration of sensitive files.

Content

Scanner excerpt · scripts/wiseocr.py (reported line 118)May include surrounding context.

python
fh = open(file_path, "rb")
            multipart = [("file", (file_path.name, fh, _mime(file_path.name)))]

            resp = requests.post(
                endpoint,
                files=multipart,
                params=params,

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest description says, "Upload a file and say Use WiseOCR to OCR this," which provides a trigger-style phrase but does not define when the skill should or should not activate. It lacks negative examples or scope constraints, so similar everyday OCR requests could ambiguously match the skill.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The README instructs users to persist the API key in shell startup files such as ~/.zshrc or ~/.bashrc. Storing long-lived secrets in broadly loaded plaintext dotfiles increases the chance of accidental disclosure through backups, screen sharing, support bundles, shell history-adjacent mistakes, or other local compromise; this is more concerning because the skill uploads user documents to a third-party cloud service and relies on that credential for access.

Content

Scanner excerpt · README.md (reported line 71)May include surrounding context.

Temporary (current terminal session)

export WISEDIAG_API_KEY=your_api_key_here

Permanent (add to ~/.zshrc or ~/.bashrc)

echo 'export WISEDIAG_API_KEY=your_api_key_here' >> ~/.zshrc source ~/.zshrc

text

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill performs sensitive actions—reading an API key from the environment, uploading user files to a remote cloud service, and writing OCR output to disk—yet does not declare an explicit tool scope such as permissions or allowed-tools. This creates a governance and transparency gap: an agent may invoke network, file-write, and env-access capabilities without clear user-visible restriction, which is especially risky because the skill handles potentially sensitive documents.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script transmits the full contents of user-supplied PDFs/images to a third-party cloud OCR API, but it does not provide a clear runtime warning or consent step about external data transfer. In a skill context, users may assume local OCR and unintentionally upload sensitive documents, increasing confidentiality and compliance risk.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

Line L064 says to "NEVER call any API or HTTP endpoint directly," but the manifest and rest of the document explicitly describe this skill as uploading files to WiseDiag's cloud API for OCR. This is an intent/documentation contradiction rather than a security capability mismatch, because network/API use is central to the skill's purpose.

Content

No source excerpt is available for this finding.

Scope Creep

Low
Category
Excessive Agency
Confidence
70% confidence
Finding

Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Content

Scanner excerpt · README.md (reported line 122)May include surrounding context.

md
3. Processing results are returned to you
4. Files are not permanently stored on WiseDiag servers

### ⚠️ Do NOT upload documents containing personal sensitive information, including but not limited to:
- **Identity information**: ID card numbers, passport numbers, driver's license numbers
- **Financial information**: Bank account/card numbers, credit card numbers, tax IDs, financial statements
- **Biometric data**: Fingerprints, facial images, iris scans, voiceprints

Scope Creep

Low
Category
Excessive Agency
Confidence
70% confidence
Finding

Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Content

Scanner excerpt · SKILL.md (reported line 110)May include surrounding context.

md
3. Processing results are returned to you
4. Files are not permanently stored on WiseDiag servers

### ⚠️ Do NOT upload documents containing personal sensitive information, including but not limited to:
- **Identity information**: ID card numbers, passport numbers, driver's license numbers
- **Financial information**: Bank account/card numbers, credit card numbers, tax IDs, financial statements
- **Biometric data**: Fingerprints, facial images, iris scans, voiceprints

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency specification uses a lower-bound only constraint for requests, which makes builds non-reproducible and allows installation of unexpected future versions or resolver-selected versions with known flaws. In a skill that performs networked OCR via a cloud API, the HTTP client library is security-relevant, so failing to pin versions increases supply-chain and patch-verification risk.

Content

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

text
requests>=2.28.0
pypdf>=3.0.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
88% confidence
Finding

The manifest does not pin requests, so there is no way to verify whether deployment will use a version affected by one of the known advisories. Since requests is likely used to communicate with the WiseDiag cloud API, advisory exposure could affect transport security, credential handling, or request behavior depending on the resolved version.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency specification for pypdf is unpinned, so installations may resolve to different versions over time, including releases with denial-of-service or parser-related defects. Because this skill processes attacker-controlled PDFs/images for OCR, a vulnerable PDF-parsing library is more dangerous here than in many contexts, particularly for resource exhaustion or malformed-file handling issues.

Content

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

text
requests>=2.28.0
pypdf>=3.0.0

Unverifiable Dependency: pypdf has 16 known advisory(ies) (CVE-2026-84310 (pypdf: Possible long runtimes/large memory usage when retrieving outlines); CVE-2026-48156 (pypdf: Possible long runtimes for zero-only width values in cross-reference stre); CVE-2026-24688 (pypdf has possible Infinite Loop when processing outlines/bookmarks) +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 pypdf, leaving uncertain whether the installed version is affected by known parser and resource-exhaustion advisories. Given that this skill handles untrusted PDFs uploaded for OCR, an affected pypdf version could enable denial of service through malformed documents, making the context increase the risk.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.