Back to skill

Security audit

WiseDiag MedOCR

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed cloud OCR skill, but it has an output-name bug that can write Markdown outside its stated folder and its documentation gives weak API-key storage guidance.

Review before installing. Only use this skill for files you are comfortable sending to WiseDiag, avoid sensitive or confidential documents, do not store the API key directly in shell startup files, and avoid using --name values containing slashes, absolute paths, or '..' until the output filename handling 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 (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/wiseocr.py:179
Finding

Unvalidated Output Name Permits Path Traversal and Arbitrary Markdown 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` is selected without validation: ```python stem = name if name else p.stem _save_result(resp.json(), out_dir, stem) ``` ### Technical Analysis The `--name` argument is treated as a filename stem, but the implementation does not reject absolute paths, path separators, or parent-directory components such as `../`. When `stem` contains an absolute path, `pathlib` discards the preceding `output_dir`. When it contains parent-directory components, path resolution can escape the intended output directory. The subsequent `write_text()` call overwrites an existing file without confirmation. Although the `.md` suffix limits the destination to a Markdown filename, the flaw still permits modification of arbitrary writable Markdown files outside `~/.openclaw/workspace/WiseOCR`. This is particularly relevant in an Agent environment where Markdown files may contain workspace instructions ...[truncated 1520 chars]
Remediation
View remediation
Path: if not stem or not re.fullmatch(r"[A-Za-z0-9 _.-]+", stem): raise ValueError("Invalid output filename") if stem in {".", ".."} or Path(stem).is_absolute(): raise ValueError("Invalid output filename") base = output_dir.resolve() destination = (base / f"{stem}.md").resolve() if destination.parent != base: raise ValueError("Output path escapes the configured directory") if destination.exists(): raise FileExistsError(f"Refusing to overwrite: {destination}") return destination ``` Use the validated path before writing and report validation failures without exposing credentials or document content. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
README.md:66
Finding

Documentation Encourages Persistent Plaintext API-Key Storage

Content
View full analysis
> ~/.zshrc source ~/.zshrc ``` ### Technical Analysis The documentation recommends placing the WiseDiag API key directly in a shell startup file. Shell configuration files are plaintext, long-lived, and commonly included in workstation backups, diagnostic archives, home-directory migrations, and accidental dotfile repository commits. The script itself correctly retrieves the credential from an environment variable and sends it only as a bearer token to the hard-coded WiseDiag HTTPS endpoint. The weakness is the recommended method for persistently provisioning that environment variable, not hidden credential exfiltration in the implementation. ### Attack Path 1. A user follows the documented permanent setup command. 2. The API key is stored in plaintext in `~/.zshrc`. 3. The shell profile is read by another local process running with the user's permissions, copied into a support bundle, synchronized to a dotfile repository, or exposed through a backup. 4. An unauthorized party extracts the bearer credential. 5. The party uses the key to make requests against the WiseDiag service until it is revoked or expires. ### Impact Assessment Exposure grants the attacker the service permissions associated with the compromised WiseDiag API key. This could allow unauthorized OCR requests, consumption of account quotas, service charges, and access to account-level API functionality supported by that credential. This issue does not itself grant operating-system privilege escalation. Reading the profile generally requires access equivalent to the affected user or disclosure through another channel. ]]>
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Open-Ended and Unhashed Python Dependencies Permit Unreviewed Supply-Chain Changes

Content
View full analysis
=2.28.0 pypdf>=3.0.0 ``` The documented installation command resolves these open-ended constraints: ```bash pip install -r requirements.txt ``` ### Technical Analysis The lower-bound-only constraints allow the package resolver to install any future version of `requests` or `pypdf`. No lock file or cryptographic hash constrains the artifacts to versions reviewed with this Skill. There is no evidence that the named packages are typosquatted or currently malicious. The risk is that future installations are not reproducible and may retrieve code that was never included in this audit. A compromised upstream release, compromised package-publishing account, or malicious transitive dependency could execute with the privileges of the user performing installation or running the Skill. ### Attack Path 1. A user installs the Skill at a later date using `pip install -r requirements.txt`. 2. The resolver selects newer direct or transitive dependency versions satisfying the broad constraints. 3. An upstream package release or dependency has been compromised, or introduces a security regression. 4. Package installation hooks, imported module code, or vulnerable runtime behavior executes on the user's system. 5. The compromised dependency gains access to the Skill process, including the selected OCR document and the `WISEDIAG_API_KEY` environment variable. ### Impact Assessment A malicious dependency executes with the privileges of the user installing or invoking the Skill. Depending on the payload, this could expose: - The WiseDiag API key. - Documents selected for OCR. - Files readable or writable by the current user. - Network access available to the Python process. - Workspace state and generated OCR output. No direct privilege escalation is d ...[truncated 168 chars]
Remediation
View remediation
\ --hash=sha256: pypdf== \ --hash=sha256: ``` Install it with: ```bash python3 -m pip install --require-hashes -r requirements.txt ``` Transitive dependencies must also be pinned and hashed for `--require-hashes` to provide complete integrity enforcement. ]]>
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
95% confidence
Finding

The description says users can invoke the skill by saying "Use WiseOCR to OCR this," but it does not clearly define whether that exact phrase is required, what variants are accepted, or what contexts should not trigger the skill. Because "OCR this" is a common, natural request around files and images, the trigger guidance is underspecified and could lead to unintended activation.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
95% confidence
Finding

The README instructs users to persist the API key by appending it directly to ~/.zshrc or ~/.bashrc, which stores a long-lived secret in plaintext in a shell startup file. If that file is exposed through backups, misconfigured permissions, shoulder-surfing, shell history copy/paste, or later disclosure, the WiseDiag account can be abused for unauthorized API use.

Content

Scanner excerpt · README.md (reported line 72)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
94% confidence
Finding

The skill declares capabilities that involve environment access, file writing, and network upload to a third-party cloud API, but it does not explicitly declare any tool scope or permission boundaries. This creates a transparency and least-privilege problem: an agent or user may invoke a skill that can exfiltrate document contents remotely and write outputs locally without clear upfront execution constraints.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The invocation guidance, 'Upload a file and say Use WiseOCR to OCR this,' is broad and could trigger on arbitrary uploaded documents without meaningful constraints or a mandatory consent checkpoint. In the context of a cloud OCR skill, broad triggering increases the risk of accidental transmission of sensitive files to a remote service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill uploads local user-provided documents and images to a remote cloud OCR API, but the runtime code does not present an explicit warning or confirmation about third-party transmission, privacy, or potential handling of sensitive content. In an agent context, users may reasonably assume local processing unless clearly informed, making accidental disclosure of confidential documents more likely.

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 123)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
- **Medical & health information**: Medical records, diagnoses, prescriptions, health insurance information

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 111)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
- **Medical & health information**: Medical records, diagnoses, prescriptions, health insurance information

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency is specified with a minimum version only, so builds may resolve to different releases over time. This weakens supply-chain control and makes it impossible to verify whether a deployed version includes known security fixes or introduces new vulnerable behavior.

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 references requests without an exact version, while the package has multiple known advisories across releases. Because the actual installed version is unverifiable from this file, the skill may resolve to a vulnerable version depending on install time or environment, creating avoidable supply-chain exposure.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency is unpinned, which means installations are not reproducible and may silently pull in different versions in different environments. That increases supply-chain risk and prevents auditors from determining whether the selected version is affected by known vulnerabilities.

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

The skill processes attacker-controlled PDFs and images, and pypdf has had advisories involving excessive runtime, memory usage, and parsing issues. With no pinned version, deployments may install a release affected by denial-of-service-style parser flaws, which is more concerning in this OCR/PDF-processing context than in a non-file-processing skill.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.