Back to skill

Security audit

Garmin Connect

Security checks for vulnerabilities and agentic risk

Overview

This Garmin skill has a coherent fitness-sync purpose, but it mishandles account passwords, shared app secrets, persistence, and private health data enough that it should be reviewed before installation.

Install only after reviewing and preferably fixing the credential handling. Do not pass your Garmin password on the command line, rotate any Feishu secret that may be real, run the sync only as your normal user, restrict ~/.garth and ~/.clawdbot permissions, avoid shared machines, and verify any webhook or report destination before enabling automatic reports.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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 (8)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/daily_health_report_feishu.py:225
Finding

Hard-Coded Feishu Application Credentials

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

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

Garmin Password Stored with Reversible Base64 Encoding

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/garmin-sync.py:624
Finding

Sensitive Health Data Written and Printed Without Adequate Confidentiality Controls

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/garmin-cron.sh:8
Finding

Predictable Temporary Log Enables Health-Data Disclosure and Symlink File Clobbering

Content
View full analysis
/tmp/garmin-sync.log 2>&1 ``` ### Technical Analysis The cron wrapper redirects output to a fixed path in the globally shared `/tmp` directory. The invoked synchronization script prints the complete health dataset to standard output, so the temporary log contains sensitive information. Shell redirection follows symbolic links. Another local user may be able to pre-create `/tmp/garmin-sync.log` as a symbolic link to a file writable by the cron account. When the scheduled command runs, the target can be truncated and overwritten. The risk is especially serious if a user installs the cron entry under a privileged account, although such privilege is not required or justified by the Skill's functionality. ### Attack Path 1. An attacker with local access creates `/tmp/garmin-sync.log` as a symbolic link to a target file writable by the cron user. 2. The configured cron task starts. 3. Shell redirection follows the symbolic link and truncates the target. 4. Garmin synchronization output is written into the target file. 5. The attacker may cause data corruption and may also read the health output if the resulting file is accessible. Alternatively, an attacker can monitor the predictable log directly when its permissions permit reading. ### Impact Assessment The vulnerability can disclose private health data and corrupt arbitrary files writable by the account running cron. If the task is incorrectly installed as root, the file-clobbering scope could include privileged system files. The Skill does not require root privileges, so privileged scheduling would exceed least privilege. ]]>
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/daily_health_report_webhook.py:146
Finding

Health Reports Can Be Sent to an Unrestricted Webhook Destination

Content
View full analysis
Remediation
View remediation

T07 · Tool Hijacking and Spoofing

Warning
Location
scripts/garmin_quick_response.py:20
Finding

Execution of Replaceable Scripts from an External Home-Directory Path

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/garmin_db_reader.py:78
Finding

SQL Query Limits Are Constructed Through String Interpolation

Content
View full analysis
List[Dict]: """获取历史健康数据""" conn = self.get_connection() cursor = conn.cursor() cursor.execute(f""" SELECT * FROM daily_metrics ORDER BY date DESC LIMIT {days} """) ``` Similar interpolation is used elsewhere: ```python cursor.execute(f""" SELECT * FROM sleep_data ORDER BY date DESC LIMIT {days} """) ``` ```python cursor.execute( f"SELECT * FROM workouts ORDER BY timestamp DESC LIMIT {limit}" ) ``` ### Technical Analysis Python type annotations do not enforce argument types at runtime. A caller can supply a string or another object whose string representation changes the SQL expression. SQLite's `execute()` generally rejects stacked statements, which limits direct multi-statement exploitation, but an attacker can still manipulate the `LIMIT` expression, bypass intended record limits, trigger expensive expressions, or produce database errors. The parameterized implementation already used by `get_workouts_by_type()` demonstrates the safer pattern. ### Attack Path 1. An integration exposes one of the reader methods to an untrusted caller. 2. The caller passes a crafted string instead of an integer for `days` or `limit`. 3. The value is inserted directly into the SQL statement. 4. SQLite evaluates the modified `LIMIT` expression. 5. The attacker bypasses the intended result limit, causes query failure, or increases resource consumption. ### Impact Assessment The practical impact is primarily unauthorized expansion of query results, application errors, and denial of service. The vulnerable statements are read-only, and SQLite's single-statement restriction r ...[truncated 82 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Security-Sensitive Dependencies Are Not Reproducibly Pinned

Content
View full analysis
=0.2.38 requests>=2.28.0 python-dateutil>=2.8.2 garth>=0.5.0 ``` ### Technical Analysis All dependencies use open-ended minimum-version constraints. A future installation may therefore select versions that were never reviewed with this Skill. These packages execute in a process that handles a Garmin password, authenticated sessions, private health data, and outbound network requests. No evidence of typosquatting, dependency confusion, or a currently malicious package was found. The risk arises from non-reproducible resolution and exposure to future compromised, incompatible, or unexpectedly changed releases. ### Attack Path 1. A dependency publishes a compromised or behaviorally incompatible future release. 2. A user runs `pip install -r requirements.txt`. 3. The package resolver selects the unreviewed release because it satisfies the minimum constraint. 4. The dependency executes in the Skill environment. 5. A compromised dependency can access credentials, health records, and network connectivity available to the process. ### Impact Assessment A compromised dependency could obtain the same user-level access as the Skill, including Garmin credentials, authenticated sessions, SQLite health data, report configurations, and outbound network access. The risk is supply-chain-wide because it can affect new installations without any change to this repository. ]]>
Remediation
View remediation
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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (89)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Background daemons, PID/lock files, lifecycle controls, and retry behavior are not inherently malicious, but they are significant operational behaviors omitted from the declared purpose. Undeclared persistence and long-running execution can surprise operators and expand the attack surface, particularly on systems where skills are expected to be transient.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Background daemons, PID/lock files, lifecycle controls, and retry behavior are not inherently malicious, but they are significant operational behaviors omitted from the declared purpose. Undeclared persistence and long-running execution can surprise operators and expand the attack surface, particularly on systems where skills are expected to be transient.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Background daemons, PID/lock files, lifecycle controls, and retry behavior are not inherently malicious, but they are significant operational behaviors omitted from the declared purpose. Undeclared persistence and long-running execution can surprise operators and expand the attack surface, particularly on systems where skills are expected to be transient.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

Background daemons, PID/lock files, lifecycle controls, and retry behavior are not inherently malicious, but they are significant operational behaviors omitted from the declared purpose. Undeclared persistence and long-running execution can surprise operators and expand the attack surface, particularly on systems where skills are expected to be transient.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Background daemons, PID/lock files, lifecycle controls, and retry behavior are not inherently malicious, but they are significant operational behaviors omitted from the declared purpose. Undeclared persistence and long-running execution can surprise operators and expand the attack surface, particularly on systems where skills are expected to be transient.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Background daemons, PID/lock files, lifecycle controls, and retry behavior are not inherently malicious, but they are significant operational behaviors omitted from the declared purpose. Undeclared persistence and long-running execution can surprise operators and expand the attack surface, particularly on systems where skills are expected to be transient.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Background daemons, PID/lock files, lifecycle controls, and retry behavior are not inherently malicious, but they are significant operational behaviors omitted from the declared purpose. Undeclared persistence and long-running execution can surprise operators and expand the attack surface, particularly on systems where skills are expected to be transient.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Background daemons, PID/lock files, lifecycle controls, and retry behavior are not inherently malicious, but they are significant operational behaviors omitted from the declared purpose. Undeclared persistence and long-running execution can surprise operators and expand the attack surface, particularly on systems where skills are expected to be transient.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

Background daemons, PID/lock files, lifecycle controls, and retry behavior are not inherently malicious, but they are significant operational behaviors omitted from the declared purpose. Undeclared persistence and long-running execution can surprise operators and expand the attack surface, particularly on systems where skills are expected to be transient.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Background daemons, PID/lock files, lifecycle controls, and retry behavior are not inherently malicious, but they are significant operational behaviors omitted from the declared purpose. Undeclared persistence and long-running execution can surprise operators and expand the attack surface, particularly on systems where skills are expected to be transient.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

Background daemons, PID/lock files, lifecycle controls, and retry behavior are not inherently malicious, but they are significant operational behaviors omitted from the declared purpose. Undeclared persistence and long-running execution can surprise operators and expand the attack surface, particularly on systems where skills are expected to be transient.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Background daemons, PID/lock files, lifecycle controls, and retry behavior are not inherently malicious, but they are significant operational behaviors omitted from the declared purpose. Undeclared persistence and long-running execution can surprise operators and expand the attack surface, particularly on systems where skills are expected to be transient.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

Background daemons, PID/lock files, lifecycle controls, and retry behavior are not inherently malicious, but they are significant operational behaviors omitted from the declared purpose. Undeclared persistence and long-running execution can surprise operators and expand the attack surface, particularly on systems where skills are expected to be transient.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The script contains hardcoded Feishu App ID and App Secret, embedding live third-party credentials in source code. Anyone with access to the skill can reuse these credentials to obtain tokens and operate the associated Feishu app, potentially impersonating the bot, sending messages, or abusing tenant resources.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The hardcoded App Secret is persisted locally and then used for outbound API calls, creating both secret exposure and poor credential-handling practice. Even though the file mode is restricted, storing a real shared secret in plaintext on disk and shipping a default secret in code greatly increases the chance of unauthorized reuse and long-term compromise.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The docstring states credentials are saved securely, but the implementation only base64-encodes the password, which is trivially reversible and provides no real confidentiality. This is dangerous because it can mislead users and reviewers into believing the stored secret is protected when anyone with filesystem access can recover the plaintext password immediately.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script persists the user's Garmin password after login in base64-obfuscated form and does so without a strong warning that the secret is written to disk and recoverable. In the context of a fitness sync skill, this is especially risky because compromise of the local machine or backup artifacts could expose the user's Garmin account credentials, enabling account takeover and access to personal health data.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The usage instructions tell users to pass their password as a command-line argument, which commonly leaks secrets through shell history, process listings, terminal logging, and monitoring tools. This is dangerous because even if the file permissions are restricted later, the password may already have been exposed to other local users, system telemetry, or support logs at invocation time.

Content

No source excerpt is available for this finding.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
94% confidence
Finding

The code executes a shell command via os.popen using a dynamically constructed command string. Although script_path is selected from hardcoded Path objects in this file, invoking a shell is still dangerous because the path is derived from the user's home directory and can contain shell metacharacters or point to attacker-controlled files in a writable location, leading to command injection or unintended code execution.

Content

Scanner excerpt · scripts/garmin_quick_response.py (reported line 70)May include surrounding context.

python
if not script_path.exists():
            return f"❌ 脚本不存在:{script_path}"

        result = os.popen(f'python3 {script_path}').read()

        if not result:
            return "❌ 暂无数据"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The README instructs users to pass Garmin account passwords directly on the command line, which commonly exposes secrets through shell history, process listings, terminal logging, and support screenshots. Because these credentials grant access to personal fitness and health data, disclosure can lead to account compromise and privacy harm beyond the local machine.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README documents storage of health data in a local SQLite database and OAuth/session credentials in a predictable filesystem location, but provides no warning about their sensitivity or the need for access controls. On shared systems, backups, or compromised user accounts, these files can expose intimate health information and reusable session material.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill documentation describes capabilities that imply file access, shell execution, persistence, and network use, but it does not declare any explicit tool scope or permissions boundary. In an agent ecosystem, this increases the chance that the skill is granted broader-than-necessary powers or that reviewers underestimate what it can do.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The skill stores sensitive health data locally in SQLite but provides no user-facing warning about privacy, retention, access controls, or backup exposure. Health metrics such as sleep, HRV, heart rate, and body battery are sensitive personal data, so silent local persistence increases privacy risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The instructions tell users to place their Garmin password directly on the command line. Command-line arguments are commonly exposed through shell history, process listings, logs, and support screenshots, making credential disclosure far more likely.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

bash
# 已自动配置,每1小时同步一次
sudo systemctl status garmin-sync.timer

手动触发:

Static analysis

No suspicious patterns detected.