Back to skill

Security audit

Drug Safety Review

Security checks for vulnerabilities and agentic risk

Overview

This healthcare skill needs review because it can treat simulated medication-safety output as a successful result and its local tracking and self-evolution artifacts are not clearly or accurately disclosed.

Install only after reviewing the clinical and privacy limitations. Do not rely on this skill for real patient decisions unless demo mode is explicitly disabled, credential/free-trial behavior is fixed, the drug database coverage is validated, and local trial/output files are protected. Treat user IDs as potentially identifying health-usage metadata.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/safety_review.py:324
Finding
Implicit Demo Mode Returns Simulated Results for Real Medication Input## Vulnerability Details **File Location**: `scripts/safety_review.py:324-326`, `scripts/safety_review.py:481-482`, and `scripts/safety_review.py:529-535` **Vulnerability Type**: Unsafe fail-open behavior and clinical output integrity failure **Risk Level**: High ### Vulnerable Code ```python def __init__(self, demo_mode: bool = False): self.billing = SkillPayBilling() self.trial = TrialManager("drug-safety-review") self.demo_mode = demo_mode or not API_KEY ``` ```python def review(self, medications: List[Dict], allergies: List[Dict] = None, patient_data: Dict = None) -> Dict[str, Any]: if self.demo_mode: return DemoDataGenerator.generate_demo_review() ``` ```python def process(self, medications: List[Dict], allergies: List[Dict] = None, patient_data: Dict = None, user_id: str = "") -> Dict[str, Any]: if self.demo_mode: print(self.get_message('demo_mode_active'), file=sys.stderr) return { 'success': True, 'demo_mode': True, 'trial_mode': False, 'trial_remaining': 0, 'balance': None, 'review': self.review(medications, allergies, patient_data) } ``` ### Technical Analysis The reviewer automatically enables demo mode whenever the module-level `SKILLPAY_API_KEY` value is absent. Demo mode is therefore not restricted to an explicit user request such as `--demo`. Once enabled, `review()` ignores the supplied medication, allergy, and patient data and calls `DemoDataGenerator.generate_demo_review()`. The result is nevertheless returned with `"success": True`. This is a fail-open design: missing billing configuration changes the semantic meaning of the operation from a patient-specific review to a simulated review rather than stopping execution with a clear error. The behavior conflicts with documentation that advertises real free-trial reviews without an API key. A caller following that documentation can r ...[truncated 2233 chars]
Remediation
## Remediation Suggestions 1. Require explicit activation of demo mode. Replace implicit fallback behavior with logic equivalent to: ```python self.demo_mode = demo_mode ``` 2. When credentials are unavailable outside explicit demo mode, either perform the advertised local free-trial analysis or return a clear configuration error. 3. Never return `"success": True` for a simulated review submitted through a normal patient-review workflow. 4. Reject real medication or patient input in demo mode, or require an explicit acknowledgement that the output is simulated and unrelated to the input. 5. Add a prominent machine-readable result type, such as `"result_type": "simulated_demo"`, in addition to human-readable warnings. 6. Add automated tests confirming that changing medication, allergy, condition, and renal-function inputs changes real review output. 7. Add integration tests covering missing credentials, explicit demo mode, free-trial mode, and paid mode. 8. Correct the documented database and interaction coverage so it accurately reflects the implemented data. 9. Subject clinical rules and recommendations to qualified clinical validation before production use.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/safety_review.py:58
Finding
Raw User Identifiers Are Persisted in Plaintext Contrary to the Security Policy## Vulnerability Details **File Location**: `scripts/safety_review.py:58-93` **Vulnerability Type**: Plaintext sensitive identifier storage and insecure file permissions **Risk Level**: Medium ### Vulnerable Code ```python class TrialManager: def __init__(self, skill_name: str): self.skill_name = skill_name self.trial_dir = os.path.expanduser("~/.openclaw/skill_trial") self.trial_file = os.path.join(self.trial_dir, f"{skill_name}.json") self.max_free_calls = 10 os.makedirs(self.trial_dir, exist_ok=True) def _load_trial_data(self) -> Dict[str, Any]: if os.path.exists(self.trial_file): try: with open(self.trial_file, 'r', encoding='utf-8') as f: return json.load(f) except (json.JSONDecodeError, IOError): return {} return {} def _save_trial_data(self, data: Dict[str, Any]): try: with open(self.trial_file, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=2) except IOError as e: print(f"Warning: Could not save trial data: {e}", file=sys.stderr) def get_trial_remaining(self, user_id: str) -> int: if not user_id: return 0 data = self._load_trial_data() user_data = data.get(user_id, {}) used_calls = user_data.get('used_calls', 0) return max(0, self.max_free_calls - used_calls) def use_trial(self, user_id: str) -> bool: if not user_id: return False data = self._load_trial_data() if user_id not in data: data[user_id] = {'used_calls': 0, 'first_use': datetime.now().isoformat()} data[user_id]['used_calls'] += 1 data[user_id]['last_use'] = datetime.now().isoformat() self._save_trial_data(data) return T ...[truncated 2570 chars]
Remediation
## Remediation Suggestions 1. Do not store raw user identifiers. Derive a pseudonymous key using an HMAC with a locally protected secret: ```python pseudonymous_id = hmac.new(secret, user_id.encode(), hashlib.sha256).hexdigest() ``` 2. Avoid a plain unsalted hash for predictable identifiers such as email addresses; use a keyed construction to resist dictionary attacks. 3. Create `~/.openclaw/skill_trial` with mode `0700`. 4. Create the trial file with mode `0600`, and verify permissions when opening an existing file. 5. Write updates to a securely created temporary file in the same directory, flush and synchronize it, then use an atomic replacement. 6. Use file locking or another concurrency-safe store to prevent lost updates and corruption. 7. Define and implement a retention period that removes inactive trial records automatically. 8. Document a deletion procedure and ensure uninstall operations remove trial state where appropriate. 9. Correct `SECURITY.md` immediately if raw identifiers remain in use; security documentation must match actual behavior. 10. Remove guidance that broadly applies mode `0755` to `~/.openclaw`, or clearly document safe permissions for sensitive subdirectories and files.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (29)

Credential Access

High
Category
Privilege Escalation
Content
3. Copy the environment variables file and configure:
```bash
cp .env.example .env
# Edit .env with your actual API keys
```
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
3. Copy the environment variables file and configure:
```bash
cp .env.example .env
# Edit .env with your actual API keys
```

## Environment Variables Configuration
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Self-Modification

High
Category
Rogue Agent
Content
echo "🧬 Auto-Evolution Started: $(date)" > $LOG_FILE
while true; do
    echo "[$(date)] Evolving..." >> $LOG_FILE
    cd $SKILL_PATH && python3 scripts/self_evolve.py >> $LOG_FILE 2>&1
    sleep 1800
done
Confidence
98% confidence
Finding
The daemon directly invokes a script named self_evolve.py on a recurring schedule, which strongly indicates self-modifying or self-updating behavior. In a skill environment, self-modification is especially risky because it can change future behavior outside normal review, potentially introducing persistence, bypassing trust assumptions, or pulling the system into unsafe or unauthorized states over time.

Intent-Code Divergence

Medium
Confidence
93% confidence
Finding
The FAQ makes a strong security/privacy claim that no medication data is ever stored or transmitted, yet other sections describe online billing, balance checks, top-up URLs, and external support channels. Even if only billing metadata is transmitted, the absolute wording is misleading and could cause users to submit sensitive health information under false assumptions about data flows.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The document claims the tool works completely offline and has no external dependencies, but later describes network-based billing via SkillPay and external endpoints for support. This inconsistency can mislead operators in regulated or air-gapped environments into deploying the tool where network isolation is assumed, creating compliance and operational risk.

Session Persistence

Medium
Category
Rogue Agent
Content
```

### Permission denied errors
Create the required directory:
```bash
mkdir -p ~/.openclaw/skill_trial
chmod 755 ~/.openclaw
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
Create the required directory:
```bash
mkdir -p ~/.openclaw/skill_trial
chmod 755 ~/.openclaw
```

### Drug not recognized
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
Create the required directory:
```bash
mkdir -p ~/.openclaw/skill_trial
chmod 755 ~/.openclaw
```

### Drug not recognized
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The quick-start examples explicitly encourage users to submit medications, allergies, and patient data, which are sensitive health data, without any nearby warning about privacy, retention, transmission, or whether the review runs locally versus through a remote service. In a medical context, this can lead users to disclose protected or highly sensitive information under unsafe assumptions, increasing privacy and compliance risk.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The documentation recommends saving the safety report to a file but does not warn that the output may contain sensitive medical information, including medications, allergies, conditions, and risk assessments. Users may store these reports insecurely, commit them to source control, or share them unintentionally, causing data exposure.

Session Persistence

Medium
Category
Rogue Agent
Content
### Permission Denied
If you see permission errors for `~/.openclaw/`:
```bash
mkdir -p ~/.openclaw/skill_trial
chmod 755 ~/.openclaw
```
Confidence
86% confidence
Finding
The troubleshooting guidance creates a persistent directory under the user's home directory for trial or skill state without explaining what data may be stored there, how long it persists, or any privacy implications. In a health-related skill, persistent local state can expose usage history, identifiers, or derived medical outputs to other local processes or users if not properly controlled.

Session Persistence

Medium
Category
Rogue Agent
Content
- **Retention**: Until user deletes the file or uninstalls the skill

### File System Access
- **Purpose**: Read/write trial tracking data
- **Scope**: User's home directory only (`~/.openclaw/`)
- **No access** to: System files, other applications' data, sensitive directories
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The quick-start and review examples encourage submission of highly sensitive health-related data including medications, allergies, age, weight, and renal function, but the markdown does not clearly warn users that this data may be processed remotely or transmitted to external services. In a healthcare context, lack of transparent data-handling disclosure can cause users to expose protected or highly sensitive information without informed consent, increasing privacy, compliance, and data-governance risk.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
This script runs indefinitely and repeatedly executes a local Python program that is explicitly named for self-evolution, while silently appending output to a log file. In an agent skill context, an unattended background loop that continually triggers code changes or autonomous behavior without user approval, execution bounds, or integrity checks is dangerous because it can persistently alter the skill or environment and obscure when those actions occur.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
This reference presents extensive medication, contraindication, and interaction information without any warning that it is informational only and not a substitute for clinician, pharmacist, or poison-control judgment. In an agent setting, users or downstream components may over-trust the content for dosing, interaction, or safety decisions, increasing the risk of harmful medical advice or unsafe self-medication.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
This file provides detailed drug interaction, contraindication, allergy, and monitoring guidance without any prominent disclaimer that it is informational and not a substitute for clinician or pharmacist judgment. In a healthcare context, users may over-rely on the content as authoritative or complete, which can contribute to unsafe self-medication, missed patient-specific contraindications, or harmful treatment decisions.

Context-Inappropriate Capability

Medium
Confidence
97% confidence
Finding
This medication safety tool includes billing and payment-gating logic that is unrelated to its core clinical function. In a healthcare context, coupling access to safety review with monetization increases privacy and availability risk because users may unknowingly trigger billing flows and the skill’s behavior depends on external commercial configuration.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
The script persistently stores per-user trial usage data under the user's home directory without notice or protections. Even though it stores limited fields, the user ID plus timestamps create trackable usage records that may expose identity, behavior, or regulated workflow metadata on shared systems.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The tool writes trial usage data to a persistent file in the home directory without informing the user. In a medical-assistance context, hidden persistence is more concerning because it can reveal which users accessed a healthcare-related function and when, particularly on multi-user or managed machines.

Context-Inappropriate Capability

Medium
Confidence
98% confidence
Finding
The code performs outbound network requests to an external billing API from within a drug-safety skill. In a healthcare-related tool, unsolicited external communication expands the attack surface and creates data-governance risk, especially when users may reasonably expect the analysis to be local.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The code sends a user identifier to an external billing endpoint, and the overall skill processes medication, allergy, and patient-condition data, but there is no comment, docstring, prompt, or visible notice in this file warning that external billing/network access occurs. For a healthcare-related skill, undisclosed external transmission is a meaningful privacy concern even if only the user_id is explicitly sent here.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The reviewer initializes self.lang to 'zh' and falls back to Chinese for unsupported values, and the CLI also defaults --language to 'zh'. This forces a specific language by default rather than prompting for user preference or preserving the user's locale, which matches the language/locale policy violation category.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The script can write full review output to an arbitrary file without warning that it may contain medications, allergies, renal data, contraindications, and other sensitive medical information. In a healthcare setting, silent export to disk materially increases the risk of local data exposure, accidental sharing, backup leakage, or insecure retention.

Natural-Language Policy Violations

Low
Confidence
89% confidence
Finding
The changelog entries are written in Chinese with no indication that language choice is optional or tied to a documented regional requirement. This can violate a language/locale policy when the skill documentation implicitly enforces a specific language for users without opt-in.

Natural-Language Policy Violations

Low
Confidence
96% confidence
Finding
The example prints `剩余免费次数`, which forces a Chinese-language user-visible message in otherwise English documentation. This appears to impose a locale-specific output without user opt-in or explanation, which is a natural-language policy concern.

Static analysis

No suspicious patterns detected.