Back to skill

Security audit

Strong Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a coherent Strong workout API helper, but its normal instructions can expose account access tokens in tool output.

Review before installing. This skill needs your Strong username and password and can read detailed workout/account data. Do not let an agent run login or refresh_token unless you intentionally want raw tokens printed; normal data commands should authenticate internally. Use sharing commands only when you mean to create externally usable links for workout templates or logs.

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

Error
Location
scripts/strong_runner.py:92
Finding

Authentication Tokens Exposed Through Standard Output

Content
View full analysis

Vulnerability Details

File Location: scripts/strong_runner.py:92-115
Vulnerability Type: Sensitive authentication token disclosure
Risk Level: High

The login command writes the access token and refresh token directly to standard output. The refresh_token command also prints the complete refresh response, which is documented as containing replacement access and refresh tokens.

python
def cmd_login(_args):
    access_token, refresh_token, user_id = _login()
    _output({
        "accessToken": access_token,
        "refreshToken": refresh_token,
        "userId": user_id,
    })


def cmd_refresh_token(args):
    access_token, refresh_token, _user_id = _login()
    resp = _request(
        "POST",
        "/auth/login/refresh",
        headers=_auth_headers(access_token),
        body={
            "accessToken": access_token,
            "refreshToken": refresh_token,
        },
    )
    _output(resp)

Technical Analysis

Access and refresh tokens are bearer credentials: possession may be sufficient to authenticate as the user. Printing them to stdout exposes them beyond the runner's in-memory authentication boundary. In an agent environment, stdout commonly becomes tool output and may be retained in conversation context, execution traces, observability systems, or application logs.

This disclosure is unnecessary for normal data-fetching operations because each data command calls _login() internally and uses the resulting access token without requiring manual token management. The implementation therefore grants token visibility to the caller even though the declared workflow does not require that privilege.

The issue also conflicts with SKILL.md, which says that raw tokens must never be exposed to the user.

Attack Path

  1. A user or agent invokes python3 scripts/strong_runner.py login or refresh_token.
  2. The runner authenticates using `STRONG_USERNA ...[truncated 1147 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove or disable the public login and refresh_token subcommands when the runner is used through an agent.
  • Keep access and refresh tokens entirely in memory and return only a non-sensitive success result, such as the authenticated user ID.
  • If direct token retrieval is essential for a separate administrative use case, place it behind an explicit high-friction opt-in option and display a security warning. Do not enable that option in agent-driven workflows.
  • Redact authentication fields recursively before serializing any authentication response:
    • accessToken
    • refreshToken
    • Authorization
    • equivalent case or naming variants
  • Ensure logging and error-handling layers never record request headers, login bodies, passwords, or token-bearing responses.
  • Revoke tokens that may already have been captured and review agent, terminal, CI, and observability logs for prior exposure.
  • Add automated tests asserting that stdout and stderr never contain raw access tokens, refresh tokens, passwords, or authorization headers.

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:443
Finding

Skill Instructions Trigger a Redundant Token-Producing Login Command

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:443-448
Vulnerability Type: Unsafe credential-handling workflow
Risk Level: High

The model invocation instructions tell the agent to invoke login implicitly before data-fetching commands, even though the runner already authenticates inside every such command. The same instruction simultaneously says never to expose raw tokens, but the login command prints both tokens to stdout.

markdown
## Model invocation note

The agent should invoke this skill whenever the user asks about their Strong app workouts,
exercises, templates, workout history, tags, folders, or training data. The agent should
call `login` implicitly before any data-fetching command and never expose raw tokens to the
user. Prefer `list_logs` and `list_templates` for broad queries, and `get_log --log_id ...`
or `get_template --template_id ...` for specific lookups.

Technical Analysis

The instruction creates a direct contradiction in the skill's security model. Calling login produces raw token output, while the following clause prohibits exposing that output. Even if the agent suppresses tokens in its natural-language answer, the tokens have already crossed into tool output and may be retained by the orchestration layer.

The additional login is not required for functionality. Functions such as cmd_get_profile, cmd_list_logs, and cmd_list_templates call _login() internally. Requiring a separate invocation therefore increases credential exposure and network activity without providing a corresponding capability or least-privilege benefit.

Attack Path

  1. A user asks the agent for Strong workout or training data.
  2. The agent loads and follows the model invocation note.
  3. Before running the requested data command, the agent invokes login.
  4. cmd_login writes the access token and refresh token into captured tool output.
  5. The agent invokes the requested command, w ...[truncated 940 chars]
Remediation
View remediation

Remediation Suggestions

  • Replace the instruction with guidance to invoke only the requested data command because authentication is already handled internally.
  • Explicitly prohibit agents from invoking login or refresh_token unless the user specifically requests an authentication diagnostic and understands the disclosure risk.
  • Align documentation with implementation by stating that tokens must remain internal to the runner and must never appear in stdout, stderr, model context, or user-facing responses.
  • Remove token-shaped examples from normal workflow documentation where they could encourage token retrieval.
  • Add a documentation and integration test that simulates an agent data request and verifies that only one command is executed and no token-producing command is called.
  • After changing the instructions, implement the runner-side token redaction described in the related finding so safety does not rely solely on agent compliance.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description understates actual behavior: the skill can fetch profile data, create shareable links, and retrieve shared-link objects, while claiming broader 'manage' functionality it does not implement. This mismatch is dangerous because users and orchestrators may grant or invoke the skill under inaccurate assumptions, leading to unexpected data exposure or sharing actions.

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

2. Refresh Token

Renew an expired access token without re-entering credentials.

bash
python3 scripts/strong_runner.py refresh_token

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

2. Refresh Token

Renew an expired access token without re-entering credentials.

bash
python3 scripts/strong_runner.py refresh_token

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/strong_runner.py (reported line 372)May include surrounding context.

python
## 2. Refresh Token

Renew an expired access token without re-entering credentials.

```bash
python3 scripts/strong_runner.py refresh_token

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README states the skill is invoked automatically when it 'matches your request' without defining narrow trigger boundaries. In a skill that can access sensitive fitness data and uses stored account credentials, broad invocation language increases the risk of the agent calling it for loosely related prompts and unnecessarily exposing or acting on private user data.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill requires environment-variable credentials and performs outbound network access, but it does not declare an explicit tool scope such as permissions or allowed-tools. That weakens policy enforcement and reviewability, making it easier for a caller or runtime to invoke sensitive capabilities without clear prior approval boundaries.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill handles sensitive health-adjacent and account-linked data but does not present a clear privacy warning at the point of invocation guidance. Without prominent disclosure, users may not realize their account credentials and detailed workout history will be transmitted to a third-party service during execution.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The invocation guidance is broad enough that an agent may call the skill for generic fitness questions whenever they mention workouts or training data. In context, this can trigger unnecessary authentication and retrieval of sensitive personal fitness/account data without a clearly scoped user request.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill exposes a standalone login command that prints the access token and refresh token to stdout, which materially expands the capability beyond ordinary workout-data retrieval. In an agent/tooling context, stdout is often captured in logs, traces, transcripts, or passed to other components, so this creates a credential-exposure path that can enable replayed API access to the user's Strong account.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Printing access and refresh tokens to stdout is dangerous because these secrets can be harvested from terminal history, orchestration logs, agent transcripts, or downstream tool output. A stolen refresh token can allow long-lived unauthorized access even after the initial access token expires, making this more severe in an agent skill than in an interactive local-only CLI.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The share_template and share_log commands generate shareable links for potentially sensitive workout data, and the script provides no friction, confirmation, or warning before doing so. In an agent setting, a user may not realize that generating such links can create externally accessible URLs that expose private health/fitness information beyond the authenticated session.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The manifest claims the skill can 'manage folders, tags, measurements, and widgets,' which implies create/update/delete or other modification actions. In the code, these areas are limited to read-only listing endpoints (list_folders, list_tags, list_widgets) and measurement retrieval/search, so the documented behavior overstates what is actually implemented.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.