Back to skill

Security audit

Finance OCR Pro

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent OCR tool, but its generated HTML reports can carry unsafe active content and undisclosed RizMoon branding, so it needs review before installation.

Install only if you trust the configured VLM endpoint and understand that document page images will be sent there. Avoid opening or sharing generated HTML reports from untrusted documents until the report generator sanitizes OCR Markdown and Mermaid output, and be aware reports include RizMoon branding and an external link. Prefer pinned dependencies, monitor background jobs, and clean ~/.semantic-ocr/jobs when results are no longer needed.

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)

other

Note
Location
scripts/md_to_html.py:1909
Finding

Forced Third-Party Branding and External Promotion in Generated Reports

Content
View full analysis
``` ```python
{logo_html}
``` ```python
© Extracted by RizMoon. contact@rizmoon.com.
``` ### Technical Analysis Every generated HTML report is automatically modified to include RizMoon branding, contact information, and a clickable link to `https://www.rizmoon.ai`. This content is unrelated to the technical requirements of OCR, document extraction, or format conversion. The declared skill instructions do not disclose that reports will contain third-party promotional material. Users are not offered a configuration option to disable or replace it. This creates a persistent and deterministic modification of the user’s requested output. The external link does not automatically transmit document content, but clicking it causes navigation to a third-party domain and may expose ordinary browser metadata such as the user’s IP address and user-agent string. ### Attack Path 1. A user submits a document for OCR and requests an HTML report. 2. The OCR and Markdown conversion stages process the document. 3. `_generate_html_document` inserts the hardcoded brand link, c ...[truncated 791 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/md_to_html.py:841
Finding

Unsanitized OCR Markdown Can Introduce Active Content into Generated HTML Reports

Content
View full analysis
str: md = raw_md or "" md = _normalize_indentation(md) md = _convert_ocr_figure_placeholders(md) md = _ensure_blank_lines_around_tables(md) md, mermaid_blocks = _protect_mermaid_blocks(md) protected, math_blocks = _protect_math_expressions(md) processor = markdown2.Markdown( extras=[ "fenced-code-blocks", "code-friendly", "cuddled-lists", "header-ids", "strike", "tables", "task_list", ] ) html_content = processor.convert(protected) html_content = _restore_math_expressions(html_content, math_blocks) html_content = _restore_mermaid_blocks(html_content, mermaid_blocks) html_content = _enhance_tables(html_content) html_content = _classify_numeric_cells(html_content) return html_content ``` The resulting HTML is then incorporated into the final report: ```python if md_path and md_path.exists(): raw_md = md_path.read_text(encoding="utf-8-sig", errors="replace") raw_md = re.sub(r"\nPage Number \d+:\n", "\n", raw_md, flags=re.IGNORECASE) rendered = _convert_markdown_to_html(raw_md) html_content = ( rendered if rendered.strip() else '
Empty extracted content
' ) ``` ### Technical Analysis The pipeline treats VLM-generated Markdown as trusted content. `markdown2` permits raw HTML unless the caller separately disables or sanitizes it. No HTML allowlist sanitizer, dangerous-URI filter, or equivalent output validation is applied after conversion. A malicious source document ...[truncated 2344 chars]
Remediation
View remediation
`, ``, `<object>`, `<embed>`, `<form>`, and `<base>` elements. - Attributes beginning with `on`. - `srcdoc`, `formaction`, and similar execution-capable attributes. - Dangerous URI schemes including `javascript:`, `vbscript:`, and unsafe `data:` values. 4. Disable raw HTML during Markdown conversion where possible. 5. Add a restrictive Content Security Policy. For example, disallow remote connections and objects, and avoid permitting arbitrary inline scripts. 6. Move trusted application JavaScript into a separately hashed or nonce-protected block rather than broadly allowing inline script execution. 7. Consider removing clickable links and remote image references from OCR output unless explicitly approved by the user. 8. Add security tests using payloads such as raw script elements, event-handler attributes, dangerous links, SVG payloads, and malformed HTML. 9. Treat responses from `BASE_URL` as untrusted even when the endpoint is expected to be reputable. ]]>

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unbounded Dependency Versions Create Non-Reproducible and Unsafe Installations

Content
View full analysis
=1.0 python-dotenv>=0.19 # PDF / image processing PyMuPDF>=1.21 Pillow>=9.0 pdf2image>=1.16 # Markdown → HTML rendering markdown2>=2.4 # Markdown → DOCX rendering python-docx>=0.8.11 beautifulsoup4>=4.12 lxml>=4.9 latex2mathml>=3.75 # Markdown → Excel rendering openpyxl>=3.1 unicodeit>=0.7 # Windows-only Office COM conversion fallback pywin32>=306; platform_system == "Windows" ``` ### Technical Analysis All Python dependencies use open-ended lower bounds. Installation can therefore select any later package release, including major versions that were never reviewed with this skill. No lock file or package hashes are present in the audited project. As a result, two installations performed at different times can resolve to materially different code. The audit did not identify a currently compromised package or a typosquatted dependency. The confirmed weakness is the absence of reproducible, reviewable dependency resolution. The practical risk includes accidental installation of a vulnerable release, breaking API changes, or a future compromised upstream release. Several listed packages process complex and potentially attacker-controlled formats, including images, PDFs, XML, HTML, Office documents, and model responses. Vulnerabilities in these dependencies may therefore be reachable during normal skill operation. ### Attack Path 1. A user or automated setup process installs `requirements.txt`. 2. The package resolver selects the newest versions satisfying the open-ended `>=` constraints. 3. A selected release contains a newly introduced vulnerability, malicious upstream modification, or incompatible behavior. 4. The skill imports and executes that package during OCR or document conversion. 5. A crafted input document or ordinary execu ...[truncated 758 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (66)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

This is a substantial description/behavior mismatch. The declared purpose presents an end-to-end OCR and document-understanding workflow that sends page images and prompts to a VLM endpoint and produces structured textual outputs such as Markdown, HTML, DOCX, or Excel. The supplied code chunk is only a preprocessing/conversion utility: it turns supported documents into page images, with platform-specific document-to-PDF conversion and PDF/image rendering. Those image-generation steps may support a later OCR pipeline, but they do not themselves implement the described OCR/transcription/export functionality. The actual code also relies on local desktop/server tooling rather than remote API access, so the resource/access pattern differs materially from the description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents a multimodal OCR pipeline whose core function is extracting text/content from scanned or visual documents via a remote VLM service and converting results into several output formats. The actual code chunk instead implements a downstream formatting utility: it converts existing Markdown into a styled DOCX, including HTML table parsing and LaTeX-to-Word equation conversion. While the code mentions removal of OCR artifacts and page-order sentinels, that is only preprocessing of already-produced text, not OCR itself. The only notable overlap is DOCX output and improved native Word equation generation, but these are insufficient to make the overall description accurate because the primary purpose, inputs, outputs, and resource usage differ substantially.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The description claims a full OCR/extraction workflow driven by an external VLM service, including required API configuration and conversion of scanned documents into multiple output formats. The actual code chunk only implements a renderer for already-extracted Markdown paired with page images. It scans directories for numbered image/Markdown files, converts Markdown to HTML, embeds local MathJax and Mermaid assets, and writes one standalone HTML report. While some elements loosely align with the description (HTML output, local asset bundling, handling complex tables/math/diagrams), the core declared capability—performing OCR via a model endpoint—is absent. This is a material description/behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This code chunk does not match the declared OCR workflow. It appears to be bundled third-party frontend code for Mermaid/DOM sanitization/KaTeX-style math rendering, including allowed HTML/SVG attribute lists, sanitization hooks, parser/rendering utilities, and SVG path definitions for mathematical symbols. Those are plausible supporting assets for HTML report rendering, but the chunk itself does not perform OCR, document ingestion, model prompting, file conversion, or background job orchestration. Since the actual supplied code is primarily an unrelated vendor rendering library rather than OCR/conversion logic, this is a clear description-behavior mismatch for the evaluated chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description centers on document OCR and conversion via a VLM-backed workflow. The actual code shown is a bundled/minified third-party rendering asset used for visual/math/diagram rendering in the browser, with classes and functions for spans, SVG paths, MathML nodes, font metrics, and symbol tables. This is materially different from OCR processing and does not evidence the declared external API usage, document handling, or output conversion behavior. While bundled frontend assets could be a supporting detail of a larger skill, this specific code chunk itself is unrelated to the declared primary purpose, so it should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The description claims a document OCR and conversion workflow centered on sending page images and prompts to a VLM endpoint and producing structured output files. The actual code is a minified frontend/vendor JavaScript library concerned with mathematical typesetting/rendering (e.g., LaTeX-like parsing, MathML/HTML builders, delimiters, accents, arrays, macros, includegraphics, styling). This is materially different from the declared purpose. While the description mentions local HTML assets, this code is not merely a small supporting asset in an otherwise visible OCR workflow; the supplied chunk itself does not evidence any OCR-related behavior at all and instead shows an unrelated primary capability.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The code does not implement OCR, document ingestion, scanned PDF/image processing, VLM API calls, background jobs, output conversion to Markdown/HTML/DOCX/Excel, or Word equation export. Instead, it is frontend/vendor rendering code for Mermaid diagrams and math content. This is a materially different primary purpose and introduces undeclared capabilities unrelated to the stated OCR workflow.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description promises a document OCR/conversion workflow driven by an OpenAI-compatible VLM endpoint and focused on scanned PDFs/images/office files. The actual code shown is unrelated frontend/vendor library code: Mermaid rendering helpers, markdown lexer/parser/renderer, and js-yaml functionality. There is no evidence of OCR, file processing, page image extraction, API_KEY/BASE_URL/VLM_MODEL usage, network calls to a VLM endpoint, document conversion pipelines, or equation export logic. This is a strong description-versus-behavior mismatch, with the code serving an unrelated UI/rendering/parsing purpose rather than OCR.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description promises a document OCR and conversion workflow that sends page images and OCR prompts to a VLM endpoint and outputs formats like Markdown, HTML, DOCX, or Excel. The actual code is clearly a bundled front-end/vendor library segment for Mermaid diagram rendering: it creates text spans, SVG paths, circles, polygons, rectangles, cylinders, braces, icons, images, and various flowchart node shapes; computes bounding boxes and intersections; and applies styles. There is no evidence of OCR, scanned PDF/image ingestion, office document handling, API key/base URL/model usage, network calls to an OpenAI-compatible endpoint, equation recognition, or output generation in the declared formats. This is a strong description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is about document OCR and conversion via a VLM endpoint, requiring API credentials and producing document outputs. The actual code shown does not perform OCR, document parsing, API calls, file conversion, or equation handling. Instead, it is a bundled third-party Mermaid rendering library for drawing diagrams in SVG/DOM. This is materially unrelated to the declared primary purpose, so the description does not accurately represent this code chunk.

Content

No source excerpt is available for this finding.

Unvalidated Output Injection

High
Category
Output Handling
Confidence
97% confidence
Finding

The script assigns Mermaid's rendered SVG output directly to innerHTML. With Mermaid configured as securityLevel: 'loose' and htmlLabels enabled, untrusted diagram source from OCR content can potentially produce active SVG/HTML content that executes in the report viewer, creating a client-side code injection/XSS path.

Content

Scanner excerpt · scripts/md_to_html.py (reported line 1825)May include surrounding context.

python
var id = 'mmd-' + i;
    try {
      var result = await mermaid.render(id, source);
      el.innerHTML = result.svg;
      el.classList.remove('mermaid');
      el.classList.add('mermaid-rendered');
    } catch (err) {

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/ocr_prompt.py (reported line 237)May include surrounding context.

python
- Do not leave a Mermaid-eligible ownership/entity chart as placeholder-only text if it can be represented faithfully.
- Do not describe Mermaid-eligible relationships only as bullet points when Mermaid can represent them reliably.

Mermaid output rules:
1) Keep the required figure placeholder line at the figure position:
   - ![Concise description <=20 words]
2) Immediately after that placeholder, output exactly one Mermaid fenced block for that figure.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/ai_service_vlm.py (reported line 9)May include surrounding context.

python
"""
First-run setup for the OCR Document Extraction skill.

Checks Python dependencies and .env configuration, creates local config
templates when needed, and validates that the configured model is likely
a vision-capable (multi-modal) model.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/ocr_main.py (reported line 32)May include surrounding context.

python
"""
First-run setup for the OCR Document Extraction skill.

Checks Python dependencies and .env configuration, creates local config
templates when needed, and validates that the configured model is likely
a vision-capable (multi-modal) model.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/ocr_setup.py (reported line 4)May include surrounding context.

python
"""
First-run setup for the OCR Document Extraction skill.

Checks Python dependencies and .env configuration, creates local config
templates when needed, and validates that the configured model is likely
a vision-capable (multi-modal) model.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/ocr_setup.py (reported line 108)May include surrounding context.

python
"""
First-run setup for the OCR Document Extraction skill.

Checks Python dependencies and .env configuration, creates local config
templates when needed, and validates that the configured model is likely
a vision-capable (multi-modal) model.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/ocr_setup.py (reported line 189)May include surrounding context.

python
"""
First-run setup for the OCR Document Extraction skill.

Checks Python dependencies and .env configuration, creates local config
templates when needed, and validates that the configured model is likely
a vision-capable (multi-modal) model.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/ai_service_vlm.py (reported line 30)May include surrounding context.

python
_SCRIPT_DIR = Path(__file__).resolve().parent
_SKILL_ROOT = _SCRIPT_DIR.parent
_REQUIREMENTS = _SKILL_ROOT / "requirements.txt"
_ENV_FILE = _SKILL_ROOT / ".env"
_ENV_EXAMPLE = _SKILL_ROOT / ".env.example"

REQUIRED_PACKAGES: list[tuple[str, str]] = [

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/ai_service_vlm.py (reported line 32)May include surrounding context.

python
_SCRIPT_DIR = Path(__file__).resolve().parent
_SKILL_ROOT = _SCRIPT_DIR.parent
_REQUIREMENTS = _SKILL_ROOT / "requirements.txt"
_ENV_FILE = _SKILL_ROOT / ".env"
_ENV_EXAMPLE = _SKILL_ROOT / ".env.example"

REQUIRED_PACKAGES: list[tuple[str, str]] = [

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/ocr_main.py (reported line 51)May include surrounding context.

python
_SCRIPT_DIR = Path(__file__).resolve().parent
_SKILL_ROOT = _SCRIPT_DIR.parent
_REQUIREMENTS = _SKILL_ROOT / "requirements.txt"
_ENV_FILE = _SKILL_ROOT / ".env"
_ENV_EXAMPLE = _SKILL_ROOT / ".env.example"

REQUIRED_PACKAGES: list[tuple[str, str]] = [

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/ocr_setup.py (reported line 28)May include surrounding context.

python
_SCRIPT_DIR = Path(__file__).resolve().parent
_SKILL_ROOT = _SCRIPT_DIR.parent
_REQUIREMENTS = _SKILL_ROOT / "requirements.txt"
_ENV_FILE = _SKILL_ROOT / ".env"
_ENV_EXAMPLE = _SKILL_ROOT / ".env.example"

REQUIRED_PACKAGES: list[tuple[str, str]] = [

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/ocrctl.py (reported line 215)May include surrounding context.

python
_SCRIPT_DIR = Path(__file__).resolve().parent
_SKILL_ROOT = _SCRIPT_DIR.parent
_REQUIREMENTS = _SKILL_ROOT / "requirements.txt"
_ENV_FILE = _SKILL_ROOT / ".env"
_ENV_EXAMPLE = _SKILL_ROOT / ".env.example"

REQUIRED_PACKAGES: list[tuple[str, str]] = [

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/ocrctl.py (reported line 100)May include surrounding context.

python
)

    cmd = [sys.executable, str(_SCRIPT_DIR / "ocr_worker.py"), "--job-dir", str(store.job_dir)]
    env = {**os.environ, "PYTHONUNBUFFERED": "1"}
    with store.log_path.open("a", encoding="utf-8") as log_file:
        proc = subprocess.Popen(cmd, **_worker_popen_kwargs(log_file=log_file, env=env))
    store.set_worker_pid(proc.pid)

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/ocrctl.py (reported line 190)May include surrounding context.

python
)

    cmd = [sys.executable, str(_SCRIPT_DIR / "ocr_worker.py"), "--job-dir", str(store.job_dir)]
    env = {**os.environ, "PYTHONUNBUFFERED": "1"}
    with store.log_path.open("a", encoding="utf-8") as log_file:
        proc = subprocess.Popen(cmd, **_worker_popen_kwargs(log_file=log_file, env=env))
    store.set_worker_pid(proc.pid)

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · scripts/vendor/mathjax-3.2.2/tex-svg-full.js (reported line 1)May include surrounding context.

js
AIREDDELIMS]},priority:-5}))},config:function(t,e){var r,n,i=e.parseOptions,a=i.options.mathtools.pairedDelimiters;try{for(var Q=o(Object.keys(a)),s=Q.next();!s.done;s=Q.next()){var T=s.value;l.MathtoolsUtil.addPairedDelims(i,T,a[T])}}catch(t){r={error:t}}finally{try{s&&!s.done&&(n=Q.return)&&n.call(Q)}finally{if(r)throw r.error}}(0,c.MathtoolsTagFormat)(t,e)},postprocessors:[[p,-6]],options:{mathtools:{multlinegap:"1em","multlined-pos":"c","firstline-afterskip":"","lastline-preskip":"","smallmatrix-align":"c",shortvdotsadjustabove:".2em",shortvdotsadjustbelow:".2em",centercolon:!1,"centercolon-offset":".04em","thincolon-dx":"-.04em","thincolon-dw":"-.08em","use-unicode":!1,"prescript-sub-format":"","prescript-sup-format":"","prescript-arg-format":"","allow-mathtoolsset":!0,pairedDelimiters:(0,T.expandable)({}),tagforms:(0,T.expandable)({})}}})},6224:function(t,e,r){var n,o=this&&this.__extends||(n=function(t,e){return n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t