Back to skill

Security audit

Health Assistant

Security checks for vulnerabilities and agentic risk

Overview

This health assistant is purpose-aligned but handles sensitive health data with inconsistent privacy claims and broad setup behavior, so users should review it carefully before installing.

Install only if you are comfortable linking Garmin and Google/NotebookLM, sending detailed wearable health metrics and health concerns to an external AI service, and retaining local health history/log files. Review the dependency installation path, disable or adjust the daily cron if undesired, and do not rely on the current reset command to remove all local health data.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (5)

T08 · Insecure Dependencies

Error
Location
requirements.txt:1
Finding
Automatic Installation of Unpinned Third-Party Dependencies<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1-2`, `install.sh:22-36`, `src/env_checker.py:35-43` **Vulnerability Type**: Supply-chain exposure through mutable dependency resolution **Risk Level**: High ### Vulnerable Code `requirements.txt:1-2`: ```text garth>=0.1.0 notebooklm-py>=0.3.0 ``` `install.sh:22-36`: ```bash pip install --upgrade pip if [ -f "requirements.txt" ]; then pip install -r requirements.txt else # 至少安装 garth pip install garth fi # 3. 检查并安装 notebooklm-py 及其依赖 echo "📦 安装 notebooklm-py 及浏览器驱动..." pip install "notebooklm-py[browser]" # 4. 自动下载 Playwright 所需的 Chromium 浏览器 echo "🌐 正在下载 Chromium 浏览器内核 (用于 AI 登录)..." python3 -m playwright install chromium ``` `src/env_checker.py:35-43`: ```python @staticmethod def run_install(): """执行安装脚本并返回结果""" try: # 使用 sys.executable 确保在同一个 python 环境下安装 print("Installing dependencies...") subprocess.check_call([sys.executable, "-m", "pip", "install", "notebooklm-py[browser]"]) print("Downloading browser core...") subprocess.check_call([sys.executable, "-m", "playwright", "install", "chromium"]) ``` ### Technical Analysis The application installs packages using lower-bound version constraints rather than exact, verified versions. It also downloads the current Playwright Chromium build without an application-controlled checksum or artifact lock. Python package installation can execute package build and installation logic. Consequently, the effective code installed by this Skill may differ from the code reviewed during the audit. The runtime setup flow makes this especially significant because a user can trigger package installation by replying affirmatively to the interactive setup prompt. This finding does not establish that the named packages are malicious. The vulnerability is that the Skill has no reproducible dependency lock, hash verification, or upper version boundary to protect it from a compromise ...[truncated 1207 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace lower-bound constraints with exact, reviewed versions for direct and transitive dependencies. 2. Generate a lockfile containing hashes, such as a `pip-tools` requirements file with `--generate-hashes`. 3. Install with hash enforcement: ```bash python -m pip install --require-hashes -r requirements.lock ``` 4. Pin the Playwright package and corresponding browser revision, and verify downloaded artifacts through a trusted integrity mechanism. 5. Avoid installing packages from a chat-triggered runtime path. Perform dependency installation during a separate, explicit administrative deployment stage. 6. Disable source builds where practical and accept only reviewed binary artifacts. 7. Add automated dependency scanning and a controlled upgrade process that reviews release changes before modifying the lockfile. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/main.py:22
Finding
Sensitive Health History and Full Reports May Be Created with Permissive File Permissions<![CDATA[ ## Vulnerability Details **File Location**: `src/main.py:22-30`, `src/main.py:43-54`, `src/main.py:108-109` **Vulnerability Type**: Inadequate access control for locally stored health information **Risk Level**: Medium ### Vulnerable Code `src/main.py:22-30`: ```python LOG_DIR = Path.home() / ".openclaw" / "logs" LOG_DIR.mkdir(parents=True, exist_ok=True) logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler(LOG_DIR / "health-assistant.log"), logging.StreamHandler(sys.stdout) ] ) ``` `src/main.py:43-54`: ```python def save_history(records): """保存历史记录""" try: CONFIG_DIR.mkdir(parents=True, exist_ok=True) with open(HISTORY_FILE, 'w', encoding='utf-8') as f: json.dump({ "version": "1.0", "records": records[-30:], # 只保留最近30天 "metadata": {"last_updated": datetime.now().isoformat()} }, f, ensure_ascii=False, indent=2) logger.info(f"历史记录已保存,共 {len(records)} 条") ``` `src/main.py:108-109`: ```python logger.info(f"\n{final_report}") return final_report ``` ### Technical Analysis The project explicitly changes `config.json` to mode `0600`, but it does not apply equivalent protection to `history.json` or `health-assistant.log`. The resulting permissions therefore depend on the process umask and any pre-existing file permissions. `history.json` stores up to 30 days of sleep, HRV, activity, stress, intensity, and body-battery data. The log receives the complete formatted report, including biometric values and AI-generated recommendations. These records constitute sensitive health information. Directory creation also omits an explicit restrictive mode. Existing files or directories with permissive permissions are not corrected. ### Attack Path 1. The application runs under an account or service configuration with a permissive umask, or the ...[truncated 758 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create `CONFIG_DIR` and `LOG_DIR` with mode `0700`, and correct permissions on existing directories. 2. Create `history.json` and the log with mode `0600`, using atomic creation that does not temporarily expose a permissive file. 3. Write history to a mode-restricted temporary file, flush and synchronize it, then atomically replace the destination. 4. Configure a dedicated logging handler that creates files with restrictive permissions. 5. Do not log the complete report. Log only operational metadata such as the report date, success status, and a non-sensitive error identifier. 6. Define secure log rotation and retention limits. 7. On startup, verify permissions and refuse to process sensitive data when storage locations are owned by another account or are accessible to group/other users. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/setup_handler.py:111
Finding
Persistent User-Controlled Health Concerns Can Inject Instructions into the AI Prompt<![CDATA[ ## Vulnerability Details **File Location**: `src/setup_handler.py:111-138`, `src/report_generator.py:17-22`, `src/report_generator.py:64-65`, `src/prompts/base.py:8-12` **Vulnerability Type**: Persistent indirect prompt injection **Risk Level**: Medium ### Vulnerable Code `src/setup_handler.py:111-138`: ```python def _handle_concerns(self, message: str) -> str: """处理用户对健康关切的回应""" mapping = { 'A': 'Improve Sleep', 'B': 'Weight Management', 'C': 'Stress Relief', 'D': 'Boost Energy', 'E': 'Specific Condition' } selected = [] msg_upper = message.upper() for key, value in mapping.items(): if key in msg_upper: selected.append(value) # 如果没有字母匹配,且长度大于1,尝试当作自定义描述 if not selected: if 'F' in msg_upper or len(message) > 2: selected.append(message.replace('F', '').replace('f', '').strip()) if not selected: return "Sorry, I didn't quite get that. Please select an option (A-F) or explicitly tell me your primary wellness goal." # 更新配置 self.config.health_concerns = list(set(self.config.health_concerns + selected)) ``` `src/report_generator.py:17-22`: ```python def _format_concerns(self) -> str: """格式化健康关切""" concerns = self.user_config.health_concerns conditions = [c['condition'] for c in self.user_config.specific_conditions] all_concerns = list(set(concerns + conditions)) return "\n".join([f"- {c}" for c in all_concerns]) ``` `src/report_generator.py:64-65`: ```python prompt = format_base_prompt( USER_CONCERNS=self._format_concerns(), ``` `src/prompts/base.py:8-12`: ```python BASE_PROMPT = """【Role & Objective】 You are a Health Advisor with a strong background in Functional Medicine. Your task is to provide personalized, science-backed daily health recommendations based on the user's authentic wearable device data. ## User Health Concerns {USER_CONCERNS} ``` ### Technical Analysis Custom co ...[truncated 1989 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat all concern descriptions as untrusted data rather than prompt instructions. 2. Enforce a conservative maximum length and reject control sequences, markup, or instruction-like multiline content where custom free text is unnecessary. 3. Prefer a fixed allowlist of concern identifiers and map those identifiers to trusted server-side descriptions. 4. If custom text is required, serialize it as structured JSON and place it inside explicit data delimiters. 5. Add a high-priority prompt rule stating that content inside user-data sections is descriptive data and that any instructions found there must be ignored. 6. Separate trusted system instructions from user-derived content using the strongest role separation supported by the NotebookLM interface. 7. Validate generated output against an expected schema before including it in a report. 8. Apply length limits and neutralization to all other user-controlled fields that may later be inserted into prompts. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/report_generator.py:64
Finding
Privacy Documentation Conflicts with External Transmission and Identifier Retention<![CDATA[ ## Vulnerability Details **File Location**: `src/report_generator.py:64-89`, `src/report_generator.py:96-117`, `src/setup_handler.py:166-174`, `README.md:130-135`, `PRD.md:567-579` **Vulnerability Type**: Undisclosed or inaccurately described processing of sensitive health data **Risk Level**: High ### Vulnerable Code and Claims `src/report_generator.py:64-89` embeds exact health metrics in the prompt: ```python prompt = format_base_prompt( USER_CONCERNS=self._format_concerns(), HISTORY_DATA=self._format_history(history), DATE=daily_data.get('date', datetime.now().strftime('%Y-%m-%d')), SLEEP_TOTAL_HOURS=sleep.get('total_hours', 'N/A'), SLEEP_DEEP_HOURS=sleep.get('deep_hours', 'N/A'), SLEEP_DEEP_PERCENT=sleep.get('deep_percent', 'N/A'), SLEEP_LIGHT_HOURS=sleep.get('light_hours', 'N/A'), SLEEP_REM_HOURS=sleep.get('rem_hours', 'N/A'), SLEEP_SCORE=sleep.get('score', 'N/A'), STEPS_TOTAL=steps.get('total_steps', 'N/A'), STEPS_DISTANCE=steps.get('distance_km', 'N/A'), STEPS_COMPLETION=steps.get('completion_percent', 'N/A'), HRV_LAST_NIGHT=hrv.get('last_night_avg', 'N/A'), HRV_WEEKLY=hrv.get('weekly_avg', 'N/A'), HRV_STATUS=hrv.get('status', 'N/A'), BODY_BATTERY_CURRENT=bb.get('current', 'N/A'), BODY_BATTERY_MAX=bb.get('max', 'N/A'), STRESS_OVERALL=stress.get('overall', 'N/A'), STRESS_LOW=stress.get('low_duration', 'N/A'), STRESS_MEDIUM=stress.get('medium_duration', 'N/A'), STRESS_HIGH=stress.get('high_duration', 'N/A'), STRESS_REST=stress.get('rest_duration', 'N/A'), INTENSITY_MODERATE=intensity.get('moderate', 'N/A'), INTENSITY_VIGOROUS=intensity.get('vigorous', 'N/A'), INTENSITY_GOAL=intensity.get('weekly_goal', 'N/A'), ANALYSIS_MODULES=analysis_modules ) ``` `src/report_generator.py:96-117` submits the prompt through NotebookLM: ```python def call_notebooklm(self, prompt: str) -> Optional[str]: """调用 NotebookLM CLI 获取建议""" import tempfile ...[truncated 4200 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Present an explicit consent notice before the first NotebookLM submission. 2. Enumerate the external recipient, every category of submitted data, the purpose of processing, and applicable retention or account controls. 3. Replace claims of entirely local or de-identified processing with technically accurate language. 4. Offer a local-only mode that does not invoke NotebookLM. 5. Apply data minimization by aggregating or categorizing values instead of transmitting every exact metric. 6. Remove the Garmin email field because the current Garmin client does not use it. If an identifier becomes necessary, document its purpose and retention. 7. Allow users to preview the exact outbound prompt and disable individual data categories. 8. Document cross-border and third-party processing accurately rather than making unsupported GDPR, HIPAA, or data-localization assurances. 9. Establish a clear retention and deletion policy covering local files, Google/NotebookLM processing, logs, and authentication state. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/config.py:102
Finding
Reset Operation Leaves Health History and Report Logs Behind<![CDATA[ ## Vulnerability Details **File Location**: `src/config.py:102-108`, `src/main.py:22-30`, `src/main.py:32` **Vulnerability Type**: Incomplete deletion of sensitive user data **Risk Level**: Medium ### Vulnerable Code `src/config.py:102-108`: ```python def reset_config() -> bool: """重置配置(删除配置文件)""" try: if CONFIG_FILE.exists(): CONFIG_FILE.unlink() return True except Exception as e: print(f"重置配置失败: {e}") return False ``` The separate retained files are defined in `src/main.py:22-32`: ```python LOG_DIR = Path.home() / ".openclaw" / "logs" LOG_DIR.mkdir(parents=True, exist_ok=True) logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler(LOG_DIR / "health-assistant.log"), logging.StreamHandler(sys.stdout) ] ) logger = logging.getLogger("HealthAssistant") HISTORY_FILE = CONFIG_DIR / "history.json" ``` ### Technical Analysis The reset command calls `reset_config()`, which deletes only `config.json`. It does not delete `history.json` or the log containing full generated reports. This behavior conflicts with the documented claim that reset clears local histories and preferences. Following reset, a user may reasonably believe that sensitive health information has been removed even though historical biometric data and report content remain on disk. ### Attack Path 1. The application generates daily reports and stores health records in `history.json` and report content in the log. 2. The user sends the documented `reset` command to clear local information. 3. `reset_config()` deletes only `config.json`. 4. The history and log files remain in their original locations. 5. A later local reader, backup process, subsequent installation, or compromised process accesses the retained health information. ### Impact Assessment The vulnerability causes unintended retention of sensitive health hist ...[truncated 231 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define reset semantics clearly and make the default reset remove configuration, health history, and Skill-specific report logs. 2. Ask for explicit confirmation before deletion and report exactly which files were removed. 3. Close or rotate the active file handler before deleting the log so deletion behaves consistently across operating systems. 4. Handle each deletion separately and return a failure if any requested data remains. 5. Remove empty Skill-specific directories after deleting their contents. 6. Document that ordinary filesystem deletion may not erase copies retained in backups, snapshots, or external NotebookLM systems. 7. If separate reset modes are desirable, provide clearly named options such as “reset preferences” and “delete all local health data.” ]]>
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (40)

Intent-Code Divergence

High
Confidence
97% confidence
Finding
The PRD claims that personal identity information such as email is not stored, but the onboarding flow requires collecting a Garmin account email and indicates local storage of device credentials. This inconsistency can lead to undeclared storage of personal identifiers and authentication-related data, increasing privacy risk and exposing the system to compliance failures if users rely on the false statement.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The PRD asserts that all health data remains local and is not uploaded to the cloud, yet the design explicitly sends health data and user health concerns to NotebookLM, an external service. This creates a serious privacy and trust issue because sensitive biometric and health-related data leaves the local environment despite the product's stated guarantees, potentially triggering regulatory and consent problems.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
Prompting for Google and Garmin authentication, installing NotebookLM/Playwright, and collecting account email and preferences locally are significant behaviors not adequately reflected by the declared purpose of daily health insight generation. This undermines informed consent and creates combined privacy and account-security risk through credential handling, third-party dependencies, and local storage of sensitive setup data.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
Prompting for Google and Garmin authentication, installing NotebookLM/Playwright, and collecting account email and preferences locally are significant behaviors not adequately reflected by the declared purpose of daily health insight generation. This undermines informed consent and creates combined privacy and account-security risk through credential handling, third-party dependencies, and local storage of sensitive setup data.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
Prompting for Google and Garmin authentication, installing NotebookLM/Playwright, and collecting account email and preferences locally are significant behaviors not adequately reflected by the declared purpose of daily health insight generation. This undermines informed consent and creates combined privacy and account-security risk through credential handling, third-party dependencies, and local storage of sensitive setup data.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
Prompting for Google and Garmin authentication, installing NotebookLM/Playwright, and collecting account email and preferences locally are significant behaviors not adequately reflected by the declared purpose of daily health insight generation. This undermines informed consent and creates combined privacy and account-security risk through credential handling, third-party dependencies, and local storage of sensitive setup data.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
Prompting for Google and Garmin authentication, installing NotebookLM/Playwright, and collecting account email and preferences locally are significant behaviors not adequately reflected by the declared purpose of daily health insight generation. This undermines informed consent and creates combined privacy and account-security risk through credential handling, third-party dependencies, and local storage of sensitive setup data.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
- Vigorous: {INTENSITY_VIGOROUS} mins
- Weekly Goal: {INTENSITY_GOAL} mins

## Research & Output Directives

Please analyze the data above and output today's health suggestions.
**CRITICAL INSTRUCTION: You MUST write the entire analysis and response in English.**
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
ANALYSIS_MODULES=analysis_modules
        )
        
        return prompt

    def call_notebooklm(self, prompt: str) -> Optional[str]:
        """调用 NotebookLM CLI 获取建议"""
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
ANALYSIS_MODULES=analysis_modules
        )
        
        return prompt

    def call_notebooklm(self, prompt: str) -> Optional[str]:
        """调用 NotebookLM CLI 获取建议"""
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
This markdown file presents all user-facing instructions, prompts, and examples exclusively in Chinese, including onboarding dialogue and review instructions. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is explicitly justified, which is not stated here.

Intent-Code Divergence

Medium
Confidence
87% confidence
Finding
At L043 the documentation states the assistant 'only requests read permissions,' which conveys a read-only posture. However, L135 explicitly says users can say `reset` to clear local histories and preferences, which is a write/delete side effect and contradicts the earlier claim rather than merely omitting detail.

Intent-Code Divergence

Medium
Confidence
93% confidence
Finding
The README makes strong privacy assurances about no third-party data transfer, but the skill explicitly relies on Google NotebookLM for analysis. In a health-data context, this can mislead users about where sensitive biometric information is sent and processed, undermining informed consent and increasing privacy/compliance risk if users share data assuming it stays local.

Lp3

Medium
Category
MCP Least Privilege
Confidence
82% confidence
Finding
The skill declares executable behavior via cron and command usage, and its documented dependencies imply shell execution, local credential storage, and filesystem interaction, yet it defines no explicit tool scope or permissions boundary. That creates unnecessary ambiguity around what the skill may access and makes review, sandboxing, and user consent weaker, especially for a health-focused skill handling sensitive data.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The skill description does not clearly warn that sensitive health and biometric data may be synced automatically on a daily schedule. For a health assistant, missing notice around automated collection and processing weakens informed consent and increases the likelihood of unintended privacy exposure.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill notes use of a messaging plugin for Telegram, Discord, WeChat, or Feishu, but the description omits a clear warning that generated health reports may be transmitted to third-party platforms. In this context, that omission is especially dangerous because medical-adjacent summaries and biometric insights may leave the local environment and be subject to weaker privacy controls on external services.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The final user-facing instruction tells the user to send the Chinese phrase '生成健康报告' to use the feature. This imposes a specific language for invocation and there is no indication elsewhere in the file that alternative languages are supported or that the user can opt in to this locale constraint.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The default preference sets the timezone to "Asia/Shanghai", which embeds a specific locale choice directly into the skill behavior. Under the policy, forcing a language or locale without user opt-in is a natural-language policy concern unless the constraint is clearly documented and justified as region-specific.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The file's core behavior is not health-data analysis but setup for NotebookLM, Playwright, and local session detection, which is materially inconsistent with the skill description. This context makes the code more dangerous because users expecting a benign health coach may unknowingly run software that prepares unrelated automation and leverages existing local authentication state.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The code probes for a NotebookLM session file in the user's home directory, indicating awareness of and interest in an unrelated authenticated session. In the context of a health assistant, checking for a separate service's login state is suspicious because it can facilitate unauthorized use of an existing session or silent access to data outside the skill's stated scope.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The environment checker installs Playwright and Chromium even though the skill is presented as a Garmin and health-data analysis assistant. This mismatch between declared purpose and implementation is dangerous because it introduces unnecessary browser automation capability, which increases system risk and may support unrelated data access or automation.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
try:
            # 使用 sys.executable 确保在同一个 python 环境下安装
            print("Installing dependencies...")
            subprocess.check_call([sys.executable, "-m", "pip", "install", "notebooklm-py[browser]"])
            
            print("Downloading browser core...")
            subprocess.check_call([sys.executable, "-m", "playwright", "install", "chromium"])
Confidence
88% confidence
Finding
This code executes package installation at runtime via pip, which causes the skill to modify the host environment and fetch code from external package sources. Even though the command arguments are hardcoded and not shell-injected, it still creates a supply-chain and unexpected-code-execution risk, especially in an agent skill that users may invoke without expecting system changes.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
subprocess.check_call([sys.executable, "-m", "pip", "install", "notebooklm-py[browser]"])
            
            print("Downloading browser core...")
            subprocess.check_call([sys.executable, "-m", "playwright", "install", "chromium"])
            
            return True, "Installation successful"
        except Exception as e:
Confidence
84% confidence
Finding
This subprocess downloads and installs a Chromium browser runtime onto the host system. Installing browser automation components at runtime expands attack surface, changes the local environment, and can enable later automated browsing actions not obviously related to the advertised health-coaching purpose.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
This client retrieves highly sensitive biometric and sleep data from Garmin over the network, but the code provides no user-facing notice, consent flow, or explanation of how that data will be accessed, processed, or stored. In a health-assistant context, silent collection of personal health data increases privacy and compliance risk because users may not understand the scope of access or the sensitivity of the information being handled.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The file’s natural-language strings and descriptions indicate the skill is intended to operate in Chinese, including command phrases and user-facing help text, but there is no opt-in or documented language selection. This can violate language/locale policy when users are not given a choice or the locale restriction is not justified.

Static analysis

No suspicious patterns detected.