Back to skill

Security audit

Withings (Official API)

Security checks for vulnerabilities and agentic risk

Overview

The skill appears purpose-aligned for Withings data, but it handles OAuth tokens and sensitive health files with enough weak safeguards that users should review it before installing.

Review this skill before installing if you use Withings health data. Use a private token path and private output directory, avoid the documented /tmp filenames on shared machines, restrict token and output permissions, and be aware that OAuth login lacks state validation.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/withings_oauth_login.py:113
Finding

OAuth Authorization Flow Lacks State Validation

Content
View full analysis
")) tok = exchange_code_for_token( code=code, client_id=client_id, client_secret=client_secret, redirect_uri=redirect_uri, ) ``` The loopback callback also accepts a code without correlating it to the authorization request: ```python q = urllib.parse.parse_qs(parsed.query) code = (q.get("code") or [None])[0] if code: got["code"] = code self.send_response(200) ``` ### Technical Analysis OAuth authorization requests should include a cryptographically unpredictable `state` value that is bound to the local login attempt. The callback must require the same value and reject responses with a missing or mismatched state. This implementation does not generate, transmit, retain, or validate a `state` parameter. Consequently, it cannot distinguish the authorization response initiated by the current user from an unsolicited response delivered to the same callback URI. The copy-and-paste mode has the same weakness because `parse_code()` extracts only the authorization code and does not validate state. Authorization-code protections at the provider may limit exploitability, because the code remains bound to the configured client and redirect URI and should be single-use. They do not provide local request correlation, h ...[truncated 1327 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/withings_fetch_daily.py:145
Finding

Sensitive Health Data Is Written to Predictable Files Without Restrictive Permissions

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/withings_token.py:48
Finding

OAuth Token Temporary File Is Not Securely Created

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`, which is an appropriate objective. However, the OAuth response is first written to a predictable `.tmp` file using ordinary `open()`. Its initial permissions are controlled by the process umask, and restrictive permissions are applied only to the final path after `os.replace()`. If the process is interrupted before replacement or chmod, a temporary or final token file may remain with broader permissions than intended. The temporary path is also predictable and ordinary opening follows symbolic links. A local attacker who can manipulate the token directory may pre-position a symbolic link at the `.tmp` path, causing token JSON to be written to a different victim-writable location. The default parent path under `~/.config` reduces practical exposure on many single-user systems, but `_mkdirp()` does not explicitly enforce mode `0700`, and `WITHINGS_TOKEN_PATH` can place the file in a shared or attacker-influenced directory. ### Attack Path 1. The victim configures the token path in a shared or insufficiently protected directory, or the relevant directory permissions allow another local user to manipulate entries. 2. The attacker predicts the fixed `.tmp` filename and monitors it or places a symbolic link at that path. 3. OAuth login or token refresh calls `save_token()`. 4. The a ...[truncated 834 chars]
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 (10)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code is clearly related to Withings personal health data and does fetch measurements plus best-effort sleep summaries, including today/yesterday date resolution by timezone. However, the declared description claims a broader OAuth integration that connects/authorizes accounts, stores and refreshes tokens locally, and produces normalized daily JSON for a Wellness hub. This specific code chunk does not implement the OAuth authorization flow, token storage, or normalization logic; it simply obtains an access token from an external helper, calls Withings APIs, and writes a bundle containing mostly raw responses to disk. Because key claimed capabilities are absent from the supplied code chunk, the description does not accurately represent what this chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a full Withings integration: account authorization, local token management, API retrieval of measurements and sleep data, and date-scoped fetching. The supplied code does none of that. It only processes an already-existing local JSON input file and writes a normalized summary file. While the normalization portion is consistent with part of the description, the code chunk lacks the major advertised capabilities of OAuth, token persistence/refresh, and remote data fetching. Therefore the description materially overstates what this code actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents this skill as a full Withings integration responsible for account authorization, token management, remote data retrieval, and normalized JSON generation. The supplied code does none of those core functions. Instead, it only loads a local JSON file and formats its contents into human-readable text/markdown output. While the rendered fields align with Withings-related wellness data, the primary purpose is materially different from the declared integration behavior, so this is a clear description-behavior mismatch.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill declares no explicit tool scope or permissions even though the documented behavior clearly requires environment-variable access, local file read/write, network access, and shell execution. In an agent ecosystem, missing capability boundaries can let the skill run with broader privileges than users expect, especially since it handles OAuth secrets, token files, and sensitive health data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill handles OAuth tokens and highly sensitive personal health data but does not prominently warn users that tokens are stored locally or explain the privacy implications. In this context, inadequate disclosure increases the chance that users will place token files in insecure locations, mishandle outputs, or unknowingly expose medical information.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code performs a network token exchange using client credentials and then writes the resulting OAuth token to disk. While the script is interactive and prints the authorization URL, it does not disclose before these steps that sensitive tokens will be transmitted and stored locally, which is a safety-relevant behavior under the warning criteria for code files.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The function persists OAuth token material, which can include access and refresh tokens, to a local file. While the module docstring mentions OAuth2 generally, there is no user-facing warning, confirmation, or explicit disclosure in this file that sensitive credentials will be stored on disk at a path under the user's home directory.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The token exchange sends the authorization code, client ID, and client secret to the Withings token endpoint, and the refresh flow similarly transmits client credentials and refresh tokens. Although this behavior is functionally expected for OAuth, this file does not include a user-facing warning or explicit disclosure that sensitive authentication data will be sent over the network.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The file's natural-language documentation states a default timezone of Asia/Shanghai, and the code also uses that locale-specific default when no user choice is provided. This imposes a specific locale behavior without opt-in, which matches the language/locale policy concern for natural-language policy violations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The script writes and appends to the path provided by --out, which can overwrite or create files, but there is no confirmation prompt, print/log message, or inline warning near the operation. The top-level docstring describes usage but does not explicitly disclose that the specified output file will be written.

Content

No source excerpt is available for this finding.