Back to skill

Security audit

AI健身教练

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real fitness coach, but it needs review because it stores sensitive fitness and conversation data persistently and includes weakly scoped local-file and publishing behaviors.

Review before installing if you plan to run the Python prototype or enable integrations. Treat health, workout, body-metric, and conversation logs as sensitive; avoid using untrusted user_id values; do not put live secrets in tracked config.yaml; and do not run the GitHub publishing script from a repository containing credentials or private data.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
memory_manager.py:17
Finding

User-controlled identifier permits path traversal outside the intended data directory

Content
View full analysis

Vulnerability Details

File Location: memory_manager.py:17-32, 67-74, 98-123, 145-163, 235-265
Vulnerability Type: Path traversal and arbitrary JSON file access
Risk Level: High

Vulnerable Code

python
def __init__(self, data_dir: str = None):
    if data_dir is None:
        data_dir = Path.home() / ".claude" / "skills" / "fitness-coach" / "data"
    self.data_dir = Path(data_dir)
    self.users_dir = self.data_dir / "users"
    self.logs_dir = self.data_dir / "logs"

    self.users_dir.mkdir(parents=True, exist_ok=True)
    self.logs_dir.mkdir(parents=True, exist_ok=True)

def _get_user_file(self, user_id: str) -> Path:
    return self.users_dir / f"{user_id}.json"

def _get_logs_file(self, user_id: str) -> Path:
    return self.logs_dir / f"{user_id}_logs.json"
python
def load_user_profile(self, user_id: str) -> Optional[UserProfile]:
    file_path = self._get_user_file(user_id)
    if not file_path.exists():
        return None

    with open(file_path, 'r', encoding='utf-8') as f:
        data = json.load(f)
python
def save_user_profile(self, profile: UserProfile):
    file_path = self._get_user_file(profile.user_id)

    data = {
        "user_id": profile.user_id,
        "name": profile.name,
        "target_weight": profile.target_weight,
        "exercise_frequency": profile.exercise_frequency,
        "diet_preference": profile.diet_preference,
        "goal_type": profile.goal_type,
        "personality_insights": profile.personality_insights,
        "created_at": profile.created_at.isoformat(),
        "updated_at": datetime.now().isoformat()
    }

    with open(file_path, 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=2)
python
def add_conversation(self, user_id: str, role: str, content: str):
    memory_file = self.users_dir / f"{user_id}_memory.json"

    memory = {"sho
...[truncated 2426 chars]
Remediation
View remediation

Remediation Suggestions

  • Validate every user_id at the trust boundary using a strict allowlist, such as ASCII letters, digits, underscores, and hyphens with a short maximum length.
  • Reject absolute paths, path separators, . components, and .. components.
  • Resolve the final path and verify that it remains beneath the expected directory before every read or write.
  • Use a generated internal identifier instead of using external account identifiers directly as filenames.
  • Centralize safe path construction so conversation, profile, and workout-log paths receive identical validation.
  • Add tests for absolute paths, nested traversal, encoded separators, repeated separators, and platform-specific Windows path forms.

Example defensive pattern:

python
import re

USER_ID_PATTERN = re.compile(r"^[A-Za-z0-9_-]{1,64}$")

def _safe_user_path(base: Path, user_id: str, suffix: str) -> Path:
    if not USER_ID_PATTERN.fullmatch(user_id):
        raise ValueError("Invalid user identifier")

    base = base.resolve()
    candidate = (base / f"{user_id}{suffix}").resolve()

    if candidate.parent != base:
        raise ValueError("Path escapes the data directory")

    return candidate

T09 · Insecure Skill Coding Practices

Warning
Location
memory_manager.py:98
Finding

Sensitive health information and conversation history are automatically stored in plaintext

Content
View full analysis

Vulnerability Details

File Location: memory_manager.py:98-123, 125-163, 231-265
Vulnerability Type: Unprotected storage of sensitive personal data
Risk Level: Medium

Vulnerable Code

python
def save_user_profile(self, profile: UserProfile):
    file_path = self._get_user_file(profile.user_id)

    data = {
        "user_id": profile.user_id,
        "name": profile.name,
        "target_weight": profile.target_weight,
        "exercise_frequency": profile.exercise_frequency,
        "diet_preference": profile.diet_preference,
        "goal_type": profile.goal_type,
        "personality_insights": profile.personality_insights,
        "created_at": profile.created_at.isoformat(),
        "updated_at": datetime.now().isoformat()
    }

    if profile.body_metrics:
        data["body_metrics"] = {
            "height": profile.body_metrics.height,
            "weight": profile.body_metrics.weight,
            "body_fat": profile.body_metrics.body_fat,
            "estimated_body_fat": profile.body_metrics.estimated_body_fat
        }

    with open(file_path, 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=2)
python
def add_workout_log(self, log: WorkoutLog):
    logs = self.load_workout_logs(log.user_id)
    logs.append({
        "log_id": log.log_id,
        "user_id": log.user_id,
        "training_date": log.training_date.isoformat(),
        "focus": log.focus,
        "exercises": [
            {
                "name": ex.name,
                "sets": ex.sets,
                "reps": ex.reps,
                "weight": ex.weight
            }
            for ex in log.exercises
        ],
        "completion_rate": log.completion_rate,
        "user_feedback": log.user_feedback,
        "feeling_score": log.feeling_score,
        "weight_logged": log.weight_logged,
        "daily_report": log.d
...[truncated 2686 chars]
Remediation
View remediation

Remediation Suggestions

  • Obtain explicit user consent before enabling persistent profile, workout, or conversation storage.
  • Collect and retain only fields required for the requested coaching function.
  • Create the data directory with mode 0700 and individual data files with mode 0600 on supported systems.
  • Use atomic file creation with explicit permissions rather than relying on the process umask.
  • Store sensitive records through an operating-system credential or encrypted-storage facility where available.
  • Add configurable retention limits and a user-accessible operation to inspect, export, and delete all stored information.
  • Make conversation persistence optional and redact secrets, medical details, and unrelated sensitive content before writing.
  • Document the exact storage location, retained fields, retention period, and cloud-backup implications.

T09 · Insecure Skill Coding Practices

Warning
Location
publish-to-github.sh:7
Finding

Plaintext credentials can be accidentally published through the bundled GitHub workflow

Content
View full analysis

Vulnerability Details

File Location: config.yaml:4-16, README.md:128-149, publish-to-github.sh:7-18
Vulnerability Type: Secret exposure through repository-tracked configuration and public publishing
Risk Level: Medium

Vulnerable Code

The project configuration contains fields intended to receive live credentials:

yaml
llm:
  provider: "zhipu"
  api_key: ""
  model: "glm-4-flash"
  temperature: 0.8
  max_tokens: 2000

feishu:
  enabled: false
  app_id: ""
  app_secret: ""
  base_url: "https://open.feishu.cn/open-apis"

The documentation directs users to place credentials into that file:

yaml
llm:
  provider: "zhipu"
  api_key: "your-api-key"
  model: "glm-4-flash"
yaml
feishu:
  enabled: true
  app_id: "your-app-id"
  app_secret: "your-app-secret"

The publishing script pushes the current branch without checking for secrets:

bash
read GITHUB_USERNAME

git remote add origin https://github.com/${GITHUB_USERNAME}/fitness-coach.git

git branch -M main
git push -u origin main

The same script instructs the operator to create a public repository before executing the push.

Technical Analysis

config.yaml is part of the project tree and is the documented location for an LLM API key and a Feishu application secret. If an operator follows the documentation, the live credentials may be placed directly into a repository-tracked file.

The bundled publishing workflow then pushes the active branch to GitHub without checking whether the configuration contains secrets. The script also directs the operator to use a public repository. There is no demonstrated .gitignore protection, pre-push secret scan, or environment-variable indirection.

Even if a secret is removed in a later commit, it can remain recoverable from Git history.

Attack Path

  1. An operator enters a live LLM API key or Feishu application secret into `conf ...[truncated 1063 chars]
Remediation
View remediation

Remediation Suggestions

  • Replace live-secret fields in repository files with environment-variable references or secret-store identifiers.
  • Rename the distributed file to config.example.yaml and require users to create an untracked local configuration.
  • Add the real configuration file, local data directories, logs, exports, and environment files to .gitignore.
  • Add a pre-commit and pre-push secret scanner, such as Gitleaks or an equivalent reviewed tool.
  • Make the publishing script abort when credential-like values are found.
  • Do not require public repository visibility.
  • If a credential was ever committed, revoke and rotate it immediately, then remove it from the entire Git history.
  • Apply provider-side restrictions, minimal scopes, spending limits, and short-lived credentials wherever supported.

T08 · Insecure Dependencies

Note
Location
openclaw.yaml:23
Finding

Runtime dependencies use open-ended version ranges without reproducible integrity controls

Content
View full analysis

Vulnerability Details

File Location: openclaw.yaml:23-26
Vulnerability Type: Unpinned third-party dependencies
Risk Level: Low

Vulnerable Code

yaml
dependencies:
  python:
    - "requests>=2.28.0"
    - "pyyaml>=6.0"

Technical Analysis

The dependency declarations specify minimum versions but no upper bounds, exact versions, lock file, or package hashes. A future installation can therefore resolve to package releases that were not present when the Skill was reviewed.

This reduces build reproducibility and expands the supply-chain trust boundary to all future compatible releases. The inspected runtime code does not import yaml, making the declared pyyaml dependency unnecessary for the current implementation and increasing exposure without a demonstrated functional need.

No evidence was found that either named package is malicious. The issue is the unsafe dependency resolution policy rather than a confirmed compromised package.

Attack Path

  1. The Skill is installed in a fresh environment.
  2. The package manager resolves the open-ended dependency specifications.
  3. It selects a later release that was not reviewed with this project.
  4. If that release is compromised, malicious installation or runtime behavior executes with the privileges of the Skill environment.

Impact Assessment

A compromised dependency could potentially read Skill data, access environment variables, make network requests, or execute code with the same operating-system permissions as the Python process.

This finding does not demonstrate an existing compromise. It identifies avoidable future supply-chain exposure and non-reproducible installation behavior.

Remediation
View remediation

Remediation Suggestions

  • Remove pyyaml unless runtime functionality actually requires it.
  • Pin each required dependency to a reviewed exact version.
  • Use a lock file and cryptographic hashes for reproducible installations.
  • Automate vulnerability monitoring and controlled dependency updates.
  • Test dependency upgrades before publishing a new Skill version.
  • Prefer an isolated virtual environment with only the minimum packages required by the declared functionality.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (29)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents a user-facing fitness coaching skill whose purpose is planning workouts, logging progress, and offering guidance. The supplied code does not implement coaching, planning, accountability logic, or fitness advice. Instead, it primarily provides an integration layer for Feishu multi-dimensional tables: obtaining access tokens, preparing record payloads, adding records, exporting CSV files, and printing import/setup guides. While the data fields are fitness-related, the primary behavior is external data synchronization/storage tooling, which is a materially different and undeclared capability. Therefore this is a clear description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents a user-facing fitness coaching skill, but the supplied code does not implement any fitness planning, workout tracking, check-ins, or coaching behavior. Instead, it is an operational deployment script for publishing a repository to GitHub and instructing the user how to install the skill afterward. This is a materially different primary purpose and introduces undeclared capabilities related to source control and public code publishing.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown file presents the skill name, usage instructions, safety statements, and user interaction examples exclusively in Chinese. Under the policy for natural-language violations, forcing a specific language without user opt-in is a reportable locale/language issue unless the regional constraint is explicitly justified.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · DESIGN.md (reported line 229)May include surrounding context.

md
├── feishu_integration.py    # 飞书集成
├── fitness_coach.py         # 主程序
│
├── auto-deploy.sh           # 自动部署脚本
└── data/                    # 数据存储目录
    ├── users/               # 用户档案
    │   └── {user_id}.json

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The documented behavior extends beyond a coaching assistant into software deployment and distribution, creating a mismatch between the declared purpose and actual capabilities. This increases risk because users may grant trust or permissions appropriate for a fitness assistant while the skill also contains operational actions that can affect external systems.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

The design explicitly documents an automatic deployment script tied to GitHub and ClawHub publication, indicating operational autonomy beyond the fitness assistant's intended role. In this context, autonomous deployment behavior is risky because it can trigger external changes and publication workflows that users would not expect from a coaching skill.

Content

Scanner excerpt · DESIGN.md (reported line 823)May include surrounding context.

仓库地址:https://github.com/dexterqiu-collab/fitness-coach

自动部署脚本:auto-deploy.sh

bash
#!/bin/bash

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The design includes automated GitHub repository creation and code publication behavior that is unrelated to the core fitness-coaching function. In an agent skill context, adding deployment and publication capabilities broadens the attack surface and could enable unintended exfiltration of code, data, or credentials if invoked or adapted unsafely.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

The design includes a direct external API call to GitHub using an authorization token to create repositories. Even though shown as a deployment script example, embedding token-driven outbound actions in the skill design can normalize or encourage capabilities that transmit data or perform external side effects beyond the assistant's core function.

Content

Scanner excerpt · DESIGN.md (reported line 830)May include surrounding context.

md
# 自动化部署到GitHub和ClawHub

# 1. 创建GitHub仓库
curl -X POST \
  -H "Authorization: token ${GITHUB_TOKEN}" \
  "https://api.github.com/user/repos" \
  -d '{"name":"fitness-coach","private":false}'

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

The GitHub API endpoint reference reinforces that the skill ecosystem includes external transmission and remote system interaction not needed for fitness coaching. In context with the auto-deploy script, this indicates unnecessary outbound integration that could be repurposed for data leakage or unauthorized publication.

Content

Scanner excerpt · DESIGN.md (reported line 832)May include surrounding context.

md
# 1. 创建GitHub仓库
curl -X POST \
  -H "Authorization: token ${GITHUB_TOKEN}" \
  "https://api.github.com/user/repos" \
  -d '{"name":"fitness-coach","private":false}'

# 2. 推送代码

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill encourages broad natural-language invocation with generic phrases such as a normal greeting and a desire to start fitness. In hosts that auto-route or trigger skills from ordinary chat text, this can cause unintended activation, unexpected collection of personal health/body data, or confusion about whether the user intended to invoke the skill at all.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The README states that training data can be automatically synced to Feishu, but it does not clearly disclose that user health/workout data will be transmitted to a third-party service or explain the privacy implications. In a fitness-coaching skill, this is more sensitive than generic telemetry because workout history, body metrics, and progress logs may qualify as sensitive personal data and users may not expect external sharing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README explicitly promises automatic workout recording and synchronization to Feishu tables, but provides no notice about what personal data is collected, where it is stored, who can access it, or how consent is obtained. In a fitness coaching skill, training history and progress logs can reveal health-related and behavioral data, so omitting privacy and data-handling warnings creates a real user-safety and compliance risk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · feishu_integration.py (reported line 39)May include surrounding context.

python
}

        try:
            response = requests.post(url, json=payload)
            data = response.json()

            if data.get("code") == 0:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The code synchronizes sensitive fitness and health-related profile data, including body metrics, training logs, and free-form user feedback, to an external Feishu system without any visible consent check, notice, or data-minimization control at the sync call sites. In a fitness coaching skill, this data is privacy-sensitive, and silent export to a third party can violate user expectations, internal policy, or applicable privacy requirements.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code presents core onboarding and coaching interactions entirely in Chinese, starting from the module description and continuing through all user-visible responses. That can violate a language/locale policy when the skill forces a specific language without giving users a choice or documenting a justified locale restriction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The module's natural-language documentation is entirely in Chinese, including the top-level description and class/docstring text, which indicates a fixed language assumption. There is no accompanying indication that the user can choose language or that the skill is intentionally limited to a Chinese-speaking context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code persists sensitive fitness data, body metrics, workout logs, and conversation history to predictable local JSON files under the user's home directory without any visible consent, disclosure, encryption, or access control. In a fitness-coach skill, this data can reveal health-related and behavioral information, so silent storage increases privacy and confidentiality risk if the host system, backups, or other local processes are accessed.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest describes a fitness planning and accountability coach, but this script performs Git/GitHub repository setup and publication operations. Publishing source code to a public GitHub repository is not a direct or obvious requirement of delivering workout plans, logging, check-ins, or fitness guidance.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module title and class docstring describe the skill entirely in Chinese, indicating a fixed language experience with no visible opt-in or alternative locale support. Under the policy rule, forcing a specific language without user choice is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This planner generates workout prescriptions with specific exercises, sets, reps, and weekly frequency, including higher-risk movements like squats, bench press, Romanian deadlifts, and dips, without screening for injuries, medical conditions, experience limits, or explicit safety warnings. In a fitness-coaching skill, that context makes the issue more dangerous because users may treat the output as personalized guidance and follow unsafe recommendations, leading to strain, aggravation of existing conditions, or injury.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

整份技能说明与示例均以中文固定呈现,未说明是否支持其他语言,也未给予用户语言/地区选择。按规则,若技能或文档强制特定语言且无用户选择或合理限定,属于自然语言政策风险。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

A natural-language policy issue exists because the skill documentation appears to force a specific language/locale by default. The file does not indicate that users may choose another language or that the Chinese-only presentation is required for a region-specific purpose.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The natural-language content in the configuration is entirely Chinese, and a locale-specific value is hardcoded with rest_days: ["周日"]. This indicates the skill is oriented to a specific language/locale without any visible opt-in, alternative locale support, or documented justification in this file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The data model uses Chinese-only natural-language values and comments throughout, including enum values such as "减脂", "增肌", and schedule examples like "周一", "周三", "周五". This creates a locale/language constraint without any documented user choice or opt-in, which matches the policy category for forced language behavior.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.