Back to skill

Security audit

Withings Family

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it says, but it handles family health records and persistent OAuth tokens with enough storage and consent gaps that users should review it carefully before installing.

Install only if you are comfortable storing Withings OAuth tokens on this machine and using this agent to retrieve sensitive health data. Each family member should explicitly authorize their own account, and users should know where tokens are stored so they can delete them locally and revoke access in Withings if needed. Prefer a trusted single-user machine, and treat the local token directory as sensitive.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/withings.py:61
Finding

OAuth token files are not created atomically with restrictive permissions

Content
View full analysis
dict: """Save tokens with expiry calculation.""" expiry = time.time() + data['expires_in'] payload = {**data, 'expiry_date': expiry} token_file = get_token_file(user_id) token_file.write_text(json.dumps(payload, indent=2)) try: os.chmod(token_file, 0o600) except Exception: pass return payload ``` The equivalent implementation in `scripts/withings_oauth_local.py` is: ```python def save_tokens(data: dict, user_id: str = 'default') -> dict: """Save tokens with expiry calculation.""" expiry = time.time() + data['expires_in'] payload = {**data, 'expiry_date': expiry} token_file = get_token_file(user_id) token_file.write_text(json.dumps(payload, indent=2)) # Secure permissions try: os.chmod(token_file, 0o600) except Exception: pass return payload ``` ### Technical Analysis Both scripts save OAuth access and refresh tokens by first calling `Path.write_text()` and only afterward changing the file mode to `0600`. When a token file is newly created, its initial permissions are determined by the process umask. With a common umask of `022`, the file may initially be created as `0644`. There is consequently a time-of-check/time-of-use window between file creation and `chmod()` during which another local user may be able to read the tokens. The scripts also suppress every exception raised by `chmod()`. If the permission change fails because of filesystem semantics, ownership, access-control rules, or another environmental condition, execution continues and the token file may remain overly permissive without notifying the u ...[truncated 2298 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/withings.py:127
Finding

Manual OAuth flow uses a fixed state and does not validate it

Content
View full analysis
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description emphasizes fetching health data, but the documented behavior also includes OAuth initiation, running a localhost callback server, and persistent token storage. That mismatch can mislead reviewers and users about the true security posture of the skill, especially because authentication flows and token handling materially increase risk beyond simple data retrieval.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/withings.py (reported line 94)May include surrounding context.

python
def get_valid_token(user_id='default'):
    """Get a valid access token, refreshing if needed."""
    token_file = get_token_file(user_id)
    
    if not token_file.exists():

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill advertises and operationally requires sensitive capabilities—environment access, file read/write, network, and shell—but does not explicitly declare a tool scope or permissions boundary. In a skill that handles OAuth credentials and health data, missing scope declarations increase the chance of unintended broad access and make review and runtime enforcement harder.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill is explicitly designed for multiple family members' health data, which is highly sensitive medical information, yet it lacks an explicit privacy, consent, and access-control warning. In a multi-user context, this omission increases the risk of unauthorized retrieval, accidental cross-user access, or misuse of one family member's credentials to inspect another person's data.

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 41)May include surrounding context.

md
## Setup: Creating a Withings Developer App

Before using this skill, you need to create a free Withings developer application to get your API credentials.

### Step 1: Create a Withings Developer Account

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

OAuth access and refresh tokens are persisted to disk in plaintext JSON, which creates a local secret-at-rest exposure if the host, home directory, backups, or workspace are accessible to other users or processes. The chmod(0600) helps on Unix-like systems but is best-effort only, may silently fail, and does not provide encryption or platform-independent protection.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code sends user health-related data requests and OAuth credentials to Withings over the network, but there is no user-facing disclosure about the privacy implications of contacting an external health service. Since the file handles sensitive body, activity, and sleep data, a visible warning or notice would help users understand that their data is being transmitted off-device.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.