Ai Coach

Security checks across malware telemetry and agentic risk

Overview

This is a real triathlon coaching skill, but it handles fitness credentials and uploads plan content with weak credential boundaries.

Review before installing. Use this only if you are comfortable granting access to TrainingPeaks cookies, Garmin credentials, health metrics, workout history, weather lookups, and external IMA note uploads. Replace hardcoded IMA credentials with your own secure configuration, avoid saving Garmin passwords in plaintext, restrict file permissions on any cookie/token files, and inspect where cached health and plan data will be written.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (15)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"""同步 TrainingPeaks 数据"""
    try:
        python_path = os.path.expanduser("~/.miniconda3/bin/python3")
        result = subprocess.run(
            [python_path, str(TP_SKILL_DIR / "scripts/tp.py"), "workouts", 
             (datetime.now() - timedelta(days=90)).strftime("%Y-%m-%d"),
             datetime.now().strftime("%Y-%m-%d"), "--json"],
Confidence
88% confidence
Finding
result = subprocess.run( [python_path, str(TP_SKILL_DIR / "scripts/tp.py"), "workouts", (datetime.now() - timedelta(days=90)).strftime("%Y-%m-%d"), datet

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"""获取体能状态"""
    try:
        python_path = os.path.expanduser("~/.miniconda3/bin/python3")
        result = subprocess.run(
            [python_path, str(TP_SKILL_DIR / "scripts/tp.py"), "fitness", "--json"],
            capture_output=True, text=True, timeout=30
        )
Confidence
87% confidence
Finding
result = subprocess.run( [python_path, str(TP_SKILL_DIR / "scripts/tp.py"), "fitness", "--json"], capture_output=True, text=True, timeout=30 )

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Content
start_date = (datetime.now() - timedelta(days=90)).strftime("%Y-%m-%d")
    
    cmd = f"{PYTHON} {TP_SCRIPT} workouts {start_date} {end_date} --json"
    result = os.popen(cmd).read()
    
    output_file = AI_COACH_DIR / "data" / "tp_workouts.json"
    output_file.parent.mkdir(exist_ok=True)
Confidence
90% confidence
Finding
result = os.popen(cmd).read()

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Content
def sync_fitness():
    """同步体能数据 (CTL/ATL/TSB)"""
    cmd = f"{PYTHON} {TP_SCRIPT} fitness --days 90 --json"
    result = os.popen(cmd).read()
    
    output_file = AI_COACH_DIR / "data" / "tp_fitness.json"
    with open(output_file, 'w') as f:
Confidence
90% confidence
Finding
result = os.popen(cmd).read()

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The script saves Garmin credentials, including the password, directly to a local JSON file in plaintext. Any local user, malware, backup system, or accidental repository inclusion could expose the account credentials and enable unauthorized access to the user's Garmin account.

Context-Inappropriate Capability

Medium
Confidence
97% confidence
Finding
The module contains credential-based Garmin account access and token loading inside a training plan component, which is a sensitive capability unrelated to simple plan generation. It reads credentials, loads a token from /tmp, and authenticates to a third-party service, creating risk of credential misuse, token abuse, and unauthorized account access if the module or runtime is compromised.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
Executing an external trainingpeaks script gives this file a broad capability beyond data formatting or plan generation, increasing the consequences of path hijacking or tampered dependencies. In an unknown-purpose skill with no metadata justifying such execution, this is a meaningful security concern because the module implicitly trusts adjacent code and local runtime setup.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The fitness status retrieval path similarly relies on subprocess execution, which is more powerful than necessary for a planner and creates hidden trust in external code. The danger is not classic command injection but the broadened execution surface and the possibility that a modified sibling script changes behavior or exfiltrates data.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
This training-plan module directly accesses Garmin credentials and retrieves sensitive health data such as sleep, stress, HRV, and readiness, which is not necessary for a minimal local planner and materially expands the data-collection surface. Pulling this data from a credentialed third-party account increases privacy risk and exposes highly sensitive personal health information if the module is reused in contexts where users did not clearly consent to such access.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The code writes credentials to a local JSON file without any warning that the password will be stored in plaintext. This increases the likelihood of unsafe user behavior and silent credential exposure through local compromise, backups, or shared systems.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The code silently reads Garmin credentials from user_config.json or environment variables and uses them for third-party authentication without any local notice, consent flow, or minimization. This is dangerous because secrets may be consumed unexpectedly by a skill, and in this context the static finding is reinforced by actual account-login behavior nearby.

Missing User Warnings

High
Confidence
99% confidence
Finding
The script contains hardcoded IMA API credentials directly in source code and uses them to authenticate outbound requests. Anyone with access to the repository, logs, backups, or distributed copies of the skill can recover and misuse these secrets to access or abuse the associated account/API, and hardcoded secrets are difficult to rotate safely once exposed.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The code reads Garmin credentials from config or environment and performs remote account access without any visible user-facing disclosure or consent gate. Because the retrieved data includes sensitive health metrics, silent credential use materially increases privacy harm and the chance of unintended account access.

Missing User Warnings

Low
Confidence
89% confidence
Finding
The module makes a third-party HTTP request to wttr.in without informing the user that weather and implied location context are being shared externally. Even with a hard-coded city, undisclosed outbound requests create transparency and privacy issues and can surprise users in restricted environments.

Session Persistence

Medium
Category
Rogue Agent
Content
**方式A(推荐)**:写入文件
```bash
mkdir -p ~/.trainingpeaks
echo "你的cookie值" > ~/.trainingpeaks/cookie
chmod 600 ~/.trainingpeaks/cookie
```
Confidence
87% confidence
Finding
mkdir -p ~/.trainingpeaks echo "你的cookie值" > ~/.trainingpeaks/cookie chmod 600 ~/.trainingpeaks/cookie ``` **方式B**:设置环境变量 ```bash export TP_AUTH_COOKIE="你的cookie值" ``` > ⚠️ **安全提示**:cookie 文件包含认证凭证,

VirusTotal

VirusTotal findings are pending for this skill version.

View on VirusTotal