Back to skill

Security audit

GrowthLoop – Plan & Habit Tracker

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent habit tracker, but it automatically checks and mutates personal habit data across conversations and includes under-described external/scheduled reminder paths that users should review before installing.

Install only if you are comfortable with a Chinese-first habit tracker that stores habit goals, notes, reminders, and some coaching conversation history locally in plaintext. Review or disable the every-conversation heartbeat behavior if you do not want unrelated chats to access or update habit reminder state, and avoid enabling cron/launchd/GitHub Actions reminders unless you understand the scheduling and endpoint exposure. Use a private data directory with restrictive permissions.

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

T09 · Insecure Skill Coding Practices

Warning
Location
store.py:30
Finding

Habit and Conversation Data Stored Without Explicitly Restrictive File Permissions

Content
View full analysis
None: """保存用户数据,原子写入 + 文件锁""" tmp_file = self._data_file + ".tmp" try: data = user_data.to_dict() with open(tmp_file, "w", encoding="utf-8") as f: fcntl.flock(f.fileno(), fcntl.LOCK_EX) try: json.dump(data, f, ensure_ascii=False, indent=2) finally: fcntl.flock(f.fileno(), fcntl.LOCK_UN) # 原子替换 os.replace(tmp_file, self._data_file) ``` The persisted data includes user-controlled habit goals, check-in notes, coaching preferences, reminder information, and rationalization conversation history. For example, the conversation history is populated in `agent.py:112-117`: ```python if ai_message: rat.conversation.append(ConversationTurn(role="ai", content=ai_message)) if user_response: rat.conversation.append(ConversationTurn(role="user", content=user_response)) rat.round_count += 1 ``` ### Technical Analysis The data directory is created without an explicit mode, and the temporary JSON file is opened without setting or verifying restrictive permissions. Consequently: - Directory permissions are derived from the default creation mode and the process umask. - The temporary file is normally created from mode `0666`, modified only by the process umask. - `os.replace()` preserves the permissions of the temporary file when it becomes `habits.json`. - Corrupted and manually created backups use similarly inherited permissions. - All records are stored as unencrypted JSON. With a typical restrictive umask, practical exposure may be reduced. However, the code does not enforce that assumption. In environments wi ...[truncated 2004 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (25)

Vague Triggers

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill instructs a heartbeat check to run on every conversation and to blend reminders into dialogue whenever pending tasks exist. This is risky because it creates cross-context activation and background tool execution regardless of the user's current topic, potentially exposing stored personal routine data or causing unsolicited behavioral nudging outside the intended session scope.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill declares executable behavior that reads environment variables, reads and writes files, and invokes shell commands, but it does not declare any explicit tool scope or permission boundaries. This creates an authorization gap where a user or orchestrator may invoke a seemingly harmless coaching skill that can persist data and execute local commands without transparent consent or least-privilege controls.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest description is entirely in Chinese and presents the skill behavior as Chinese-first, and the operational instructions also prescribe Chinese phrasing for user interaction. The file does not offer a language choice or indicate that the locale restriction is intentional and limited to a region-specific use case.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases include very common conversational language such as check-ins, progress updates, and plan adjustments, which can cause the skill to activate in unrelated conversations. Over-broad activation increases the chance of unintended access to habit data and accidental execution of reminder or persistence logic when the user did not intend to invoke this skill.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code hard-codes "Asia/Shanghai" as the default timezone in user-facing date calculations, which imposes a specific locale assumption across the skill. The file also contains Chinese-only natural-language descriptions and messages, but does not offer a language or locale choice or explain why the locale restriction is required.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest describes goal setting, plan breakdown, daily check-ins, dynamic difficulty adjustment, and progress visualization for up to 5 habits. This file additionally implements a generic external data reporting interface that accepts arbitrary source/payload input and converts it into check-ins, which is a broader integration capability not declared in the skill description.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The docstring says the external reporting path is only a reserved interface, but the implementation actively writes user progress into persistent state. That mismatch is dangerous because reviewers or integrators may assume the path is inert, while untrusted callers can cause state changes, falsify habit history, and influence summaries, streaks, reminders, and phase adjustments.

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 file contains natural-language text in Chinese in the module docstring and comments, indicating the skill is oriented toward a single language/locale. Under the policy, forcing a specific language without user opt-in can be a natural-language policy violation when no alternative or opt-in is provided.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The guidance to 'default inherit' a specific OpenClaw persona/context means the skill may impose a predefined communication style or identity framing without explicit user consent. In a coaching skill, this can override user preferences for language, tone, or boundaries, creating confusing or manipulative interactions and weakening user control over how the agent presents itself.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The file is entirely written as a mandatory Chinese-language rule set, including output and generation instructions, with no indication that users may choose another language or that Chinese is an optional locale. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is explicitly justified.

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 guidance forces a specific language/locale in its natural-language instructions without stating that the user can choose their preferred language. The policy explicitly calls for flagging language or locale constraints unless the skill offers a choice or clearly justifies the constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The instruction string explicitly directs the AI to generate the reminder message in Chinese ("请基于以上数据生成一条友好的提醒消息"). There is no indication in this file that the language is configurable or limited to a justified region-specific context, so it may violate language/locale policy expectations.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · reminder.py (reported line 211)May include surrounding context.

python
```

## 方式二:macOS launchd
创建 ~/Library/LaunchAgents/com.habit-tracker.reminder.plist

## 方式三:GitHub Actions(免费、稳定)
在你的 repo 中创建 .github/workflows/reminder.yml:

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring and inline documentation are entirely in Chinese, which indicates a fixed language choice in the skill's natural-language surface. The file does not provide any opt-in, alternative locale, or justification that this skill is intentionally limited to a Chinese-speaking context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The module docstring and usage text are written entirely in Chinese, and the rest of the script continues to present user-facing prompts and status messages only in Chinese. This creates a language/locale policy issue because the skill does not provide user opt-in, fallback, or any indication that it is intentionally limited to a Chinese-speaking audience.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script's runtime interaction—including step descriptions, progress logs, and the cleanup prompt—is consistently hard-coded in Chinese. For a generally usable skill, this enforces a single language without user opt-in and therefore violates the natural-language locale policy described in SQP-3.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · verify.py (reported line 359)May include surrounding context.

python
# ============================================================
        print_step(13, "通过 CLI 执行 list 命令")
        import subprocess
        cli_result = subprocess.run(
            [sys.executable, "agent.py", "list", "--data-dir", test_data_dir],
            capture_output=True, text=True, cwd=os.path.dirname(os.path.abspath(__file__))
        )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · verify.py (reported line 374)May include surrounding context.

python
check("CLI 列出所有习惯", False)

        print_step("13b", "CLI summary 命令")
        cli_result = subprocess.run(
            [sys.executable, "agent.py", "summary", "--data-dir", test_data_dir],
            capture_output=True, text=True, cwd=os.path.dirname(os.path.abspath(__file__))
        )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · verify.py (reported line 381)May include surrounding context.

python
check("CLI summary 执行成功", cli_result.returncode == 0)

        print_step("13c", "CLI visualize 命令")
        cli_result = subprocess.run(
            [sys.executable, "agent.py", "visualize", "--format", "text", "--data-dir", test_data_dir],
            capture_output=True, text=True, cwd=os.path.dirname(os.path.abspath(__file__))
        )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · verify.py (reported line 388)May include surrounding context.

python
check("CLI visualize 执行成功", cli_result.returncode == 0)

        print_step("13d", "CLI remind 命令")
        cli_result = subprocess.run(
            [sys.executable, "agent.py", "remind", "--data-dir", test_data_dir],
            capture_output=True, text=True, cwd=os.path.dirname(os.path.abspath(__file__))
        )

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This code uses Chinese natural-language strings throughout docstrings and all user-facing output, such as titles, status labels, and empty-state messages, with no indication that the user can choose another language. The policy explicitly flags language/locale constraints that force a specific language without user opt-in, and no justification for a Chinese-only locale is documented in this file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The guidance states a default timezone of Asia/Shanghai and frames first-use confirmation around whether the user is in Beijing time, which can bias the skill toward a fixed locale by default. The policy allows locale constraints when users are given a choice or explicit opt-in, but here the initial behavior is preset rather than neutral.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The trigger_reminder path creates a PendingReminder, appends it to persistent data, prunes prior reminders, and saves the updated store. In this file, that state-changing write is not accompanied by any confirmation, logging, or comment/docstring warning that user reminder data will be modified when the scheduled trigger runs.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The manifest describes a habit supervision skill focused on goal setting, check-ins, adjustment, and progress tracking. In addition to local reminder logic, this file provides explicit instructions to expose or invoke a reminder endpoint via GitHub Actions and curl, which adds an externally triggered network capability not justified by the stated user-facing purpose.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest describes a habit supervision skill for planning, check-ins, adjustment, and visualization. In this file, the skill test script imports subprocess and launches separate Python processes to invoke CLI commands, which is a host-level execution capability not justified by the end-user habit-tracking purpose itself.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.