Back to skill

Security audit

WoS Zotero Literature Hunter

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it says, but it needs Review because it handles read/write Zotero credentials through command-line examples and uses authenticated browser/profile access plus external metadata services.

Before installing, use a narrowly scoped Zotero API key, avoid pasting the key directly into command lines, run dry-run first, and review the paper list before import. Be aware that the agent may use your authenticated browser session and that Crossref queries disclose paper titles or DOIs to a third-party metadata service.

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/import_to_zotero.py:255
Finding

Zotero API Key Exposed Through Command-Line Arguments

Content
View full analysis
\ --zotero-id \ --collection "collection-name" ``` ### Technical Analysis The script requires the Zotero API key as a command-line argument. Command-line secrets can be exposed through: - Shell history files when users type or paste the documented command. - Process inspection facilities while the command is running. - Process-monitoring, telemetry, or audit systems that record complete command lines. - Terminal logs, debugging output, or automation logs containing the invocation. This behavior conflicts with the documentation's assertion that the key is never written to disk. Although the Python script does not explicitly save the key, the shell may persist the complete command automatically. Exploitation requires local access, access to command telemetry, or access to the affected user's shell history. There is no evidence that the project intentionally transmits the key to an unrelated service. ### Attack Path 1. A user follows the documented command and supplies a read/write Zotero API key through `--zotero-key`. 2. The shell records the command in its history, or the operating system exposes it in process metadata while the script runs. 3. Another local user, process, monitoring service, or attacker with access to the user's files retrieves th ...[truncated 773 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
SKILL.md:18
Finding

Unpinned Third-Party Dependency Installation

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The manifest describes a WoS search-and-filter skill, but the documented implementation actually relies on browser automation plus a shell script that imports already-supplied records and enriches them via Crossref. This mismatch can mislead users and reviewers about what is truly automated, what external services are contacted, and where sensitive inputs like API keys are exposed, making unsafe execution more likely.

Content

No source excerpt is available for this finding.

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 · SKILL.md (reported line 3)May include surrounding context.

md
---
name: wos-zotero-hunter
description: Search Web of Science for academic literature through institutional access, filter by journal, impact factor, or date, and automatically import results into Zotero. Use when the user wants to find and import scholarly papers from WoS into Zotero — they will describe a topic, quality criteria (IF, journal names, citation count), desired paper count, and a Zotero collection name.
---

# WoS → Zotero Literature Hunter

Search Web of Science through the user's institutional access, filter results by quality criteria, and import papers to a new Zotero collection with full metadata.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill declares capabilities that require network and shell access but does not explicitly scope or constrain those tools in the manifest. This weakens reviewability and enforcement, increasing the chance that an agent can invoke broader-than-expected operations, including external requests and command execution with sensitive arguments.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The docstring says the script can resolve DOIs from titles via Crossref when DOIs are missing. But in the main preprocessing loop, enrichment is only called when a paper lacks a journal and already has a DOI (L293-L296), and the per-item import path also only calls enrichment when a DOI already exists (L181-L183). As a result, title-only DOI lookup is not actually exercised for missing-DOI inputs in normal execution.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
84% confidence
Finding

The script sends paper titles to Crossref, which is an external third party, without any explicit user confirmation, opt-out, or data-minimization controls. In a research workflow, titles may reveal unpublished topics, sensitive review work, or confidential institutional interests, so this can leak user data beyond the expected WoS/Zotero flow.

Content

Scanner excerpt · scripts/import_to_zotero.py (reported line 34)May include surrounding context.

python
def lookup_doi_via_crossref(title: str) -> Optional[str]:
    """Look up a paper's DOI via Crossref API by title."""
    query = urllib.parse.quote(title[:200])
    url = f"https://api.crossref.org/works?query.title={query}&rows=1"
    try:
        result = subprocess.run(
            ["curl", "-s", "--max-time", "10", url],

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/import_to_zotero.py (reported line 36)May include surrounding context.

python
query = urllib.parse.quote(title[:200])
    url = f"https://api.crossref.org/works?query.title={query}&rows=1"
    try:
        result = subprocess.run(
            ["curl", "-s", "--max-time", "10", url],
            capture_output=True, text=True, timeout=12,
        )

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/import_to_zotero.py (reported line 64)May include surrounding context.

python
query = urllib.parse.quote(title[:200])
    url = f"https://api.crossref.org/works?query.title={query}&rows=1"
    try:
        result = subprocess.run(
            ["curl", "-s", "--max-time", "10", url],
            capture_output=True, text=True, timeout=12,
        )

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

The script transmits DOI values to Crossref for metadata enrichment, creating an external data flow not limited to Zotero or Web of Science. While DOIs are public identifiers, the set of queried DOIs can still disclose a user's research focus, institutional activity, or reading/import intentions, which is more sensitive in this skill context because users expect a WoS-to-Zotero workflow.

Content

Scanner excerpt · scripts/import_to_zotero.py (reported line 62)May include surrounding context.

python
if not doi:
        return paper  # Can't enrich without DOI

    url = f"https://api.crossref.org/works/{urllib.parse.quote(doi)}"
    try:
        result = subprocess.run(
            ["curl", "-s", "--max-time", "10", url],

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The manifest describes a skill for searching Web of Science and importing those results into Zotero. This script, however, accepts any JSON list of papers from a file or stdin and processes/imports them without validating that they came from Web of Science, while also performing Crossref-based metadata enrichment. That makes the implemented import capability more general than the manifest claims.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.