Back to skill

Security audit

PubMed Review

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it advertises, but it needs review because it sends research content to external services and uses shared task state and configurable executables/endpoints without enough containment.

Review before installing on shared Feishu/OpenClaw hosts. Use a dedicated MiniMax key, pin or allowlist the MiniMax endpoint and notify binary, keep env files writable only by trusted admins, avoid confidential patient or unpublished project details, and require explicit task_id or per-user context for follow-up answers.

Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (13)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
msg_file = '/tmp/pubmed_intent_notify.msg'
    with open(msg_file, 'w') as f:
        f.write(message)
    subprocess.run([NOTIFY_SCRIPT, '-t', '文献综述', '-m', message], shell=False)
    os.remove(msg_file)
Confidence
93% confidence
Finding
The code executes an external program whose path is partially controlled by the NOTIFY_PATH environment variable. Even with shell=False, an attacker who can influence the runtime environment can redirect execution to an arbitrary binary or script, resulting in unintended code execution in the context of this service.

Tainted flow: 'NOTIFY_SCRIPT' from os.environ.get (line 20, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Content
def notify_user(message):
    """发送飞书消息"""
    subprocess.run(
        [NOTIFY_SCRIPT, '-t', '综述追问回复', '-m', message],
        shell=False
    )
Confidence
89% confidence
Finding
NOTIFY_SCRIPT is sourced from an environment variable and then executed as a program. If an attacker can influence the runtime environment, they can replace the notifier path with an arbitrary executable, leading to code execution under the privileges of this script.

Tainted flow: 'req' from os.environ.get (line 216, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
method='POST'
    )

    with urllib.request.urlopen(req, timeout=30) as resp:
        result = json.loads(resp.read().decode('utf-8'))
        msg = result['choices'][0]['message']
        content = msg.get('content', '') or msg.get('reasoning_content', '')
Confidence
95% confidence
Finding
The request destination is derived from environment-controlled configuration and user/question/article content is sent to that endpoint. If MINIMAX_API_URL is altered, sensitive content can be silently exfiltrated to an attacker-controlled server; this is especially concerning because the script includes literature content and user questions in the payload.

Tainted flow: 'NOTIFY_SCRIPT' from os.environ.get (line 23, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Content
msg_file = '/tmp/pubmed_intent_notify.msg'
    with open(msg_file, 'w') as f:
        f.write(message)
    subprocess.run([NOTIFY_SCRIPT, '-t', '文献综述', '-m', message], shell=False)
    os.remove(msg_file)
Confidence
97% confidence
Finding
NOTIFY_SCRIPT is derived from an environment variable and then used as the executable in subprocess.run. In an agent or automation environment where env can be influenced by deployment mistakes, wrappers, or other components, this becomes an arbitrary command execution primitive.

Tainted flow: 'req' from os.environ.get (line 73, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
method='POST'
    )

    with urllib.request.urlopen(req, timeout=15) as resp:
        result = json.loads(resp.read().decode('utf-8'))
        msg = result['choices'][0]['message']
        content = msg.get('content', '') or msg.get('reasoning_content', '')
Confidence
91% confidence
Finding
The request destination is built from environment-controlled LLM_API_URL and then user content is sent to that endpoint. If an attacker can alter the environment, they can redirect sensitive prompts and user messages to an arbitrary server, causing SSRF-like outbound connections and data exfiltration of potentially sensitive medical queries.

Tainted flow: 'LOCK_FILE' from os.environ.get (line 13, credential/environment) → open (file write)

Medium
Category
Data Flow
Content
def dispatch():
    my_pid = os.getpid()
    lock_fd = open(LOCK_FILE, 'w')
    try:
        fcntl.flock(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
    except BlockingIOError:
Confidence
90% confidence
Finding
LOCK_FILE is derived from an environment variable and then opened for writing without validation. In environments where an attacker can influence process environment variables, this can cause arbitrary file creation or truncation, symlink abuse, or writing locks outside the intended .locks directory, potentially damaging files or interfering with system behavior.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill documentation describes capabilities to access environment variables, read and write local files, invoke shell commands, and make network requests, but it does not declare any permissions or constraints. This creates a trust and review gap: operators cannot accurately assess what the skill is allowed to do, and the combination of shell, file, env, and network access materially increases the risk of data exfiltration or unintended command execution if the implementation is compromised or misused.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The script sends user questions and article-derived content to an external LLM service without any visible user consent, warning, or data-minimization control. In a research workflow, follow-up questions may contain sensitive project context or unpublished material, so undisclosed third-party transmission creates a privacy and compliance risk.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script transmits PubMed article titles, abstracts, topic text, and related metadata to an external LLM API without any explicit user-facing consent, warning, or policy check. In a literature-review workflow this can leak unpublished search topics, sensitive research interests, or regulated biomedical text to a third-party processor unexpectedly.

Ssd 3

Medium
Confidence
93% confidence
Finding
The fallback logic can resolve a follow-up question to a previously completed task based on prior state, weak keyword overlap, or simply the latest completed task. In a multi-user or shared runtime context, this can cause one user's question to retrieve and summarize another task's article set, creating cross-request data leakage and incorrect context binding.

Ssd 3

Medium
Confidence
89% confidence
Finding
Raw user input is sent to an external LLM for intent recognition without any minimization, redaction, or consent boundary. In this skill context, users may include sensitive medical or research details, so external transmission increases privacy and compliance risk even if it is part of intended functionality.

Ssd 4

Medium
Confidence
92% confidence
Finding
Untrusted article titles and abstracts are inserted directly into the LLM prompt, so malicious or adversarial text inside fetched literature can instruct the model to ignore the requested format, reveal hidden context, or generate misleading output. In an agentic workflow, prompt injection is especially relevant because model output is later written to files and partially forwarded for notifications.

Ssd 4

Medium
Confidence
86% confidence
Finding
The topic string from task metadata is interpolated verbatim into the prompt and can semantically steer the model if task content is attacker-controlled. In this skill, tasks appear to come from upstream workflow files, so a malicious topic could alter instructions, force disclosure-style content, or degrade output integrity.

Static analysis

No suspicious patterns detected.