Back to skill

Security audit

中国专利.Skill

Security checks across malware telemetry and agentic risk

Overview

The skill largely matches its patent-workflow purpose, but it can automatically install a third-party skill and stores embedding credentials in plaintext, so users should review those parts before installing.

Install only if you are comfortable granting this skill broad local project-document access, command execution for its tooling, and writes to output/Obsidian/OA data directories. Before using Mode D, review the automatic book-to-skill installation path, prefer a manually reviewed pinned install, and avoid putting API keys on the command line; use environment variables or a protected secret store where possible. Pin dependencies for production use, especially document parsers and browser/CAD tooling, and do not process untrusted Office/PDF files outside a sandbox.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (24)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def _run(cmd: list[str] | str, *, timeout: int = 180) -> subprocess.CompletedProcess[str]:
    if isinstance(cmd, str):
        return subprocess.run(
            cmd,
            shell=True,
            text=True,
Confidence
97% confidence
Finding
When cmd is a string, this helper executes it with shell=True, which allows shell metacharacters and command chaining to be interpreted. In this file, the command string can be derived from README content fetched from GitHub, so a compromised repo/README or tampered network path could lead to arbitrary command execution on the host.

Tainted flow: 'out_path' from os.environ.get (line 428, credential/environment) → pathlib.Path.write_text (file write)

Medium
Category
Data Flow
Content
os.environ.get("EPUB_RESULT_HTML", "").strip() or default_result_html_path()
    )
    out_path = out_path.expanduser().resolve()
    out_path.write_text(out_html, encoding="utf-8")
    print(
        "结果页长度",
        len(out_html),
Confidence
91% confidence
Finding
The script takes the output file path directly from the EPUB_RESULT_HTML environment variable, resolves it, and writes attacker-influenced content to that location without restricting the destination. If an untrusted caller can control environment variables when this tool runs, they can cause arbitrary file overwrite/create anywhere writable by the process, which can corrupt files, poison downstream workflows, or overwrite sensitive application data.

Unvalidated Output Injection

High
Category
Output Handling
Content
def _run(cmd: list[str] | str, *, timeout: int = 180) -> subprocess.CompletedProcess[str]:
    if isinstance(cmd, str):
        return subprocess.run(
            cmd,
            shell=True,
            text=True,
Confidence
96% confidence
Finding
This is a true injection sink because untrusted text ultimately reaches subprocess.run with shell=True. The skill context makes it more dangerous, not less, because this code is specifically designed to auto-install an external skill, turning remote documentation content into executable shell input.

Credential Access

High
Category
Privilege Escalation
Content
def default_secrets_path() -> Path:
    """API Key 等敏感项:仅写在用户文档目录,勿提交仓库。"""
    return oa_home() / "embedding.secrets.yaml"


def load_secrets(path: str | Path | None = None) -> dict[str, Any]:
Confidence
80% confidence
Finding
The module defines and later uses a local secrets file under the user's Documents directory to store API credentials in plaintext YAML. While not overtly malicious, storing secrets unencrypted in a broadly accessible user folder increases exposure to local compromise, backup leakage, sync-service disclosure, or accidental sharing.

Credential Access

High
Category
Privilege Escalation
Content
p_set.add_argument(
        "--api-key",
        default="",
        help="写入文档目录 embedding.secrets.yaml(勿提交 git)",
    )
    p_set.add_argument(
        "--secret-group-id",
Confidence
83% confidence
Finding
The CLI accepts an --api-key argument and writes it into embedding.secrets.yaml, which encourages plaintext secret storage and also risks exposure through shell history, process listings, audit logs, or command wrappers. In a patent workflow handling sensitive materials, credential compromise can enable unauthorized use of remote embedding services and associated data exposure.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# Used by tools/shared/md_to_docx.py, docx_to_md.py, pptx_to_md.py,
# mermaid_render.py, formula_plan.
python-docx>=1.1.0
# Word editable math (LaTeX -> MathML -> OMML); keep source text on failure
latex2mathml>=3.77.0
# formula_plan / paradigms.yaml
Confidence
92% confidence
Finding
The dependency is specified with a lower bound only, which allows future installs to resolve to different versions over time. This weakens build reproducibility and can unintentionally introduce vulnerable or breaking releases through normal dependency updates.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# mermaid_render.py, formula_plan.
python-docx>=1.1.0
# Word editable math (LaTeX -> MathML -> OMML); keep source text on failure
latex2mathml>=3.77.0
# formula_plan / paradigms.yaml
PyYAML>=6.0
# mermaid -> PNG via Playwright; shares browser with CNIPA crawl
Confidence
92% confidence
Finding
The package uses a minimum-version specifier rather than an exact pin, so installations are not deterministic. That creates supply-chain risk because newly published upstream versions may be pulled in without review and could contain vulnerabilities or incompatible behavior.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# Word editable math (LaTeX -> MathML -> OMML); keep source text on failure
latex2mathml>=3.77.0
# formula_plan / paradigms.yaml
PyYAML>=6.0
# mermaid -> PNG via Playwright; shares browser with CNIPA crawl
# (tools/shared/browser.py)
playwright>=1.40.0
Confidence
94% confidence
Finding
Using PyYAML with only a lower-bound version means the resolved package version can drift across environments and time. While not an exploit by itself, this increases exposure to supply-chain issues and makes security posture harder to control.

Unpinned Dependencies

Low
Category
Supply Chain
Content
PyYAML>=6.0
# mermaid -> PNG via Playwright; shares browser with CNIPA crawl
# (tools/shared/browser.py)
playwright>=1.40.0
mammoth>=1.6.0
python-pptx>=0.6.21
Confidence
93% confidence
Finding
Playwright is unpinned, which allows uncontrolled upgrades of a browser-automation component that often interacts with external content and browser binaries. In this skill context, browser tooling used for Mermaid rendering and CNIPA crawling increases the operational risk of unexpected vulnerable versions being installed.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# mermaid -> PNG via Playwright; shares browser with CNIPA crawl
# (tools/shared/browser.py)
playwright>=1.40.0
mammoth>=1.6.0
python-pptx>=0.6.21

# Optional: formula PNG (OMML fail AND user says yes; ~100MB incl numpy)
Confidence
97% confidence
Finding
The dependency is not effectively pinned in the requirements file and the same package is separately flagged with a known critical advisory. In this context, Mammoth processes document content, so a vulnerable or drifting version is more dangerous because it may handle attacker-supplied files.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# (tools/shared/browser.py)
playwright>=1.40.0
mammoth>=1.6.0
python-pptx>=0.6.21

# Optional: formula PNG (OMML fail AND user says yes; ~100MB incl numpy)
#   pip install matplotlib
Confidence
92% confidence
Finding
The dependency uses a lower-bound constraint instead of an exact version, allowing non-reproducible installs and unreviewed upstream changes. This is a common supply-chain hygiene issue even when there is no currently known CVE for the package.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# 国知局公布公告站检索(tools/crawl/cnipa_epub_search.py / cnipa_epub_crawler.py)依赖
# 与根目录 requirements.txt 中的 playwright 相同;有系统 Chrome / Edge 时不必 playwright install chromium
# 探测:python tools/shared/browser.py --probe
playwright>=1.40.0
Confidence
95% confidence
Finding
The dependency is specified with a lower-bound range (playwright>=1.40.0) rather than an exact pinned version, which makes builds non-reproducible and can introduce unexpected upstream changes or vulnerable releases over time. In a browser-automation dependency like Playwright, this can affect both security posture and runtime behavior if a compromised or breaking version is later resolved by package installation.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# 模式 D · 审查答复 / 案例向量(可选)
sqlite-vec>=0.1.6
PyYAML>=6.0
numpy>=1.24.0
Confidence
93% confidence
Finding
The dependency is specified with a lower bound only, which allows future unreviewed versions to be installed and can reduce build reproducibility. If an upstream release introduces a malicious package, breaking change, or known vulnerable transitive dependency, installations may silently pick it up.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# 模式 D · 审查答复 / 案例向量(可选)
sqlite-vec>=0.1.6
PyYAML>=6.0
numpy>=1.24.0

# 本地 embedding(provider=local 时)
Confidence
97% confidence
Finding
PyYAML is declared with a minimum version but no upper bound or exact pin, so deployments are not reproducible and may consume unexpected upstream changes. For a parser library, this increases supply-chain and stability risk if a future release introduces a security issue or incompatible behavior.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# 模式 D · 审查答复 / 案例向量(可选)
sqlite-vec>=0.1.6
PyYAML>=6.0
numpy>=1.24.0

# 本地 embedding(provider=local 时)
sentence-transformers>=2.2.0
Confidence
93% confidence
Finding
Using an unpinned numpy version permits installation of any later release satisfying the minimum bound, which can introduce unreviewed code or dependency changes. This is mainly a software supply-chain and reproducibility concern rather than an immediate direct exploit in this file.

Unpinned Dependencies

Low
Category
Supply Chain
Content
numpy>=1.24.0

# 本地 embedding(provider=local 时)
sentence-transformers>=2.2.0

# PDF 文本抽取(审查通知书 / 历史答复)
pymupdf>=1.24.0
Confidence
95% confidence
Finding
sentence-transformers is unpinned, so future installations may resolve to newer versions with changed behavior, vulnerable dependencies, or maliciously compromised releases. Because this package typically brings a sizable transitive dependency tree, the supply-chain exposure is somewhat elevated compared with very small libraries.

Unpinned Dependencies

Low
Category
Supply Chain
Content
sentence-transformers>=2.2.0

# PDF 文本抽取(审查通知书 / 历史答复)
pymupdf>=1.24.0

# 线上 openai_compatible / minimax 用标准库 urllib 即可,无需额外包
# MiniMax:需 MINIMAX_API_KEY + MINIMAX_GROUP_ID(见 config.py --preset minimax)
Confidence
96% confidence
Finding
pymupdf is specified with only a minimum version, allowing uncontrolled upgrades to parser code that processes PDFs. Parser libraries can become security-sensitive if future versions contain exploitable flaws or if a compromised release is installed, making version pinning important.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"private": true,
  "description": "Optional legacy mmdc install; mermaid_render.py now uses Playwright + vendor/mermaid.min.js and does not require this package.",
  "devDependencies": {
    "@mermaid-js/mermaid-cli": "^11.4.0",
    "puppeteer": "^23.1.1"
  }
}
Confidence
95% confidence
Finding
The dependency uses a caret range (^11.4.0), which permits automatic installation of newer minor and patch releases rather than an exact vetted version. This increases supply-chain risk because future upstream releases could introduce malicious code or breaking behavior without a deliberate review, even though the package is only listed in devDependencies and described as optional legacy tooling.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"description": "Optional legacy mmdc install; mermaid_render.py now uses Playwright + vendor/mermaid.min.js and does not require this package.",
  "devDependencies": {
    "@mermaid-js/mermaid-cli": "^11.4.0",
    "puppeteer": "^23.1.1"
  }
}
Confidence
95% confidence
Finding
The puppeteer dependency is specified with a caret range (^23.1.1), allowing npm to resolve newer minor and patch versions automatically. That creates a supply-chain exposure window where unreviewed upstream changes could be pulled into development or CI environments, though the risk is moderated by the fact that this is a development dependency rather than runtime code.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# 专利解读可选依赖(tools/patent_reader/ 处理 PDF)
pymupdf>=1.24.0
Confidence
89% confidence
Finding
The dependency is specified with a lower bound only (`pymupdf>=1.24.0`), which allows future unreviewed versions to be installed. That creates supply-chain and reproducibility risk: a breaking, compromised, or vulnerable upstream release could be pulled into the environment without explicit approval. In this skill, the package is used for PDF handling, so the context slightly increases concern because PDF parsers are historically attack-prone, but this file alone does not show active exploitation.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# Official wheels: Python 3.10-3.12 (NOT 3.13+). ASCII comments only:
# Windows venv pip may decode this file as the system code page (GBK) and fail
# on UTF-8 non-ASCII. Keep this file ASCII.
cadquery>=2.4.0
cairosvg>=2.7.0
Confidence
93% confidence
Finding
The dependency is specified with a lower bound only, which allows future installs to resolve to different versions over time. This weakens build reproducibility and can unintentionally pull in a newly broken or vulnerable release, creating supply-chain risk even though the file itself does not force a known-bad version here.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# Windows venv pip may decode this file as the system code page (GBK) and fail
# on UTF-8 non-ASCII. Keep this file ASCII.
cadquery>=2.4.0
cairosvg>=2.7.0
Confidence
96% confidence
Finding
The requirement uses a minimum version only, so dependency resolution is non-deterministic and may install different versions across environments. In this specific file, that risk is more significant because the package also has a reported vulnerable version in the analyzer context, so loose versioning increases the chance of pulling an unsafe or unreviewed release depending on installer behavior and environment state.

Known Vulnerable Dependency: mammoth==1.6.0 — 2 advisory(ies): CVE-2025-11849 (Mammoth is vulnerable to Directory Traversal); CVE-2025-11849 (Mammoth is vulnerable to Directory Traversal)

Critical
Category
Supply Chain
Confidence
98% confidence
Finding
Mammoth 1.6.0 is reported as vulnerable to directory traversal, which can allow crafted document input to access or write files outside the intended directory boundary. Because this skill handles document conversion and may process user-provided files, the context materially increases risk: an attacker could exploit document-processing workflows to impact the host environment or sensitive files.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
def _run(cmd: list[str] | str, *, timeout: int = 180) -> subprocess.CompletedProcess[str]:
    if isinstance(cmd, str):
        return subprocess.run(
            cmd,
            shell=True,
            text=True,
Confidence
98% confidence
Finding
The helper accepts a tool command as a free-form string and runs it via the shell, enabling parameter abuse and full command substitution. Because install_book_to_skill can consume a command extracted from a remote README, an attacker could abuse tool parameters to run arbitrary commands under the user's privileges.

VirusTotal

65/65 vendors flagged this skill as clean.

View on VirusTotal

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
tools/shared/formula_eval.py:239