Back to skill

Security audit

OpenClaw Health

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real health-brief integration, but it asks for and stores sensitive health access in ways users should review carefully before installing.

Install only if you are comfortable granting health-provider OAuth access and storing refresh tokens locally and/or in 1Password. Before use, reduce WHOOP scopes to only the endpoints you need, avoid collecting Withings blood pressure unless you explicitly want it, keep token files private, and be cautious with cron delivery channels and /tmp output paths.

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

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
README.md:136
Finding

Excessive WHOOP OAuth scopes violate least privilege

Content
View full analysis

Vulnerability Details

File Location: README.md:136-142
Vulnerability Type: Excessive OAuth permissions
Risk Level: Medium

Vulnerable Code

text
1. Go to [developer.whoop.com](https://developer.whoop.com) and create an account
2. Create a new OAuth application:
   - **Name:** anything (e.g. "OpenClaw Health")
   - **Redirect URI:** `http://127.0.0.1:8787/callback`
   - **Scopes:** enable all `read:*` scopes + `offline` (required for refresh tokens)
3. Copy your **Client ID** and **Client Secret**
4. Store in 1Password (item: `OpenClaw Whoop`, fields: `client_id`, `client_secret`) or export as env vars

Technical Analysis

The setup instructions direct users to grant every available WHOOP read:* scope. The connector only uses the cycle, recovery, and sleep endpoints in connectors/whoop/__init__.py:182-226. Consequently, granting all read scopes exceeds the permissions required to generate the declared daily health brief.

The offline scope is reasonably necessary for unattended token refresh. The issue is the unrestricted request for all read scopes rather than an explicit list of scopes corresponding to the implemented API calls.

OAuth access and refresh tokens inherit the authorized scope set. A token exposed through local storage, process monitoring, backups, endpoint telemetry, or another application vulnerability could therefore be used to access WHOOP resources unrelated to the Skill's implemented features.

Attack Path

  1. A user follows the README and authorizes all WHOOP read:* scopes plus offline.
  2. WHOOP issues an access token and long-lived refresh token carrying those permissions.
  3. The refresh token is stored in 1Password or ~/.openclaw/secrets/health_tokens.json.
  4. An attacker obtains either token through a separate local compromise, backup disclosure, or process-level access.
  5. The attacker uses the token against any WHOOP API resource permitted by t ...[truncated 481 chars]
Remediation
View remediation

Remediation Suggestions

  1. Replace all read:* scopes with an explicit allowlist containing only the scopes required for:
    • Cycle retrieval
    • Recovery retrieval
    • Sleep retrieval
    • Offline refresh
  2. Document why each requested scope is necessary and map it to the corresponding endpoint.
  3. Avoid requesting optional profile, body, workout, or other read scopes unless a feature requiring them is enabled.
  4. If provider authorization supports incremental consent, request optional scopes only when the user enables the related feature.
  5. Advise existing users to revoke and reauthorize the integration with the reduced scope set, because changing documentation alone will not narrow previously issued tokens.
  6. Add a test or configuration assertion that compares the requested scopes against an approved allowlist.

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
connectors/withings/__init__.py:178
Finding

Undeclared blood-pressure collection expands sensitive health-data exposure

Content
View full analysis

Vulnerability Details

File Location: connectors/withings/__init__.py:178-216; retained through core/normalize/__init__.py:85-87
Vulnerability Type: Excessive collection and retention of sensitive health data
Risk Level: Medium

Vulnerable Code

python
# Weight, body fat %, BP
try:
    start, end = _epoch_range_for_day(date_str)
    q = urllib.parse.urlencode({
        "action": "getmeas",
        "meastypes": ",".join(["1", "6", "10", "11"]),
        "startdate": str(start),
        "enddate": str(end),
    })
    js = _http_get_json(f"{WITHINGS_API}/measure?{q}", headers)
    if js.get("status") == 0:
        grps = js.get("body", {}).get("measuregrps", [])
        latest_by_type: Dict[int, Tuple[int, float]] = {}
        for g in grps:
            ts = g.get("date") or 0
            for m in g.get("measures", []) or []:
                mtype = m.get("type")
                val = m.get("value")
                unit = m.get("unit")
                if isinstance(mtype, int) and isinstance(val, (int, float)) and isinstance(unit, int):
                    value = float(val) * (10 ** unit)
                    prev = latest_by_type.get(mtype)
                    if prev is None or ts > prev[0]:
                        latest_by_type[mtype] = (ts, value)
        # Map types
        if 1 in latest_by_type:  # Weight kg
            payload["weight_kg"] = round(latest_by_type[1][1], 2)
        if 6 in latest_by_type:  # Fat ratio %
            payload["body_fat_percent"] = round(latest_by_type[6][1], 2)
        bp = {}
        if 10 in latest_by_type:
            bp["systolic"] = round(latest_by_type[10][1], 0)
        if 11 in latest_by_type:
            bp["diastolic"] = round(latest_by_type[11][1], 0)
        if bp:
            payload.setdefault("withings_extra", {})["bp"] = bp
except Exception:
    pass

The complete provider payload is subsequentl ...[truncated 2148 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove Withings measurement types 10 and 11 from the request unless blood-pressure reporting is an explicit feature:
    python
    "meastypes": ",".join(["1", "6"])
    
  2. If blood pressure is added as a supported feature:
    • Clearly disclose it in README.md and SKILL.md.
    • Require explicit user opt-in.
    • Include it in the documented schema and retention policy.
    • Request it only when the feature is enabled.
  3. Stop copying complete provider payloads into normalized output. Construct a strict allowlist containing only the normalized fields needed by the brief.
  4. Exclude withings_extra and other undeclared provider-specific data from output by default.
  5. Add schema validation with additionalProperties: false or equivalent checks to prevent unexpected medical fields from entering generated files.
  6. Add tests confirming that blood-pressure fields are absent unless an explicit opt-in configuration is active.
  7. Define secure output retention and deletion behavior, especially for files written under shared temporary directories.

T09 · Insecure Skill Coding Practices

Warning
Location
core/util/secrets.py:29
Finding

Rotated refresh tokens are exposed through process command-line arguments

Content
View full analysis

Vulnerability Details

File Location: core/util/secrets.py:29-33
Vulnerability Type: Sensitive information exposed in process arguments
Risk Level: Medium

Vulnerable Code

python
try:
    cmd = ["op", "item", "edit", item_title, f"{field_name}={value}"]
    if vault:
        cmd.extend(["--vault", vault])
    res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False, text=True)
    return res.returncode == 0
except Exception:
    return False

Technical Analysis

set_secret() passes the secret value directly in the argument vector of the 1Password CLI:

python
f"{field_name}={value}"

In current call sites, value can be a rotated WHOOP or Withings refresh token. Passing secrets in command-line arguments can expose them through process inspection interfaces, system audit records, endpoint monitoring products, debugging tools, crash diagnostics, or process-execution telemetry.

The use of an argument list instead of a shell correctly prevents shell-command injection. Capturing stdout and stderr also prevents ordinary terminal disclosure. Neither control prevents the secret from appearing in the child process's argument vector.

Exploitation requires local process-observation capability or access to telemetry that records command arguments. Writeback is opt-in through OPENCLAW_1P_WRITEBACK=1, which limits exposure to configurations where 1Password token rotation is enabled.

Attack Path

  1. The user enables 1Password writeback by setting OPENCLAW_1P_WRITEBACK=1.
  2. WHOOP or Withings rotates a refresh token during OAuth refresh.
  3. The connector calls set_secret() with the new refresh token.
  4. set_secret() starts:
    text
    op item edit ITEM FIELD=REFRESH_TOKEN
    
  5. A local process monitor, audit subsystem, endpoint security agent, debugger, or sufficiently privileged concurrent user records or reads the argument ...[truncated 743 chars]
Remediation
View remediation

Remediation Suggestions

  1. Do not place secret values in command-line arguments.
  2. Use a supported 1Password CLI mechanism that accepts sensitive values through standard input, a protected file descriptor, or another non-argv channel.
  3. If a temporary file is unavoidable:
    • Create it with mode 0600.
    • Place it in a user-private directory.
    • Avoid predictable filenames.
    • Delete it immediately after use.
    • Ensure the CLI does not copy its path or contents into logs.
  4. Keep shell execution disabled and continue using an argument array.
  5. Ensure process-execution telemetry and debug logging redact credential fields.
  6. Minimize the lifetime of refresh-token strings in memory and avoid including them in exception objects.
  7. Add a security test that intercepts the subprocess.run arguments and fails if a token value appears in the argument vector.
  8. Retain the existing explicit opt-in requirement for 1Password writeback.
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 (38)

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 · README.md (reported line 156)May include surrounding context.

md
4. Store in 1Password (item: `OpenClaw Oura`, fields: `client_id`, `client_secret`) or export as env vars
5. Run `python3 ./bin/health-reauth oura`

> **Note:** Oura deprecated personal access tokens in Dec 2025. OAuth is now required.

### Withings

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

This mismatch is security-relevant because the skill introduces external secret-management interactions with 1Password and token writeback behavior that are materially more sensitive than a simple local health-summary tool. Users may authorize the skill expecting read-only health aggregation, while it actually involves secret retrieval, rotation, and shelling out to external CLI tooling, increasing exposure of credentials and trust boundaries.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

This mismatch is security-relevant because the skill introduces external secret-management interactions with 1Password and token writeback behavior that are materially more sensitive than a simple local health-summary tool. Users may authorize the skill expecting read-only health aggregation, while it actually involves secret retrieval, rotation, and shelling out to external CLI tooling, increasing exposure of credentials and trust boundaries.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This mismatch is security-relevant because the skill introduces external secret-management interactions with 1Password and token writeback behavior that are materially more sensitive than a simple local health-summary tool. Users may authorize the skill expecting read-only health aggregation, while it actually involves secret retrieval, rotation, and shelling out to external CLI tooling, increasing exposure of credentials and trust boundaries.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

This mismatch is security-relevant because the skill introduces external secret-management interactions with 1Password and token writeback behavior that are materially more sensitive than a simple local health-summary tool. Users may authorize the skill expecting read-only health aggregation, while it actually involves secret retrieval, rotation, and shelling out to external CLI tooling, increasing exposure of credentials and trust boundaries.

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 · connectors/oura/__init__.py (reported line 67)May include surrounding context.

python
def _oura_refresh_access_token(refresh_token: str, client_id: str, client_secret: str) -> Dict[str, Any]:
    """Refresh Oura access token.

    Per Oura docs, client_id/client_secret can be supplied either as body params OR via HTTP Basic Auth.
    We prefer Basic Auth because it is the most widely compatible OAuth2 pattern.

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 · connectors/whoop/__init__.py (reported line 69)May include surrounding context.

python
def _oura_refresh_access_token(refresh_token: str, client_id: str, client_secret: str) -> Dict[str, Any]:
    """Refresh Oura access token.

    Per Oura docs, client_id/client_secret can be supplied either as body params OR via HTTP Basic Auth.
    We prefer Basic Auth because it is the most widely compatible OAuth2 pattern.

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 · connectors/whoop/__init__.py (reported line 142)May include surrounding context.

python
def _oura_refresh_access_token(refresh_token: str, client_id: str, client_secret: str) -> Dict[str, Any]:
    """Refresh Oura access token.

    Per Oura docs, client_id/client_secret can be supplied either as body params OR via HTTP Basic Auth.
    We prefer Basic Auth because it is the most widely compatible OAuth2 pattern.

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 · connectors/withings/__init__.py (reported line 110)May include surrounding context.

python
def _oura_refresh_access_token(refresh_token: str, client_id: str, client_secret: str) -> Dict[str, Any]:
    """Refresh Oura access token.

    Per Oura docs, client_id/client_secret can be supplied either as body params OR via HTTP Basic Auth.
    We prefer Basic Auth because it is the most widely compatible OAuth2 pattern.

Credential Access

High
Category
Privilege Escalation
Confidence
72% confidence
Finding

The unauthorized error path merges _http_error_details() into the returned payload, and _http_error_details() can include a body_snippet from the OAuth/API error response. Error bodies from auth systems sometimes echo sensitive details or token-related metadata, so returning them to callers risks unintended disclosure through logs, CLI output, or downstream consumers of the payload.

Content

Scanner excerpt · connectors/whoop/__init__.py (reported line 288)May include surrounding context.

python
payload["error"] = {"message": "refresh_failed", "detail": {k: ref.get(k) for k in ["status", "body_snippet", "error"]}}
                return payload

            payload["error"] = {"message": "unauthorized", "detail": "WHOOP access token expired. Please re-auth.", **details}
            return payload

        payload["error"] = {"message": "http_error", **details}

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 · docs/OURA.md (reported line 9)May include surrounding context.

md
- By default, if credentials are present, performs live API calls; otherwise falls back to samples.

Credentials
Personal access tokens were deprecated (Dec 2025). Use OAuth.

1) Create an Oura API application.
2) Register redirect URI (default used by this repo):

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 · docs/WHOOP.md (reported line 7)May include surrounding context.

md
- CLI: `./bin/whoop --date YYYY-MM-DD`
- Auth helper: `./bin/whoop-auth` (prints auth URL; can exchange code for tokens)
- Reads credentials from 1Password item **"OpenClaw Whoop"** (recommended) or env vars.
  - Access token: field `token` or env `WHOOP_ACCESS_TOKEN`
  - Refresh token: field `refresh_token` (back-compat: `refresh_password`) or env `WHOOP_REFRESH_TOKEN`
  - Client creds (for refresh): fields `client_id` / `client_secret` or env `WHOOP_CLIENT_ID` / `WHOOP_CLIENT_SECRET`
- If no access token is available, falls back to sample data.

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 · docs/1PASSWORD_CONVENTIONS.md (reported line 12)May include surrounding context.

md
- Access token: field `token` or env `WHOOP_ACCESS_TOKEN`
  - Refresh token: field `refresh_token` (back-compat: `refresh_password`) or env `WHOOP_REFRESH_TOKEN`
  - Client creds (for refresh): fields `client_id` / `client_secret` or env `WHOOP_CLIENT_ID` / `WHOOP_CLIENT_SECRET`
- If no access token is available, falls back to sample data.

Credentials
WHOOP uses OAuth 2.0 (authorization code flow).

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 · docs/1PASSWORD_CONVENTIONS.md (reported line 21)May include surrounding context.

md
- Access token: field `token` or env `WHOOP_ACCESS_TOKEN`
  - Refresh token: field `refresh_token` (back-compat: `refresh_password`) or env `WHOOP_REFRESH_TOKEN`
  - Client creds (for refresh): fields `client_id` / `client_secret` or env `WHOOP_CLIENT_ID` / `WHOOP_CLIENT_SECRET`
- If no access token is available, falls back to sample data.

Credentials
WHOOP uses OAuth 2.0 (authorization code flow).

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 · docs/WHOOP.md (reported line 10)May include surrounding context.

md
- Access token: field `token` or env `WHOOP_ACCESS_TOKEN`
  - Refresh token: field `refresh_token` (back-compat: `refresh_password`) or env `WHOOP_REFRESH_TOKEN`
  - Client creds (for refresh): fields `client_id` / `client_secret` or env `WHOOP_CLIENT_ID` / `WHOOP_CLIENT_SECRET`
- If no access token is available, falls back to sample data.

Credentials
WHOOP uses OAuth 2.0 (authorization code flow).

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 · docs/WHOOP.md (reported line 34)May include surrounding context.

md
- Access token: field `token` or env `WHOOP_ACCESS_TOKEN`
  - Refresh token: field `refresh_token` (back-compat: `refresh_password`) or env `WHOOP_REFRESH_TOKEN`
  - Client creds (for refresh): fields `client_id` / `client_secret` or env `WHOOP_CLIENT_ID` / `WHOOP_CLIENT_SECRET`
- If no access token is available, falls back to sample data.

Credentials
WHOOP uses OAuth 2.0 (authorization code flow).

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 · docs/WITHINGS.md (reported line 31)May include surrounding context.

md
- Access token: field `token` or env `WHOOP_ACCESS_TOKEN`
  - Refresh token: field `refresh_token` (back-compat: `refresh_password`) or env `WHOOP_REFRESH_TOKEN`
  - Client creds (for refresh): fields `client_id` / `client_secret` or env `WHOOP_CLIENT_ID` / `WHOOP_CLIENT_SECRET`
- If no access token is available, falls back to sample data.

Credentials
WHOOP uses OAuth 2.0 (authorization code flow).

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 · docs/WITHINGS.md (reported line 38)May include surrounding context.

md
- Access token: field `token` or env `WHOOP_ACCESS_TOKEN`
  - Refresh token: field `refresh_token` (back-compat: `refresh_password`) or env `WHOOP_REFRESH_TOKEN`
  - Client creds (for refresh): fields `client_id` / `client_secret` or env `WHOOP_CLIENT_ID` / `WHOOP_CLIENT_SECRET`
- If no access token is available, falls back to sample data.

Credentials
WHOOP uses OAuth 2.0 (authorization code flow).

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 · README.md (reported line 34)May include surrounding context.

export OPENCLAW_1P_VAULT="YourVault" # your vault name

text

Create items in your vault (see `docs/1PASSWORD_CONVENTIONS.md` for field details):
- `OpenClaw Whoop` → `client_id`, `client_secret`, `token`, `refresh_token`
- `OpenClaw Oura` → `client_id`, `client_secret`, `token`, `refresh_token`
- `OpenClaw Withings` → `client_id`, `client_secret`, `access_token`, `refresh_token`, `user_id`

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The README explicitly instructs users that OAuth access and refresh tokens will be automatically persisted to a local file containing access to sensitive health data. Even with restrictive file permissions, local disk storage increases the risk of credential exposure through backups, endpoint compromise, multi-user systems, or accidental disclosure, and the documentation does not clearly warn users about this tradeoff or make secure storage opt-in.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · README.md (reported line 104)May include surrounding context.

md
## Token persistence

Refreshed tokens persist to `~/.openclaw/secrets/health_tokens.json` (chmod 600). If a provider rotates your refresh token during a refresh, the new one is saved immediately. You should never need to re-auth unless you revoke access at the provider.

Override location: `OPENCLAW_LOCAL_SECRETS_PATH=/path/to/health_tokens.json`

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill advertises and instructs use of sensitive capabilities including environment-variable access, local file reads/writes, network access, and shell execution, yet the manifest shown in SKILL.md declares no explicit tool scope. That creates an authorization and review gap: operators cannot easily verify what the skill needs, and an agent runtime may grant broader powers than users expect when handling secrets and external services.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The skill instructs persistent storage of API client secrets, access tokens, and refresh tokens in a 1Password vault and also elsewhere locally, which increases the lifetime and recoverability of credentials. Although persistence is often necessary for OAuth-based integrations, retaining multiple high-value secrets creates a broader attack surface if the vault, workstation, or agent environment is compromised.

Content

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

export OPENCLAW_1P_VAULT="Assistant" # or your vault name

text

Create items in your vault with these titles and fields:
- `OpenClaw Whoop` → `client_id`, `client_secret`, `token`, `refresh_token`
- `OpenClaw Oura` → `client_id`, `client_secret`, `token`, `refresh_token`
- `OpenClaw Withings` → `client_id`, `client_secret`, `access_token`, `refresh_token`, `user_id`

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill explicitly states that refreshed tokens are saved to ~/.openclaw/secrets/health_tokens.json but provides no warning about the sensitivity of bearer and refresh tokens or the filesystem protections required. Storing long-lived credentials on disk without strong guidance can lead to token theft from backups, shared accounts, permissive file permissions, or malware running under the same user.

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 · connectors/whoop/__init__.py (reported line 12)May include surrounding context.

python
from core.util.local_secrets import get_local_secret, set_local_secret

# WHOOP Developer API base URLs
WHOOP_API_V2 = "https://api.prod.whoop.com/developer/v2"
WHOOP_TOKEN_URL = "https://api.prod.whoop.com/oauth/oauth2/token"

Static analysis

No suspicious patterns detected.