Back to skill

Security audit

PubMed Review

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a real PubMed review tool, but it has unsafe configuration and execution paths that need review before installation.

Install only in a controlled environment after fixes or compensating controls: pin MINIMAX_API_URL to an approved HTTPS host, parse env files as data rather than shell code, validate task IDs and article paths, restrict NOTIFY_PATH to a trusted binary, and run any dispatcher or cron job as a dedicated unprivileged user. Treat user queries and article abstracts as content that may leave the local environment for MiniMax and Feishu.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/pubmed_intent_handler.py:48
Finding

Unrestricted LLM Endpoint Can Receive API Credentials and Sensitive Medical Content

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/run_pubmed_summary.sh:26
Finding

Configurable Environment File Is Executed as Shell Code

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/run_pubmed_summary.sh:58
Finding

Command-Line Arguments Are Interpolated into Inline Python Source

Content
View full analysis
/dev/null) ARTICLE_COUNT=$(python3 -c " import json with open('${ARTICLES_JSON}') as f: articles = json.load(f) print(len(articles)) " 2>/dev/null || echo "?") ``` ### Technical Analysis `TASK_ID` and `ARTICLES_JSON` are inserted directly into Python source enclosed by single-quoted Python string literals. The script does not validate or escape either value before interpolation. A value containing quotes, line breaks, backslashes, or Python syntax can alter the program passed to `python3 -c`. Quoting the shell variables at initial assignment does not protect the later Python source construction. The normal internal task-creation path generates task IDs in a constrained format, reducing exposure through ordinary queue processing. However, the script is documented as a directly callable CLI interface and does not enforce that format at its trust boundary. The article path is likewise accepted from the command line and only checked for file existence. `TASK_ID` is also included in the summary output path: ```bash SUMMARY_FILE="${RESULTS_DIR}/${TASK_ID}_summary.md" ``` Without validation, path separators or traversal components can cause output outside the intended result filename namespace, subject to filesystem permissions. ### Attack Path 1. An untrusted caller or integration supplies a crafted `TASK_ID` or an existing crafted ` ...[truncated 1082 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/pubmed_intent_handler.py:275
Finding

Predictable Temporary File Permits Symlink-Based File Overwrite

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (52)

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

Critical
Category
Data Flow
Confidence
96% confidence
Finding

The destination URL for the LLM request is environment-controlled via MINIMAX_API_URL, and the request includes sensitive content plus the Bearer API key. If an attacker can alter that variable, they can redirect requests to an arbitrary server and exfiltrate both the user's question/article data and credentials, effectively turning this into SSRF-plus-secret-leakage.

Content

Scanner excerpt · scripts/pubmed_followup_handler.py (reported line 226)May include surrounding context.

python
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', '')

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/pubmed_intent_handler.py (reported line 83)May include surrounding context.

python
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', '')

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/pubmed_llm_summarize.py (reported line 97)May include surrounding context.

python
method='POST'
        )

        with urllib.request.urlopen(req, timeout=60) as resp:
            result = json.loads(resp.read().decode('utf-8'))
            msg = result['choices'][0]['message']
            content = msg.get('content', '') or msg.get('reasoning_content', '')

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

This mismatch is security-relevant because the skill is presented as a narrow literature-review workflow but reportedly also performs local task queue persistence and subprocess execution. Hidden or under-documented file and shell behavior can cause reviewers to underestimate operational risk and approve broader access than intended.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
86% confidence
Finding

This mismatch is security-relevant because the skill is presented as a narrow literature-review workflow but reportedly also performs local task queue persistence and subprocess execution. Hidden or under-documented file and shell behavior can cause reviewers to underestimate operational risk and approve broader access than intended.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

This mismatch is security-relevant because the skill is presented as a narrow literature-review workflow but reportedly also performs local task queue persistence and subprocess execution. Hidden or under-documented file and shell behavior can cause reviewers to underestimate operational risk and approve broader access than intended.

Content

No source excerpt is available for this finding.

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

python
{articles_text}

请开始撰写:"""
    return prompt


def call_llm(prompt):

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The README describes activation via ordinary natural-language messages in Feishu and gives examples like '帮我查…' and '帮我搜索…', but it does not define a strict trigger list, exclusion conditions, or when similar everyday phrasing should not invoke the skill. This ambiguity can cause unintended invocation because these phrases overlap with common conversational requests.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill documents capabilities that imply access to environment variables, filesystem, network, and shell execution, but it does not declare any explicit tool scope or permissions boundaries. This increases the blast radius if the skill is invoked in a permissive runtime, because operators and users cannot readily tell what external effects or privileged actions it may perform.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The natural-language trigger description is overly broad and lacks clear boundaries for when the skill should activate. In chat-integrated systems, ambiguous triggering can cause unintended execution, unnecessary data transmission, or accidental use of external APIs on messages that the user did not intend as PubMed requests.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill description does not clearly warn that user queries and generated outputs may be sent to external services and push-notified through Feishu. This is dangerous because literature queries can contain sensitive research interests, internal project context, or regulated information, and users may not realize their content is leaving the local environment.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

The skill sends content to an external LLM endpoint, which creates a real data exfiltration and privacy risk if user queries, article summaries, or follow-up content contain sensitive information. In this skill context, the risk is elevated because medical/research topics and generated reviews may reveal confidential interests or internal analyses, and the transmission is only implicitly documented.

Content

Scanner excerpt · SKILL.md (reported line 25)May include surrounding context.

md
| 变量名 | 必须 | 说明 |
|--------|------|------|
| `MINIMAX_API_KEY` | ✅ | MiniMax API Key |
| `MINIMAX_API_URL` | 否 | 默认为 `https://api.minimax.chat/v1/text/chatcompletion_v2` |
| `MINIMAX_MODEL` | 否 | 默认为 `MiniMax-M2.7-highspeed` |
| `NOTIFY_PATH` | 否 | 飞书 notify 脚本路径,默认为 `which notify` |
| `MINIMAX_ENV_FILE` | 否 | 环境变量文件路径,默认为 `./.env.minimax` |

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Automatic trigger conditions are described vaguely, without specifying when the skill should or should not run. This can lead to accidental activation in Feishu/OpenClaw contexts, exposing user text to external services or creating tasks without clear user consent.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The skill is described as handling PubMed retrieval, AI review generation, Feishu notification, and follow-up Q&A. Mentioning 'Cookie 失效' handling implies the skill also monitors or depends on browser/session cookie state, which is not justified anywhere else in the stated purpose and is not an obvious implementation detail for PubMed E-utilities or LLM summarization.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The script reads an environment-specified file and imports every KEY=VALUE pair into process environment variables without validating the path, ownership, or contents. In a shared or attacker-influenced deployment, this creates a configuration-injection surface that can alter API endpoints, credentials, or downstream behavior, enabling issues like the arbitrary endpoint and notifier-path abuses seen elsewhere in the file.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · README.md (reported line 50)May include surrounding context.

md
load_llm_env()

LLM_API_URL = os.environ.get('MINIMAX_API_URL', 'https://api.minimax.chat/v1/text/chatcompletion_v2')
LLM_API_KEY = os.environ.get('MINIMAX_API_KEY', '')
LLM_MODEL = os.environ.get('MINIMAX_MODEL', 'MiniMax-M2.7-highspeed')

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/pubmed_followup_handler.py (reported line 35)May include surrounding context.

python
load_llm_env()

LLM_API_URL = os.environ.get('MINIMAX_API_URL', 'https://api.minimax.chat/v1/text/chatcompletion_v2')
LLM_API_KEY = os.environ.get('MINIMAX_API_KEY', '')
LLM_MODEL = os.environ.get('MINIMAX_MODEL', 'MiniMax-M2.7-highspeed')

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/pubmed_intent_handler.py (reported line 48)May include surrounding context.

python
load_llm_env()

LLM_API_URL = os.environ.get('MINIMAX_API_URL', 'https://api.minimax.chat/v1/text/chatcompletion_v2')
LLM_API_KEY = os.environ.get('MINIMAX_API_KEY', '')
LLM_MODEL = os.environ.get('MINIMAX_MODEL', 'MiniMax-M2.7-highspeed')

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/pubmed_llm_summarize.py (reported line 135)May include surrounding context.

python
load_llm_env()

LLM_API_URL = os.environ.get('MINIMAX_API_URL', 'https://api.minimax.chat/v1/text/chatcompletion_v2')
LLM_API_KEY = os.environ.get('MINIMAX_API_KEY', '')
LLM_MODEL = os.environ.get('MINIMAX_MODEL', 'MiniMax-M2.7-highspeed')

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · skill.json (reported line 21)May include surrounding context.

json
load_llm_env()

LLM_API_URL = os.environ.get('MINIMAX_API_URL', 'https://api.minimax.chat/v1/text/chatcompletion_v2')
LLM_API_KEY = os.environ.get('MINIMAX_API_KEY', '')
LLM_MODEL = os.environ.get('MINIMAX_MODEL', 'MiniMax-M2.7-highspeed')

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The handler sends the user's follow-up question plus article titles and abstracts to the remote endpoint configured by LLM_API_URL. While the network call is visible in code, there is no confirmation prompt or user-facing disclosure here that their content will be transmitted to a third-party service.

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

python
def notify_user(message):
    """发送飞书消息"""
    subprocess.run(
        [NOTIFY_SCRIPT, '-t', '综述追问回复', '-m', message],
        shell=False
    )

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

Medium
Category
Data Flow
Confidence
93% confidence
Finding

The executable path for subprocess.run comes from the NOTIFY_PATH environment variable, so anyone able to influence the runtime environment can cause the script to execute an arbitrary program. Because this handler may run with the privileges of the hosting agent/service, that becomes a code-execution primitive rather than a harmless configuration choice.

Content

Scanner excerpt · scripts/pubmed_followup_handler.py (reported line 235)May include surrounding context.

python
def notify_user(message):
    """发送飞书消息"""
    subprocess.run(
        [NOTIFY_SCRIPT, '-t', '综述追问回复', '-m', message],
        shell=False
    )

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill includes capability to invoke an external notification executable selected by environment-controlled path, which expands it from PubMed intent handling into local program execution. In an agent setting, unnecessary execution capabilities increase attack surface and can be abused for lateral actions unrelated to the stated purpose.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The full user message is transmitted to an external LLM service for intent recognition without any visible consent, minimization, or redaction. Users may include medical, personal, or confidential research content, making this a meaningful privacy and data-handling issue in the skill context.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.