Back to skill

Security audit

本地导入PDF至Zotero文库

Security checks for vulnerabilities and agentic risk

Overview

This Zotero PDF import skill is mostly coherent, but it tells agents to automatically install an unpinned Python package before use.

Review this before installing. It appears intended for local Zotero PDF import, but you should avoid the automatic dependency-install path unless you are comfortable letting the skill run pip in the active Python environment. Prefer installing reviewed dependencies yourself in a virtual environment, and only import PDF paths and Zotero ports you intentionally provide.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T08 · Insecure Dependencies

Warning
Location
scripts/zotero_tool.py:246
Finding

Automatic Installation of an Unpinned Third-Party Dependency

Content
View full analysis

Vulnerability Details

File Location: scripts/zotero_tool.py:246-256
Related Locations: scripts/requirements.txt:1; SKILL.md:41,58-70
Vulnerability Type: Supply-chain exposure through automatic, unpinned dependency installation
Risk Level: Medium

Complete Code Snippet

python
req_mod = requests
if req_mod is None:
    print("dep_requests=missing")
    if args.auto_install_deps:
        print("dep_requests=installing")
        r = subprocess.run(
            [
                sys.executable,
                "-m",
                "pip",
                "install",
                "requests>=2.31.0",
            ],
            capture_output=True,
            text=True,
        )
        if r.returncode != 0:
            print("dep_requests=install_failed")
            print((r.stderr or r.stdout or "").strip()[:500])
            return 10
        import importlib
        req_mod = importlib.import_module("requests")
        print(
            f"dep_requests=installed version="
            f"{getattr(req_mod, '__version__', 'unknown')}"
        )

The dependency specification is also unpinned:

text
requests>=2.31.0

The documented workflow directs the Agent to invoke this behavior:

text
Fixed workflow: run `doctor --auto-install-deps` first, and perform the
import only after it passes.

Technical Analysis

The doctor --auto-install-deps command invokes pip whenever requests is unavailable. The version constraint permits any release at or above version 2.31.0 and does not provide an integrity hash, lock file, isolated environment, or enforced trusted package index.

Python package installation may execute package build or installation logic. Consequently, the command establishes a code-execution path from the configured package source to the local environment. The affected package name is legitimate and no malicious dependency was observed in the audited project; the risk arises from mutable resolution an ...[truncated 2398 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove automatic package installation from the runtime workflow. If requests is missing, stop and request explicit user-managed installation.
  2. Pin dependencies to an audited exact version instead of using a lower-bound-only constraint.
  3. Generate and verify cryptographic hashes, for example with a hash-locked requirements file and pip install --require-hashes.
  4. Install dependencies in a dedicated virtual environment rather than modifying the Agent's active or global Python environment.
  5. Enforce a trusted package index and disable unintended extra indexes where operationally feasible.
  6. Separate environment provisioning from Skill execution so importing a PDF never implicitly performs package-management operations.
  7. If automatic installation must remain, require explicit user confirmation immediately before installation and display the exact package, version, index, and target environment.
  8. Maintain a reviewed lock file and periodically update it through a controlled dependency-review process.
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (12)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill instructs the agent to use shell, network, file access, and environment-dependent behavior, but it does not declare any explicit tool scope or permissions boundary. This increases the chance that an agent will execute broader-than-necessary actions such as arbitrary shell commands, package installation, or local-network access without clear containment or user-visible authorization.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest description forces a specific language/locale presentation without indicating that users may choose another language. Under the policy, language constraints should be optional, user-selected, or explicitly justified as region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The user-facing invocation examples are only provided in Chinese and imply the interaction language the skill expects, but do not state that other languages are supported or that Chinese is an optional variant. This can violate language/locale policy when no user opt-in is provided.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/zotero_tool.py (reported line 63)May include surrounding context.

python
if sys.platform.startswith("win"):
        os.startfile(url)  # type: ignore[attr-defined]
    elif sys.platform == "darwin":
        subprocess.run(["open", url], check=True)
    else:
        subprocess.run(["xdg-open", url], check=True)
    time.sleep(1.2)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/zotero_tool.py (reported line 65)May include surrounding context.

python
elif sys.platform == "darwin":
        subprocess.run(["open", url], check=True)
    else:
        subprocess.run(["xdg-open", url], check=True)
    time.sleep(1.2)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The import command prints info=selected target: 我的文库, which hard-codes a Chinese locale in user-facing output. This is a natural-language policy concern because the script does not offer any language choice or document that it is intentionally region-specific.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Allowing a diagnostic subcommand to auto-install dependencies is broader than the stated purpose of importing local PDFs into Zotero and creates an unnecessary environment-modification path. In an agent/skill setting, such side effects are more dangerous because users may not expect a helper tool to invoke pip, fetch code from package sources, and alter the Python environment.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
88% confidence
Finding

The doctor command can install Python packages at runtime via pip, which expands the tool's capability beyond local Zotero import into system modification and external package retrieval. In a skill context, that is risky because it executes a package manager against remote indexes and can change the user's environment, increasing supply-chain and unintended-change exposure.

Content

Scanner excerpt · scripts/zotero_tool.py (reported line 250)May include surrounding context.

python
print("dep_requests=missing")
        if args.auto_install_deps:
            print("dep_requests=installing")
            r = subprocess.run([sys.executable, "-m", "pip", "install", "requests>=2.31.0"], capture_output=True, text=True)
            if r.returncode != 0:
                print("dep_requests=install_failed")
                print((r.stderr or r.stdout or "").strip()[:500])

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/zotero_tool.py (reported line 278)May include surrounding context.

python
if sys.platform.startswith("win"):
            print("url_opener=ok method=os.startfile")
        elif sys.platform == "darwin":
            r = subprocess.run(["which", "open"], capture_output=True, text=True)
            print("url_opener=ok method=open" if r.returncode == 0 else "url_opener=fail missing=open")
            ok = ok and (r.returncode == 0)
        else:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/zotero_tool.py (reported line 282)May include surrounding context.

python
print("url_opener=ok method=open" if r.returncode == 0 else "url_opener=fail missing=open")
            ok = ok and (r.returncode == 0)
        else:
            r = subprocess.run(["which", "xdg-open"], capture_output=True, text=True)
            print("url_opener=ok method=xdg-open" if r.returncode == 0 else "url_opener=fail missing=xdg-open")
            ok = ok and (r.returncode == 0)
    except Exception as e:

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
92% confidence
Finding

The dependency is specified as requests>=2.31.0, which allows future unreviewed versions to be installed and also does not guarantee a reproducible environment. In a security-sensitive skill that talks to a local Zotero connector over localhost and processes user-supplied file paths, unpinned dependencies increase supply-chain and compatibility risk because the actually installed version may differ across systems and over time.

Content

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

text
requests>=2.31.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
85% confidence
Finding

The manifest does not pin requests, so it is impossible to verify whether the installed version is affected by any known advisories. While this file alone does not prove an exploitable vulnerable version is present, the lack of version pinning means users may install a release with known security issues, which is avoidable supply-chain risk.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.