T09 · Insecure Skill Coding Practices
- Location
scripts/fitbit_oauth_login.py:61- Finding
OAuth Authorization Flow Does Not Validate a State Parameter
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
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.
scripts/fitbit_oauth_login.py:61OAuth Authorization Flow Does Not Validate a State Parameter
scripts/fitbit_oauth_login.py:25Default OAuth Scopes Exceed the Implemented Functionality
scripts/fitbit_fetch_daily.py:98Sensitive Health Reports Are Written Without Explicitly Restrictive Permissions
scripts/fitbit_token.py:45OAuth Tokens Are Temporarily Written Under Ambient File Permissions
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Environment variables not loaded. Source your .env file or ensure variables are set in the gateway environment:
source ~/.openclaw/.env
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.
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.
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.
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.
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.
## Setup
### 1. Create Fitbit Developer App
1. Go to [dev.fitbit.com](https://dev.fitbit.com)
2. Log in and click **Register an App**
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.
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.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
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")
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
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")
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
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")
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
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")
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.
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.
Detected: suspicious.exposed_secret_literal