Back to skill

Security audit

Medical Record Structurer

Security checks for vulnerabilities and agentic risk

Overview

The skill does medical-record structuring, but it also ships an unbounded self-evolution daemon and makes overstated privacy claims around sensitive medical data.

Review this package carefully before installing. Do not run the auto-evolution daemon, avoid processing real PHI unless you have your own privacy controls, and treat the advertised encryption, hashing, audit logging, and no-storage claims as unsupported by the inspected code paths.

Vulnerability Patterns
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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
Findings (5)

T06 · System Persistence

Error
Location
auto-evolve-daemon.sh:10
Finding
Indefinite Background Daemon Repeatedly Executes Self-Modifying Code<![CDATA[ ## Vulnerability Details **File Location**: `auto-evolve-daemon.sh:10-22` **Vulnerability Type**: Indefinite background execution and autonomous code modification **Risk Level**: High ### Vulnerable Code ```bash while true; do echo "" >> $LOG_FILE echo "[$(date)] Running self-evolution..." >> $LOG_FILE cd $SKILL_PATH python3 scripts/self_evolve.py >> $LOG_FILE 2>&1 echo "[$(date)] Evolution cycle complete. Sleeping 30 minutes..." >> $LOG_FILE # Run another evolution cycle every 30 minutes sleep 1800 done ``` The invoked evolution engine writes directly to executable code: ```python if content != original: with open(script_path, 'w', encoding='utf-8') as f: f.write(content) ``` It also rewrites the Skill definition: ```python with open(skill_md, 'w', encoding='utf-8') as f: f.write(content) ``` ### Technical Analysis The daemon runs indefinitely and invokes `scripts/self_evolve.py` every 30 minutes. That module can rewrite `scripts/process_record.py`, `SKILL.md`, generated support modules, changelogs, and evolution logs. Medical-record structuring does not require a perpetual background loop or autonomous modification of reviewed executable files. The implementation has no integrity verification, trusted update source, file locking, rollback mechanism, change approval, or limit on the number of cycles. The repository does not contain an automatic startup-service or cron installer, so cross-reboot persistence is not established by the reviewed code alone. Nevertheless, once manually launched or launched by an external supervisor, the script remains active indefinitely and continually mutates the installed Skill. ### Attack Path 1. A user, deployment script, or external process launches `auto-evolve-daemon.sh`. 2. The script enters an unbounded `while true` loop. 3. Every 30 minutes, it runs `scripts/self_evolve.py`. 4. The evolution engine rewrites executable and instruction files in ...[truncated 781 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `auto-evolve-daemon.sh` from the distributed Skill. 2. Remove all runtime mutation of executable files and `SKILL.md`. 3. Distribute updates as reviewed, immutable, versioned releases. 4. Sign release artifacts and verify signatures or checksums before installation. 5. If maintenance tooling must remain: - Require explicit manual invocation. - Operate on a temporary copy. - Generate a reviewable patch rather than overwriting files. - Require user approval before applying changes. - Implement locking, rollback, and bounded execution. 6. Run the medical parser with write access limited to a dedicated data directory, not its own executable directory. ]]>

T07 · Tool Hijacking and Spoofing

Error
Location
scripts/self_evolve.py:123
Finding
Non-Idempotent Self-Modification Causes Progressive Source Corruption<![CDATA[ ## Vulnerability Details **File Location**: `scripts/self_evolve.py:123-149` **Vulnerability Type**: Unsafe mutation of executable Skill code **Risk Level**: High ### Vulnerable Code ```python def _enhance_core_script(self) -> List[str]: """Enhance the core script.""" changes = [] script_path = self.skill_path / "scripts" / "process_record.py" if not script_path.exists(): return changes with open(script_path, 'r', encoding='utf-8') as f: content = f.read() original = content # Add performance optimization if "@lru_cache" not in content: # Add cache support content = content.replace( "import json", "import json\nfrom functools import lru_cache" ) changes.append("Add LRU cache support") # Add data validation if "validate" not in content.lower(): changes.append("Enhance data validation") if content != original: with open(script_path, 'w', encoding='utf-8') as f: f.write(content) return changes ``` The resulting `scripts/process_record.py` contains hundreds of repeated imports such as: ```python from functools import lru_cache from functools import lru_cache from functools import lru_cache ``` The bundled `evolution-log.json` records repeated evolution cycles at approximately 30-minute intervals. ### Technical Analysis The mutation condition checks whether the source contains the decorator text `@lru_cache`, but the mutation only inserts an import statement. Because the decorator is never added, the condition remains true on every cycle. Each execution therefore replaces every matching `import json` occurrence with another import block. This is non-idempotent and progressively enlarges and corrupts the source file. The issue also undermines review integrity: the executable file used by later calls is modified after installation without a trusted update or approval pr ...[truncated 1031 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Delete the self-modifying feature and restore `process_record.py` from a clean, reviewed source. 2. Remove all duplicate imports and regenerate the package. 3. Treat installed Skill code as immutable at runtime. 4. Use source-control patches and reviewed releases for changes. 5. If a code transformation is retained, make it idempotent and test the resulting abstract syntax tree. 6. Add automated tests that execute the transformation repeatedly and verify that the second execution produces no changes. 7. Add package-integrity checks that detect unexpected changes to executable files. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/process_record.py:746
Finding
Complete Medical Records Can Be Written to Disk as Unencrypted Plaintext<![CDATA[ ## Vulnerability Details **File Location**: `scripts/process_record.py:746-753` and `scripts/process_record.py:1017-1021` **Vulnerability Type**: Plaintext persistence of protected health information **Risk Level**: High ### Vulnerable Code The complete original medical note is included in every structured record: ```python "metadata": { "source_text": text, "processed_at": datetime.now().isoformat(), "processor_version": VERSION, "language": self.lang, "demo_mode": self.demo_mode } ``` The complete result can then be written directly to an arbitrary output path: ```python output_json = json.dumps(result, ensure_ascii=False, indent=2) if args.output: with open(args.output, 'w', encoding='utf-8') as f: f.write(output_json) print(f"Result saved to: {args.output}") else: print(output_json) ``` The demo script uses the same unsafe behavior: ```python if args.output and 'result' in locals(): with open(args.output, 'w', encoding='utf-8') as f: json.dump(result, f, ensure_ascii=False, indent=2) ``` ### Technical Analysis Medical input can contain patient names, diagnoses, medications, examination findings, and other protected health information. The implementation copies the complete source note into `metadata.source_text`, even when the extracted fields alone would satisfy the declared structuring function. When `--output` is used, the full record is written without encryption, restrictive file permissions, retention controls, or secure deletion. The file mode is determined by the process umask and destination-directory permissions. This contradicts `SECURITY.md`, which states that medical records are never stored on disk and that sensitive data is not stored in plaintext. Documented settings such as `PHI_ENCRYPTION_KEY` and retention controls are not implemented in the reviewed processing path. ### Attack Path 1. A user processes a real medical note containing PHI. 2. `structure_record()` co ...[truncated 833 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `metadata.source_text` from output by default. 2. Provide source-text retention only as an explicit, informed opt-in. 3. Warn users before writing PHI to disk. 4. Create output files atomically with permissions restricted to the owner, such as mode `0600`. 5. Implement authenticated encryption using a properly managed encryption key. 6. Validate output paths and discourage shared or temporary public directories. 7. Implement configurable retention and verified deletion. 8. Avoid printing complete records to terminals or logs by default. 9. Update `SECURITY.md`, `README.md`, and `SKILL.md` so claims match implemented controls. 10. Perform a healthcare compliance review before production use. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/process_record.py:437
Finding
Raw User Identifiers Are Persisted and Transmitted Despite Hashing Claims<![CDATA[ ## Vulnerability Details **File Location**: `scripts/process_record.py:437-448` and `scripts/process_record.py:502-542` **Vulnerability Type**: Plaintext identifier storage and unsafe query construction **Risk Level**: Medium ### Vulnerable Code Raw identifiers are used directly as keys in a local JSON file: ```python def use_trial(self, user_id: str) -> bool: """Record a free trial usage for a user.""" 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 True ``` The raw identifier is inserted into a URL without URL encoding: ```python def check_balance(self, user_id: str) -> float: result = self._make_request( f'/api/v1/billing/balance?user_id={user_id}' ) return result.get('balance', 0.0) ``` It is also transmitted in payment payloads: ```python result = self._make_request( '/api/v1/billing/charge', method='POST', data={ 'user_id': user_id, 'skill_id': self.skill_id, 'amount': amount, } ) ``` ```python result = self._make_request( '/api/v1/billing/payment-link', method='POST', data={ 'user_id': user_id, 'amount': amount, } ) ``` ### Technical Analysis `SECURITY.md` states that the locally stored user ID is hashed, but no hashing or pseudonymization occurs. The raw identifier is stored in `~/.openclaw/skill_trial/medical-record-structurer.json` with first-use and last-use timestamps. The same identifier is transmitted to SkillPay. Although transmitting a billing identifier is related to payment functionality, the implementation does not minimize or pseudonymize it. The balance endpoint constructs a query string through direct interpolation. Reserved charac ...[truncated 1103 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace raw user IDs with keyed pseudonymous identifiers, such as an HMAC generated using a deployment-specific secret. 2. Do not use an unsalted plain hash for predictable identifiers. 3. Construct query strings with `urllib.parse.urlencode`. 4. Validate identifier length and allowed character sets. 5. Store trial state in a file created with mode `0600`. 6. Minimize timestamp retention and provide an automatic deletion mechanism. 7. Clearly disclose all identifiers sent to SkillPay. 8. Update the security policy to remove inaccurate hashing claims until pseudonymization is implemented. 9. Confirm the billing provider's retention, data-processing, and healthcare compliance terms. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/process_record.py:983
Finding
Billing API Key Can Be Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/process_record.py:983` **Vulnerability Type**: Secret exposure through process arguments **Risk Level**: Medium ### Vulnerable Code ```python parser.add_argument( '--api-key', '-k', default=BILLING_API_KEY, help='SkillPay API key' ) ``` The supplied value is subsequently used to initialize the billing client: ```python api_key = args.api_key or BILLING_API_KEY processor = MedicalRecordStructurer( api_key, demo_mode, args.language ) ``` The billing client transmits it as an authentication header: ```python headers = { 'X-API-Key': self.api_key, 'Content-Type': 'application/json', } ``` ### Technical Analysis Accepting an API credential on the command line encourages invocations such as: ```text python scripts/process_record.py --api-key SECRET ... ``` Command-line arguments can be exposed through process listings, shell history, job-control systems, monitoring agents, crash diagnostics, terminal transcripts, and automation logs. Environment variables are also not ideal for every deployment, but they generally avoid routine process-list exposure and are already the documented default. ### Attack Path 1. A user supplies the SkillPay API key through `--api-key` or `-k`. 2. The shell records the command in its history, or the operating system exposes it in process metadata. 3. Another local user, monitoring tool, support bundle, or later history reader obtains the credential. 4. The recovered key is used against the SkillPay billing API. 5. Depending on server-side authorization, the attacker may inspect billing data or initiate unauthorized charge operations. ### Impact Assessment The direct privilege obtained depends on the permissions assigned to the exposed SkillPay key. Potential impact includes: - Unauthorized billing API requests. - Fraudulent or unintended charges. - Exposure of billing balances and identifiers. - Service disruption if the creden ...[truncated 234 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `--api-key` and `-k` command-line options. 2. Load credentials from a protected secret manager or a restricted configuration source. 3. If environment variables are used, ensure they are injected by the runtime rather than exported in shared shell profiles. 4. Support reading a secret from a protected file descriptor or owner-only file. 5. Apply least-privilege scopes to billing credentials. 6. Rotate any key that may previously have been supplied on the command line. 7. Ensure errors, debug logs, crash reports, and telemetry redact authentication values. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
Findings (52)

Missing User Warnings

High
Confidence
97% confidence
Finding
The Flask API example accepts and returns medical record content over an API without any mention of transport security, authentication, authorization, logging hygiene, or data minimization. Because the payload is medical data, this omission can encourage insecure deployment patterns that expose PHI in transit or to unauthorized callers.

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 "[$(date)] Running self-evolution..." >> $LOG_FILE
    
    cd $SKILL_PATH
    python3 scripts/self_evolve.py >> $LOG_FILE 2>&1
    
    echo "[$(date)] Evolution cycle complete. Sleeping 30 minutes..." >> $LOG_FILE
Confidence
98% confidence
Finding
The script explicitly invokes a self-evolution mechanism on a perpetual schedule, which is a classic self-modification pattern. In this context, that is especially dangerous because it can continuously alter skill behavior without oversight, making malicious payload insertion, persistence, and evasion of prior review substantially easier.

Intent-Code Divergence

High
Confidence
98% confidence
Finding
The demo-mode messaging says it uses simulated/demo data and that no API key is required, but the implementation still processes the real user-supplied medical text. In a healthcare context, this is deceptive and can cause users to enter real PHI under the false assumption that the data is synthetic or specially protected.

Missing User Warnings

High
Confidence
97% confidence
Finding
The tool prints structured records, including source_text and extracted medical details, to stdout and can write them to output files without any warning or redaction. This can expose protected health information through terminal logs, shell history capture, redirected output, shared systems, or insecure files.

Intent-Code Divergence

High
Confidence
95% confidence
Finding
The module presents itself as part of a medical record structuring skill, but its real behavior is to inspect, rewrite, and generate files in the skill repository. This mismatch is dangerous because it obscures high-risk self-modifying behavior behind an unrelated medical context, reducing operator scrutiny and making unintended code changes more likely to be trusted.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
This code autonomously edits project files, creates new modules, updates metadata, and persists logs, despite belonging to a skill whose apparent purpose is medical record processing. In this context, self-modification is unjustified and expands the attack surface substantially: compromised logic, accidental corruption, or stealthy persistence could be introduced without review.

External Script Fetching

High
Category
Supply Chain
Content
echo "Size: $(ls -lh $SKILL_PATH | awk '{print $5}')"
echo ""

# Upload using curl
curl -X POST "$CLAWHUB_API" \
    -H "Authorization: Bearer $API_TOKEN" \
    -H "Content-Type: multipart/form-data" \
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The examples process highly sensitive medical record data, including names, ages, diagnoses, and treatments, but provide no privacy, consent, de-identification, or secure-handling guidance. In a medical-record structuring skill, omission of such warnings can lead users to test with real PHI and handle it insecurely, increasing risk of privacy breaches and regulatory noncompliance.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The document explicitly organizes usage around 'Chinese Medical Records' and 'English Medical Records', which signals a fixed language scope. Because no user choice, opt-in, or justification for the locale restriction is provided in the natural-language description, this may violate the language/locale policy.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The batch example explicitly writes structured medical record results to a local JSON file, which can contain sensitive patient information, without warning about encryption, access controls, or retention. This creates a straightforward path to accidental PHI exposure through local disk persistence, backups, shared workstations, or source-control mistakes.

Session Persistence

Medium
Category
Rogue Agent
Content
- Include patient demographics

### 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
```

### Slow processing
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
```

### Slow processing
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 encourages users to process medical records, including their own data, without any warning that the content may contain protected health information. In a healthcare context, omission of privacy guidance increases the chance users will expose sensitive patient data insecurely during testing or routine use.

Intent-Code Divergence

Medium
Confidence
93% confidence
Finding
The documentation claims the skill has no external dependencies and uses only the Python standard library, yet later describes integration with an external paid service requiring API credentials. This discrepancy can mislead users into believing medical data stays local when the skill may depend on or communicate with a third-party service, creating supply-chain, privacy, and trust risks.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The API-key setup section introduces a third-party service but does not warn that sensitive medical content may be transmitted outside the local environment. Because the skill processes medical records, failing to disclose potential external transmission materially raises privacy, confidentiality, and regulatory 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
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.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The usage example and printed output strings are presented in Chinese, including patient data and user-facing messages, but the document does not state that the skill is China-specific or that users can choose their preferred language. This can violate language/locale policy because it implicitly forces a specific language experience without opt-in or justification.

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
95% confidence
Finding
The skill advertises processing medical records, file input, OCR, and speech-to-text, but does not clearly warn near the main description that patient data may be read from local files and transmitted to third-party OCR/STT providers during normal use. Because the content is explicitly PHI/medical data, inadequate disclosure materially increases the risk of unauthorized disclosure, unsafe deployment, and noncompliant handling of sensitive records.

Intent-Code Divergence

Medium
Confidence
91% confidence
Finding
The documentation makes strong PHI/privacy and compliance assurances such as encryption, access control, audit logging, and HIPAA-oriented handling, while the same file only shows these protections as optional or configurable and provides no evidence they are enforced. In a healthcare skill processing medical records, overstated security claims can cause users to submit sensitive patient data under false assumptions, creating substantial privacy, regulatory, and trust risk.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The file header identifies the script as 'Medical Record Structurer - Auto-Evolution Daemon', implying it supports a medical-record-structuring skill, but the operative behavior is an infinite loop that repeatedly invokes `scripts/self_evolve.py`. This is an active contradiction in intent labeling because the documented purpose suggests domain processing, while the code is dedicated to autonomous self-modification/evolution orchestration.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
This daemon repeatedly executes a self-evolution script in an infinite loop without any approval gate, change control, or user-visible warning. In a skill context, autonomous code evolution can introduce unreviewed behavior over time, enabling persistence, privilege abuse, or silent drift into unsafe functionality.

Static analysis

No suspicious patterns detected.