Back to skill

Security audit

Fitbit Tracker

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent Fitbit integration, but it handles sensitive health data and OAuth tokens with overly broad default access and weak local/privacy safeguards.

Install only if you are comfortable granting this skill access to Fitbit health data and storing OAuth tokens locally. Before use, reduce FITBIT_SCOPES to the minimum you need, avoid writing outputs to shared /tmp paths, keep token files private, revoke the Fitbit app if you stop using it, and prefer explicit Fitbit-specific prompts in private chats.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (4)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/fitbit_oauth_login.py:61
Finding

OAuth Authorization Flow Does Not Validate a State Parameter

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/fitbit_oauth_login.py:25
Finding

Default OAuth Scopes Exceed the Implemented Functionality

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/fitbit_fetch_daily.py:98
Finding

Sensitive Health Reports Are Written Without Explicitly Restrictive Permissions

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/fitbit_token.py:45
Finding

OAuth Tokens Are Temporarily Written Under Ambient File Permissions

Content
View full analysis
str: p = path or token_path() _mkdirp(p) tmp = p + ".tmp" with open(tmp, "w", encoding="utf-8") as f: json.dump(tok, f, indent=2, sort_keys=True) f.write("\n") os.replace(tmp, p) try: os.chmod(p, 0o600) except PermissionError: pass return p ``` ### Technical Analysis The final token file is changed to mode `0600`, but access and refresh tokens are first written to the predictable `token.json.tmp` path using ordinary file creation. The temporary file's initial permissions therefore depend on the process umask. There is an exposure window between temporary-file creation and the final `chmod`. If the process crashes before `os.replace`, the temporary file may remain on disk with unsafe permissions. The fixed temporary filename also permits interference if another local process can write to the token directory. The code does not use exclusive creation or reject symbolic links. Base64 encoding elsewhere in this module is not the vulnerability: encoding `client_id:client_secret` is the standard HTTP Basic authentication mechanism required for Fitbit's official HTTPS token endpoint. The weakness is local handling of the returned token material. ### Attack Path 1. The OAuth login or automatic refresh operation invokes `save_token`. 2. The function creates the predictable `.tmp` file under the current umask. 3. On a system with permissive directory access or file permissions, a local attacker monitors or reads the temporary file before replacement. 4. Alternatively, an interruption leaves the temporary file behind, allowing later retrieval. 5. The attacker obtains the access token and potentially the refresh token. 6. The stolen ...[truncated 609 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (14)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

"Missing env var: FITBIT_CLIENT_ID"

Environment variables not loaded. Source your .env file or ensure variables are set in the gateway environment:

bash
source ~/.openclaw/.env

"Token expired" error

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The skill processes highly sensitive health information, but the README emphasizes convenience and "just ask" usage without clearly warning users about the privacy implications of retrieving and displaying Fitbit data in chat. In shared, logged, or third-party chat environments, this can lead to inadvertent exposure of sleep, heart-rate, and activity information.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README suggests very generic trigger phrases like "how did I sleep?", "just my steps", and especially "full report," which could plausibly overlap with ordinary conversation in a chat environment. If the hosting platform routes skills based on natural-language matching, this can cause unintended invocation and disclosure of sensitive health data to the wrong context or without sufficiently explicit user intent.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The trigger list includes very broad phrases such as "fitbit", "health", "summary", and "daily summary", which can cause the skill to activate in contexts the user did not clearly intend. Because this skill accesses sensitive health data and stored OAuth tokens, accidental invocation increases privacy risk and may disclose personal wellness information unnecessarily.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill markets itself as effortless health monitoring but does not prominently warn that it sends sensitive health data to Fitbit APIs and stores OAuth tokens locally. For a health-related integration, insufficient privacy disclosure can lead users to authorize access without understanding the sensitivity of the data involved or the persistence of local credentials.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
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.

Content

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

md
## Setup

### 1. Create Fitbit Developer App

1. Go to [dev.fitbit.com](https://dev.fitbit.com)
2. Log in and click **Register an App**

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The reference explicitly requests highly sensitive health and profile scopes, including sleep, heart rate, activity, and profile data, but provides no accompanying privacy notice, data handling guidance, or user-consent disclosure language. In a skill context, collecting health data without clear disclosure increases the risk of over-collection, uninformed consent, and downstream privacy misuse even if the document is only an API reference.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code obtains credentials from environment variables, requests activity and sleep summaries from the Fitbit API, and saves the returned data to a user-specified file. While these operations are central to the script's purpose, there is no print/log message, confirmation, or inline warning disclosing that personal health data will be transmitted from Fitbit and stored locally.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/fitbit_api.md (reported line 14)May include surrounding context.

md
AUTH_URL = "https://www.fitbit.com/oauth2/authorize"
TOKEN_URL = "https://api.fitbit.com/oauth2/token"

DEFAULT_TOKEN_PATH = os.path.expanduser("~/.config/openclaw/fitbit/token.json")

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/fitbit_api.md (reported line 33)May include surrounding context.

md
AUTH_URL = "https://www.fitbit.com/oauth2/authorize"
TOKEN_URL = "https://api.fitbit.com/oauth2/token"

DEFAULT_TOKEN_PATH = os.path.expanduser("~/.config/openclaw/fitbit/token.json")

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/fitbit_api.md (reported line 66)May include surrounding context.

md
AUTH_URL = "https://www.fitbit.com/oauth2/authorize"
TOKEN_URL = "https://api.fitbit.com/oauth2/token"

DEFAULT_TOKEN_PATH = os.path.expanduser("~/.config/openclaw/fitbit/token.json")

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/fitbit_token.py (reported line 20)May include surrounding context.

python
AUTH_URL = "https://www.fitbit.com/oauth2/authorize"
TOKEN_URL = "https://api.fitbit.com/oauth2/token"

DEFAULT_TOKEN_PATH = os.path.expanduser("~/.config/openclaw/fitbit/token.json")

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code persists Fitbit token data, which may include access and refresh tokens, to a local file. Although file permissions are tightened, there is no confirmation prompt, user-facing log, or explanatory warning in the docstring/comments that sensitive credentials will be stored on disk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The helper performs HTTP POST requests to Fitbit token endpoints and is used to send authorization codes, refresh tokens, and a Basic Authorization header derived from client ID and client secret. The file lacks any visible warning, log, or explanatory comment that sensitive authentication material is sent to external network endpoints.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/fitbit_fetch_daily.py:80