Back to skill

Security audit

deepevidence循证医学AI助手

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent DeepEvidence API helper that sends clinical questions to a disclosed external service, with no hidden persistence or local data harvesting, though users should avoid sending identifiable patient data.

Install only if you trust DeepEvidence and are authorized to send the intended clinical content to that service. Keep the API key in the environment, avoid PHI/PII unless proper consent and compliance controls are in place, and consider hardening or wrapping the helper to reject cross-origin redirects for authenticated requests.

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 (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/chat.py:107
Finding

Bearer Credential and Clinical Data Exposure Through Unrestricted Redirect Handling

Content
View full analysis
urllib_request.Request: payload = json.dumps(body, ensure_ascii=False).encode("utf-8") return urllib_request.Request( CHAT_COMPLETIONS_URL, data=payload, headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", "Accept": "application/json, text/event-stream", }, method="POST", ) ``` The authenticated request is subsequently passed to `urlopen`, which uses Python's default redirect handling: ```python def call_api(body: dict, *, timeout: int = DEFAULT_TIMEOUT_SECONDS) -> Tuple[dict, Optional[str], float]: api_key = require_api_key() request = make_request(body, api_key) started = time.monotonic() try: with urllib_request.urlopen(request, timeout=timeout) as response: payload, request_id = load_json_response(response) ``` The streaming path has the same behavior: ```python def call_stream(body: dict, *, timeout: int = DEFAULT_TIMEOUT_SECONDS) -> Tuple[Optional[str], float]: api_key = require_api_key() request = make_request(body, api_key) started = time.monotonic() try: with urllib_request.urlopen(request, timeout=timeout) as response: request_id = request_id_from_headers(response.headers) raw = response.read() ``` ### Technical Analysis The helper correctly targets a fixed HTTPS endpoint and the transmission of the query and API credential is necessary for the declared API-backed functionality. However, `urllib.request.urlopen` installs default redirect processing, while the implementation does not explicitly reject re ...[truncated 2688 chars]
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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (14)

Tainted flow: 'request' from os.environ.get (line 202, 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/chat.py (reported line 158)May include surrounding context.

python
request = make_request(body, api_key)
    started = time.monotonic()
    try:
        with urllib_request.urlopen(request, timeout=timeout) as response:
            payload, request_id = load_json_response(response)
    except urllib_error.HTTPError as exc:
        request_id = request_id_from_headers(exc.headers)

Tainted flow: 'request' from os.environ.get (line 202, 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/chat.py (reported line 205)May include surrounding context.

python
request = make_request(body, api_key)
    started = time.monotonic()
    try:
        with urllib_request.urlopen(request, timeout=timeout) as response:
            payload, request_id = load_json_response(response)
    except urllib_error.HTTPError as exc:
        request_id = request_id_from_headers(exc.headers)

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

python
def print_usage(usage, *, prefix: str = "") -> None:
    if not isinstance(usage, dict):
        return
    prompt = usage.get("prompt_tokens")
    completion = usage.get("completion_tokens")
    total = usage.get("total_tokens")

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill invokes environment variables, network access, and shell execution but does not declare an explicit tool/permission scope. That creates an authorization gap where a host agent may grant broader capabilities than intended, increasing the chance of unintended outbound requests, secret access, or command execution during skill use.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
## Hard Rules

- Use `DEEPEVIDENCE_API_KEY` only from environment variables; never ask users to paste keys into chat.
- Do not print, log, screenshot, commit, or package API keys.
- Use `DEEPEVIDENCE_USER_ID` or `--user` only for stable opaque non-PII identifiers.
- Preserve citation markers returned by DeepEvidence; do not renumber, remove, reorder, or invent citations.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The integration examples send prompt content directly to a third-party clinical API but do not explicitly warn that user-entered data may leave the local system and be processed externally. In a medical context, prompts may contain sensitive health information, so omission of a privacy/data-disclosure warning can lead developers to unknowingly transmit regulated or confidential data.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
82% confidence
Finding

The curl example shows raw prompt submission to an external endpoint, which is an external data transfer pattern. While normal for API integration docs, it becomes security-relevant here because the service is for clinical questions and may be used with sensitive medical information, yet the example lacks an explicit privacy warning or safe-handling guidance.

Content

Scanner excerpt · references/integration.md (reported line 5)May include surrounding context.

Use this reference when the user asks how to integrate DeepEvidence into an application or wants curl, Python, or Node examples. These examples use direct HTTP and do not require an SDK.

Curl

bash
curl https://deepevid.medsci.cn/api/v1/chat/completions \

External Transmission

Medium
Category
Data Exfiltration
Confidence
84% confidence
Finding

The Node.js example performs direct transmission of user prompt content to an external API endpoint. In this skill's medical-evidence context, user prompts can easily contain sensitive patient or clinical data, so external transmission without an explicit disclosure/consent warning increases privacy and compliance risk.

Content

Scanner excerpt · references/integration.md (reported line 54)May include surrounding context.

Node.js

javascript
const resp = await fetch("https://deepevid.medsci.cn/api/v1/chat/completions", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.DEEPEVIDENCE_API_KEY}`,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The helper sends medical questions and optional image URLs to a third-party remote API, which may include highly sensitive health information or identifiers. In a clinical context, silent transmission of such data can create privacy, compliance, and data-governance risk if callers are not clearly informed and no minimization or validation is enforced.

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 · tests/test_chat.py (reported line 111)May include surrounding context.

python
self.assertEqual(json.loads(request.data.decode("utf-8"))["stream"], False)

    def test_missing_api_key_returns_stable_config_error(self):
        result = subprocess.run(
            [
                "env",
                "-u",

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The example query is written in Chinese, which implies a specific language/locale in the skill's usage guidance. The file does not state that language choice is optional or that this example is region-specific, so it can conflict with a policy requiring user language preference or opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The example prompt is written in Chinese and the file does not indicate that the skill is intentionally China- or Chinese-language-specific, nor does it offer alternative language examples. This can be read as imposing a language preference without user opt-in, which conflicts with the stated policy for locale/language handling.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The Python example uses a Chinese-language prompt and the document does not state that only Chinese-language usage is intended. Without an opt-in or justification, this appears to enforce a language choice in example usage.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The Node.js example includes a Chinese-language prompt while the surrounding documentation does not provide user language choice or explain a locale restriction. This creates a natural-language policy concern around implicit language enforcement.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
tests/test_chat.py:18