Back to skill

Security audit

Garmin Connect Data Query

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it says, but it handles a sensitive Garmin account token and health data in ways users should review before installing.

Install only if you are comfortable giving the skill a live Garmin bearer token that can access private account and health data. Avoid passing the token on the command line, remove the hardcoded user ID and sample personal data before use, and prefer a reviewed version that reads the token from a safer secret source and fails closed when it cannot determine the authenticated user ID.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/query.py:58
Finding

Bearer JWT Exposed Through Command-Line Arguments

Content
View full analysis
[日期 YYYY-MM-DD]") sys.exit(1) jwt = sys.argv[1] date = sys.argv[2] if len(sys.argv) > 2 else None ``` ```python # scripts/activities.py:41-43 if __name__ == '__main__': jwt = sys.argv[1] if len(sys.argv) > 1 else None if not jwt: ``` ```markdown ```bash python3 scripts/query.py [日期 YYYY-MM-DD] ``` ``` ```markdown ```bash # 查询今日数据 python3 scripts/query.py "$GARMIN_JWT" # 查询指定日期 python3 scripts/query.py "$GARMIN_JWT" 2026-03-24 # 查询最近活动 python3 scripts/activities.py "$GARMIN_JWT" ``` ``` ### Technical Analysis Both executable scripts obtain the Garmin bearer JWT from `sys.argv`. Even when an environment variable is expanded using `"$GARMIN_JWT"`, the resulting secret becomes part of the child process's argument vector. Depending on the operating system and local security configuration, process arguments may be exposed through process-monitoring commands, diagnostic tools, audit records, crash reports, process telemetry, or automation logs. Commands containing a literal token may additionally remain in shell history. The JWT is an account access credential rather than a non-sensitive identifier. The scripts use it in an `Authorization: Bearer` header to request Garmin profile, activity, and health information. ### Attack Path 1. A victim follows the documented command and passes the Garmin JWT as the first argument. 2. While the process is running, a local user or monitoring component reads its command-line arguments through process inspection or telemetry. 3. Alternatively, ...[truncated 600 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
references/api.md:24
Finding

Personal Account Data and Fixed Garmin User ID Embedded in the Project

Content
View full analysis
2 else "116181268" ``` ### Technical Analysis The API documentation contains an apparent personal name, email address, and Garmin user identifier. The same fixed user identifier is embedded as a fallback or default in both executable scripts. In `query.py`, failure to retrieve a valid authenticated profile does not cause the operation to fail closed. Instead, the heart-rate request silently targets the fixed identifier. In `activities.py`, omitting the optional user ID causes the request to target that identifier by default. Whether cross-account data is returned depends on Garmin's server-side authorization controls. The client must not assume those controls make a fixed foreign identifier safe. At minimum, the project discloses apparent personal information and creates a risk of incorrect-account requests. ### Attack Path 1. The project is published or distributed with the documented response example. 2. Anyone obtaining the project learns the embedded email address, display name, and Garmin user identifier. 3. A user runs `query.py` when the profile request fails or returns no `userId`, or runs `activities.py` without specifying a user ID. 4. The script sends a health or activity request containing ...[truncated 590 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
README.md:29
Finding

Unpinned Third-Party Dependency Installation

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The documented behavior does not match the detected behavior: the skill can access and output personal profile data like displayName and email that are not disclosed in the description, while also failing to implement several promised health-query features. For a skill processing health-related data, undeclared access to personally identifiable information is particularly sensitive because users may consent to step or sleep queries without expecting profile disclosure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README instructs users to manually extract a live Garmin JWT from browser cookies and reuse it for API access, but does not clearly frame it as a sensitive bearer credential that grants account access. Because bearer tokens can be copied and used by anyone who obtains them, users may mishandle, paste, share, or store the token insecurely, leading to unauthorized access to private health and activity data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The README demonstrates passing the JWT directly as a command-line argument, which can expose it through shell history, process listings, terminal scrollback, or monitoring tools. In this skill's context, the token grants access to sensitive personal health data, so accidental disclosure could let another local user or operator query private Garmin account information.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill requires network access to query Garmin Connect but does not declare any tool scope or allowed-tools boundary. Missing capability declarations weaken reviewability and containment, making it easier for a skill handling sensitive health data and bearer credentials to perform unintended outbound requests without clear user or platform visibility.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill instructs users to manually extract a JWT bearer token from browser cookies and pass it to a script, but provides no clear warning that this credential grants account access and may expose sensitive health information if mishandled. Encouraging token extraction and transmission without strong handling guidance increases the risk of credential leakage through shell history, logs, screenshots, copied text, or reuse in unintended contexts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This markdown file describes endpoints returning user profile data, email, activity history, and heart-rate information, and includes a Python template that sends authenticated requests to retrieve them. The document contains no warning or disclosure about handling sensitive personal/health data or protecting the JWT token, which is required for markdown files when behaviors could affect user privacy.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script accepts a JWT authentication token as a command-line argument, which can be exposed through shell history, process listings, audit logs, or job-control tooling on the host. Because this token grants access to sensitive Garmin health and activity data, accidental disclosure could allow unauthorized access to a user's private fitness, sleep, and heart-rate information.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script requires a JWT to be passed on the command line, which can expose the credential through shell history, process listings, audit logs, and wrapper tooling. Because this token grants access to sensitive Garmin health data, disclosure could let another local user or logging system reuse the token to query private profile, activity, sleep, and heart-rate information.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
72% confidence
Finding

The README presents the skill name, instructions, and example OpenClaw dialogue entirely in Chinese, which may imply a fixed language expectation for interaction. The documented regional scope concerns Garmin China endpoints, but the language constraint itself is not explicitly framed as an opt-in or user-selectable choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The file's natural-language content, headings, and field descriptions are all in Chinese, which can impose a fixed language on users without opt-in. Under the policy criteria, forcing a specific language without offering a choice or justification is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

SQP-3 applies to all file types and covers language or locale policy violations. This setup guide forces a specific language for all instructions, FAQs, and safety guidance, with no opt-in or alternative language option documented.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.