Back to skill

Security audit

Lovefromio Garmin Connect

Security checks for vulnerabilities and agentic risk

Overview

This Garmin skill is related to its stated purpose, but it handles health data and account credentials with under-disclosed and unsafe local storage practices that deserve review before installation.

Review this skill carefully before installing. It can access Garmin account data, store reusable session tokens, create recurring sync jobs, and persist sensitive health records locally. Do not pass your Garmin password on the command line; use a safer authentication flow, restrict permissions on session/cache files, avoid the 30-day dashboard/export scripts unless you understand the /tmp and remote-script risks, and pin dependencies before use.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/garmin-auth.py:49
Finding

Garmin Password Exposed Through Command-Line Arguments

Content
View full analysis
") print("Example: python3 garmin-auth.py moritz.vogt@vogges.de MyPassword123") sys.exit(1) email = sys.argv[1] password = sys.argv[2] success = setup_oauth(email, password) ``` The insecure invocation is also explicitly recommended in: ```bash python3 scripts/garmin-auth.py your-email@gmail.com your-password ``` at `README.md:18` and `SKILL.md:25`. ### Technical Analysis The authentication script requires the Garmin password as a command-line argument. Command-line arguments can be exposed through: - Shell history files. - Process inspection utilities while the command is running. - System audit and process-accounting services. - Terminal session recording. - Monitoring and endpoint-security software. - Wrapper scripts or job telemetry. The script only needs the password in memory for the authentication request; making it part of the process command line exceeds that requirement. The example also contains a real-looking email address and password pattern that should not be embedded in usage output. ### Attack Path 1. A user follows the documented authentication command and places the Garmin password directly on the command line. 2. The shell records the command in its history, or another local process reads the active process arguments. 3. An attacker with access to the user’s history, monitoring records, or local process metadata retrieves the plaintext password. 4. The attacker authenticates to Garmin using the stolen credentials. 5. The attacker can access account information and sensitive health, sleep, heart-rate, and activity data available to that Garmin account. ### Impact Assessment This issue can disclose the user’s Gar ...[truncated 359 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/garmin-sync-30days.py:569
Finding

Sensitive Health Data Written to Predictable Shared Temporary Files

Content
View full analysis
/tmp/garmin-sync.log 2>&1 ``` ### Technical Analysis The scripts write detailed health information to predictable names in the shared `/tmp` directory. The data includes sleep history, heart rate, workouts, steps, calories, timestamps, and activity names. The files are opened with ordinary `open(..., 'w')` calls. The implementation does not: - Create a private directory with mode `0700`. - Explicitly enforce file mode `0600`. - Use exclusive creation. - Reject symbolic links. - Use secure random temporary names. - Remove the files after use. The fixed names `/tmp/garmin_latest.json`, `/tmp/garmin_latest.html`, and `/tmp/garmin-cache.json` are particularly risky. On systems without sufficient t ...[truncated 1660 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/garmin-sync-30days.py:479
Finding

Stored HTML and JavaScript Injection in Generated Health Dashboard

Content
View full analysis
{w.get('date', 'N/A')[:10]} {w.get('type', 'Unknown')} {w.get('name', 'Unnamed')} {w.get('duration_minutes', 0)} min {w.get('distance_km', 0)} km {w.get('calories', 0)} cal {hr_avg}/{hr_max} bpm """ ``` The generated fragments and raw JSON are then inserted into the document: ```python html = html_template.format( start=data['period']['start'], end=data['period']['end'], timestamp=data['timestamp'], total_steps=data['summary_stats']['total_steps'], avg_steps=int(data['summary_stats']['avg_daily_steps']), total_calories=data['summary_stats']['total_calories'], active_minutes=data['summary_stats']['total_active_minutes'], avg_sleep=data['summary_stats']['avg_sleep_hours'], avg_quality=data['summary_stats']['avg_sleep_quality'], total_workouts=data['summary_stats']['total_workouts'], total_workout_minutes=data['summary_stats']['total_workout_minutes'], workout_calories=data['summary_stats']['total_workout_calories'], dates=json.dumps(dates), steps_data=json.dumps(steps_data), sleep_data=json.dumps(sleep_data), hr_data=json.dumps(hr_data), workout_types=json.dumps(workout_types), workout ...[truncated 2362 chars]
Remediation
View remediation
`, `&`, and the `` sequence. - Escape raw JSON before placing it inside a `
text
` element.
- Validate numeric fields and convert them to numeric types before rendering.
- Add a restrictive Content Security Policy that blocks inline scripts and unauthorized network destinations.
- Continue treating Garmin API content as untrusted even though it originates from an authenticated account.
]]>

T03 · Remote Payload Retrieval and Execution

Warning
Location
scripts/garmin-sync-30days.py:257
Finding

Mutable Remote JavaScript Executed When Local Dashboard Is Opened

Content
View full analysis
``` ### Technical Analysis The generated local dashboard loads JavaScript from third-party CDN URLs whenever the dashboard is opened. The referenced resources are not protected by Subresource Integrity and are not pinned to reviewed immutable artifacts. This creates a remote code execution channel within the browser: the code that executes is determined by the CDN response at viewing time rather than by the reviewed Skill package. This behavior is not necessary for Garmin synchronization and exposes the dashboard’s sensitive health information to mutable third-party code. The Tailwind URL is especially broad because it references a generic runtime CDN script. The Chart.js URL also lacks an explicit immutable version in the displayed reference. ### Attack Path 1. The user runs the 30-day sync, producing a local dashboard containing remote script references. 2. The user opens the dashboard while connected to the network. 3. The browser requests JavaScript from the configured third-party CDNs. 4. A compromised CDN account, upstream package, or delivery infrastructure returns modified JavaScript. 5. The browser executes that JavaScript as part of the local dashboard. 6. The script reads rendered health data from the document and may transmit it to a remote server. ### Impact Assessment A compromised remote asset can execute JavaScript with access to the dashboard DOM, including the user’s 30-day sleep, workout, heart-rate, calorie, and activity data. Browser sandboxing generally limits direct operating-system access, but confidentiality and integrity of the dashboard data can be lost. The effective payload can change after Skill review with ...[truncated 40 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Open-Ended Dependency Versions Allow Unreviewed Future Releases

Content
View full analysis
=0.2.38 requests>=2.28.0 python-dateutil>=2.8.2 ``` ### Technical Analysis All dependencies use open-ended minimum-version constraints. A future release satisfying these constraints may be installed without having been reviewed with this Skill. Python package installation can execute package build logic, and the installed libraries run with the permissions of the user executing the Skill. The absence of hashes also prevents `pip` from verifying that installation artifacts exactly match reviewed files. This is a supply-chain hardening weakness rather than evidence that the currently named packages are malicious. The source directly imports `garminconnect` and transitively relies on authentication behavior implemented by dependencies. The direct `requests` dependency was not observed being imported by the project scripts and should be removed if it is unnecessary. ### Attack Path 1. A dependency publisher account, package release process, or upstream distribution artifact is compromised. 2. The attacker publishes a malicious version that still satisfies the `>=` constraint. 3. A user installs or upgrades dependencies using `pip install -r requirements.txt`. 4. Pip selects the malicious future version. 5. Malicious build-time or runtime code executes with the installing user’s privileges. 6. The dependency may access the locally stored Garmin OAuth session and cached health information available to that user. ### Impact Assessment Successful supply-chain exploitation could execute code with the privileges of the user installing or running the Skill. That scope may include access to `~/.garth/session.json`, cached health data, user files, and the user’s network access. No malicious dependency was confirmed during the static au ...[truncated 70 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (33)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Writing synced health data to a local cache without declared permissions and without clearly matching the advertised sync scope is a real privacy and trust problem. Users may assume a narrower data collection model than what is actually cached, persisted, or exposed to other local processes.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

Writing synced health data to a local cache without declared permissions and without clearly matching the advertised sync scope is a real privacy and trust problem. Users may assume a narrower data collection model than what is actually cached, persisted, or exposed to other local processes.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Writing synced health data to a local cache without declared permissions and without clearly matching the advertised sync scope is a real privacy and trust problem. Users may assume a narrower data collection model than what is actually cached, persisted, or exposed to other local processes.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Writing synced health data to a local cache without declared permissions and without clearly matching the advertised sync scope is a real privacy and trust problem. Users may assume a narrower data collection model than what is actually cached, persisted, or exposed to other local processes.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

Writing synced health data to a local cache without declared permissions and without clearly matching the advertised sync scope is a real privacy and trust problem. Users may assume a narrower data collection model than what is actually cached, persisted, or exposed to other local processes.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

Writing synced health data to a local cache without declared permissions and without clearly matching the advertised sync scope is a real privacy and trust problem. Users may assume a narrower data collection model than what is actually cached, persisted, or exposed to other local processes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README promotes automatic syncing of sensitive health and fitness data to Clawdbot every 5 minutes without clearly explaining what data leaves the local system, where it is stored, or the privacy implications. In the context of health data, lack of transparent disclosure increases the risk of uninformed consent and accidental oversharing of sensitive personal information.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The README claims OAuth-based authentication, but the documented command takes a Gmail address and password on the command line, which is inconsistent with standard OAuth flows and encourages direct credential entry. This can mislead users into exposing Garmin credentials via shell history, process listings, or logs, and suggests the integration may be using a weaker login flow than advertised.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The authentication instructions tell users to provide email and password directly to a script but do not warn that command-line secrets may be exposed through shell history, terminal scrollback, job control tools, or system process inspection. Because these are account credentials tied to sensitive health data, this creates a meaningful credential-handling risk beyond normal documentation shortcomings.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The cron setup instructs users to run continuous background sync every 5 minutes without clearly warning that this will repeatedly collect and potentially transmit health telemetry on an ongoing basis. In a skill designed to integrate with another bot platform, the always-on nature increases the chance of unnoticed persistent data flow and excessive collection beyond user expectations.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill documentation describes behavior that reads and writes local files (for example session and cache paths) but does not declare any corresponding tool scope or permissions. In an agent ecosystem, undeclared file access weakens trust boundaries and can cause users or platforms to approve a skill without understanding its local data access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill handles highly sensitive health and behavioral data, including sleep and heart-rate information, on a recurring sync schedule, but the description does not prominently warn users about the privacy implications. Missing consent-oriented disclosure increases the risk of uninformed deployment and inappropriate sharing of personal health data into downstream bot systems.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation claims OAuth-based authentication with no password storage, yet it instructs users to pass a Garmin email and password directly to a script and discusses password troubleshooting. This is dangerous because command-line credentials can be exposed in shell history, process listings, logs, and screenshots, and users are misled about the authentication model.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The setup instructions ask users to enter account credentials on the command line without any warning that this can leak secrets through shell history, process inspection, or operational logs. Because this is an authentication step for a personal account tied to sensitive health data, the context makes the omission more dangerous than a generic CLI example.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script loads a persisted OAuth session file containing authentication material from a fixed path in the user's home directory, but provides no warning or safeguards around the sensitivity of that file. In a skill designed to sync fitness data every 5 minutes, compromise of the session file could allow unauthorized access to the user's Garmin account data without reauthentication.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script writes an OAuth session to disk without disclosing that the file contains reusable authentication state. Because this skill continuously syncs personal health and activity data, an attacker who obtains the session file may be able to impersonate the user and access sensitive account data until the session is revoked.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The user-facing instructions say the user should visit Garmin's sign-in page and that cookies will be automatically saved, implying this script handles OAuth/browser session capture. In reality, the code only attempts to load an existing session file and otherwise prints manual guidance; it contains no logic to open a browser, receive OAuth data, or persist cookies from a login flow.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script requires the Garmin password to be provided as a command-line argument and then persists an authenticated session to a predictable location in the user's home directory. Command-line secrets can be exposed via shell history, process listings, CI logs, or wrapper tooling, and the saved session file may be readable by other local users if file permissions are not restricted.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The code fetches a 30-day retrospective dataset instead of performing the narrow every-5-minute sync described by the skill metadata. In a health-data context, this materially increases the volume and sensitivity of accessed data and violates user expectations about scope, which can lead to overcollection of sensitive personal information.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script goes beyond the stated Garmin sync purpose by generating an interactive HTML dashboard and exporting detailed 30-day raw health data to local files. This expands data handling and exposure beyond what a user would reasonably expect from a periodic sync integration, increasing privacy risk and creating additional attack surface via stored sensitive artifacts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script writes detailed health data and an HTML dashboard containing that data to predictable files in /tmp without any privacy warning, access controls, or retention limits. On multi-user systems or systems where temporary directories are accessible or backed up, this can expose highly sensitive health information to other local users or processes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The setup flow tells the user to run OAuth authentication with a hard-coded email address and gives no explanation of the privacy or account implications. In a health-data integration, that makes the issue more dangerous because a user could authenticate the wrong account, expose another person’s account identifier, or become confused about which data is being synced and stored.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script embeds a specific personal email address in the OAuth setup instructions, which is unrelated to generic Garmin sync functionality and may misdirect users into authenticating against or associating activity with the wrong account. Hard-coded personal identifiers in authentication instructions are a security and privacy risk because they can cause accidental account misuse, expose the author’s personal information, and indicate the skill was not sanitized for third-party use.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code collects sensitive health and activity data, then writes it to a local cache file without any consent flow, retention guidance, file-permission hardening, or warning that protected personal data is being stored. In the context of a sync skill handling heart rate, sleep, workouts, and calories, undisclosed local persistence increases privacy risk if the file is readable by other users, backed up unintentionally, or consumed by other tools.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

This code makes network calls to retrieve personal health and activity data from Garmin using a saved OAuth session. While the module docstring says it syncs Garmin data, there is no explicit runtime warning, confirmation, or privacy notice that personal fitness data will be fetched from a remote service.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.