Back to skill

Security audit

Strava (Official API)

Security checks for vulnerabilities and agentic risk

Overview

This Strava skill appears purpose-aligned, but it stores OAuth tokens and sensitive workout data locally in ways that deserve review before installation.

Review this before installing if you will run it on a shared machine or store outputs in shared directories. Keep STRAVA_CLIENT_SECRET and the token file private, set STRAVA_TOKEN_PATH to a private directory, avoid the documented /tmp output paths for real activity data, and revoke the Strava authorization if the token file may have been exposed.

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/strava_oauth_login.py:106
Finding

OAuth Authorization Flow Lacks State Validation

Content
View full analysis
str: s = user_input.strip() if s.startswith("http://") or s.startswith("https://"): u = urllib.parse.urlparse(s) q = urllib.parse.parse_qs(u.query) code = (q.get("code") or [None])[0] if code: return code raise SystemExit("Could not find ?code= in the pasted redirect URL") return s ``` ```python q = urllib.parse.parse_qs(parsed.query) code = (q.get("code") or [None])[0] if code: got["code"] = code self.send_response(200) self.send_header("Content-Type", "text/plain; charset=utf-8") self.end_headers() self.wfile.write(b"OK. You can close this tab and return to OpenClaw.\n") ``` ```python params = { "client_id": client_id, "redirect_uri": redirect_uri, "response_type": "code", "approval_prompt": "auto", "scope": scopes, } ``` ### Technical Analysis The OAuth authorization request does not include a cryptographically random `state` parameter. Neither the copy-and-paste flow nor the loopback callback verifies that the received response belongs to the authorization request initiated by the current process. OAuth `state` is the standard correlation and CSRF protection mechanism for authorization redirects. Accepting any authorization code without validating its association with the active login attempt permits login CSRF or account substitution under suitable delivery conditions. The issue does not directly disclose the victim's Strava credentials. Its primary effect is that the Skill may exchange and persist a code associated with an unintended Strava account. ### Attack Path 1. An attacker initiates an OAuth authorization flow for the same configured Strava OAuth client and redire ...[truncated 1213 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/strava_token.py:42
Finding

OAuth Tokens and Sensitive Activity Data Use Unsafe File-Creation Patterns

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 ``` Raw activity output: ```python with open(args.out, "w", encoding="utf-8") as f: json.dump(bundle, f, indent=2, sort_keys=True) f.write("\n") ``` Normalized activity output: ```python json.dump(out, open(args.out, "w", encoding="utf-8"), indent=2, sort_keys=True) open(args.out, "a", encoding="utf-8").write("\n") ``` Documented predictable shared temporary paths: ```bash python3 scripts/strava_fetch_activities.py --date today --out /tmp/strava_raw_today.json python3 scripts/strava_normalize_daily.py /tmp/strava_raw_today.json --out /tmp/strava_today.json ``` ### Technical Analysis The token writer uses a predictable temporary path formed by appending `.tmp` to the destination. It opens this path with ordinary Python file semantics, which follow symbolic links and do not require exclusive creation. Restrictive `0600` permissions are applied only after the temporary file has been written and renamed. Consequently: - Initial permissions are controlled by the process umask. - A pre-existing temporary file can retain unsafe permissions. - A local attacker may pre-create a symbolic link at the predictable temporary path. - The token directory is created without explicitly enforcing a private ...[truncated 2466 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 (8)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The documentation claims end-to-end Strava integration, but the visible content only shows orchestration through local scripts and file-based inputs/outputs. When a security-sensitive skill overstates its function, operators may grant trust or permissions based on inaccurate assumptions, increasing the risk of unsafe token handling or execution of unaudited helper scripts.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The documentation claims end-to-end Strava integration, but the visible content only shows orchestration through local scripts and file-based inputs/outputs. When a security-sensitive skill overstates its function, operators may grant trust or permissions based on inaccurate assumptions, increasing the risk of unsafe token handling or execution of unaudited helper scripts.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill advertises capabilities that inherently require sensitive operations (environment access, filesystem reads/writes, network access, and shell execution) but does not declare any tool scope or permissions boundaries. In an agent environment, this weakens least-privilege controls and can allow broader-than-expected access to credentials, token files, or command execution if the skill is invoked or implemented unsafely.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill instructs users to configure Strava client credentials and references a token storage path, but it does not warn about the sensitivity of OAuth tokens, refresh tokens, and client secrets. Without explicit handling guidance, users may store secrets insecurely, commit them to repositories, or expose them via permissive filesystem locations or logs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script writes the full raw Strava activity response to an arbitrary output path without any minimization, permission hardening, or warning that the data may contain sensitive fitness and location metadata. In the context of a Strava integration, raw activity JSON can expose private routines, timestamps, geospatial information, and other personal health-related data, so insecure local storage increases privacy and secondary disclosure risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This function persists Strava token material to a local file, which can affect user privacy and credential handling. While the code sets restrictive permissions, there is no confirmation prompt, user-visible logging, or explanatory comment/docstring warning that sensitive authentication data will be stored on disk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The helper issues HTTP POST requests that can carry sensitive OAuth data, and the calling functions pass client_secret, code, and refresh_token values to Strava. The code lacks any confirmation prompt, logging, or explanatory comment/docstring warning that secrets and token data are being sent to an external service.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The documentation defines STRAVA_TZ with a default of Asia/Shanghai, which imposes a specific locale/timezone assumption in natural-language configuration guidance. This can violate locale policy when users are not explicitly offered a choice or informed that the default is region-specific.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.