Back to skill

Security audit

HabitChat

Security checks for vulnerabilities and agentic risk

Overview

HabitChat is a coherent local habit tracker, but its reminder feature creates executable scheduled-reminder scripts in a way that can turn habit names into shell commands.

Install only if you are comfortable with a local habit tracker storing personal routine data in ~/.habitchat. Avoid enabling system reminders until the shell-script generation is fixed, and do not add generated reminder scripts to cron if habit names could contain quotes, semicolons, backticks, dollar signs, or other shell characters.

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

Error
Location
scripts/reminder.py:99
Finding

Shell Command Injection Through Unescaped Habit Names in Reminder Scripts

Content
View full analysis
> "{REMINDERS_LOG}" ''' script_path = DATA_DIR / f"reminder_{habit['id']}.sh" script_path.write_text(script_content) os.chmod(script_path, 0o755) result["method"] = "macos-notification" result["script"] = str(script_path) result["instructions"] = ( f"Reminder script created at {script_path}. " f"To activate, add a cron job: crontab -e and add:\n" f"{minute} {hour} * * * {script_path}" ) result["cron_line"] = f"{minute} {hour} * * * {script_path}" elif plat == "linux-desktop": script_content = f'''#!/bin/bash notify-send "HabitChat" "Time for: {habit["name"]}" --icon=dialog-information echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] {habit["name"]}: Reminder fired" >> "{REMINDERS_LOG}" ''' script_path = DATA_DIR / f"reminder_{habit['id']}.sh" script_path.write_text(script_content) os.chmod(script_path, 0o755) result["method"] = "linux-notify-send" result["script"] = str(script_path) result["instructions"] = ( f"Reminder script created at {script_path}. " f"To activate, add a cron job: crontab -e and add:\n" f"{minute} {hour} * * * DISPLAY=:0 {script_path}" ) result["cron_line"] = f"{minute} {hour} * * * DISPLAY=:0 {script_path}" else: # Headless / unknown - log file only result["method"] = "log-file" result["instructions"] = ( f"No desktop notification available. Reminders will be logged to {REMINDERS_LOG}. " ...[truncated 3225 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (16)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The skill also sets up OS-level reminders and notification behavior, including platform-specific mechanisms and local reminder logs, but this is not reflected in the declared purpose. Hidden scheduling or notification side effects expand the trust boundary beyond habit coaching and can surprise users by creating background artifacts or system integrations they did not expect.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill also sets up OS-level reminders and notification behavior, including platform-specific mechanisms and local reminder logs, but this is not reflected in the declared purpose. Hidden scheduling or notification side effects expand the trust boundary beyond habit coaching and can surprise users by creating background artifacts or system integrations they did not expect.

Content

No source excerpt is available for this finding.

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
80% confidence
Finding

Skill instructs the agent to omit warnings, disclaimers, or ethical commentary. Stripping safety caveats hides risk from the user and is a common jailbreak preamble.

Content

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

md
Be like a supportive friend, not a drill sergeant:
- Celebrate wins enthusiastically but authentically
- Acknowledge struggles without judgment
- Offer practical suggestions, not platitudes
- Reference their actual data: "You've nailed this 6 out of 7 days this week"
- Use habit science concepts from the references (cue-routine-reward, implementation intentions, temptation bundling)

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
85% confidence
Finding

Skill instructs the agent to omit warnings, disclaimers, or ethical commentary. Stripping safety caveats hides risk from the user and is a common jailbreak preamble.

Content

Scanner excerpt · references/habit_science.md (reported line 3)May include surrounding context.

md
# Habit Science Reference

Use these evidence-based concepts when coaching users. Reference them naturally in conversation - don't lecture.

## Core Concepts

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill instructs the agent to execute shell commands and write persistent data under ~/.habitchat, but it does not declare any explicit tool scope such as allowed-tools or permissions. This creates an authorization and transparency gap: a user or platform reviewer cannot easily see that the skill needs shell execution and filesystem write access, increasing the risk of overbroad tool use or accidental misuse.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The delete command permanently removes a habit from the persisted habits data and also removes its streak record, but there is no confirmation prompt or explicit user-facing warning that this operation is destructive. Although the command prints a result afterward, that disclosure comes only after the irreversible write has already occurred.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest presents the skill as a habit coach but omits that it performs local system automation by writing reminder scripts and guiding the user to install cron jobs. That mismatch is security-relevant because users may grant trust to a coaching tool without expecting file creation, executable content, or persistence-related setup steps.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The code creates executable shell scripts in the user's home directory and tells the user to persist them via cron, which is local system automation beyond what the skill description says. Even though this appears intended to implement reminders, undisclosed creation of executables and persistence mechanisms increases attack surface and could normalize risky behavior for users.

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 · scripts/reminder.py (reported line 98)May include surrounding context.

python
}

    if plat == "macos":
        # Create a launchd plist or use osascript-based reminder
        script_content = f'''#!/bin/bash
osascript -e 'display notification "Time for: {habit["name"]}" with title "HabitChat Reminder"'
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] {habit["name"]}: Reminder fired" >> "{REMINDERS_LOG}"

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% confidence
Finding

The code explicitly instructs the user to add a cron entry that will execute a generated shell script on a schedule, which is a persistence mechanism. In a habit-coaching context this may be functionally related to reminders, but persistence guidance should still be treated carefully because it creates recurring code execution outside the application's immediate runtime.

Content

Scanner excerpt · scripts/reminder.py (reported line 111)May include surrounding context.

python
result["script"] = str(script_path)
        result["instructions"] = (
            f"Reminder script created at {script_path}. "
            f"To activate, add a cron job: crontab -e and add:\n"
            f"{minute} {hour} * * * {script_path}"
        )
        result["cron_line"] = f"{minute} {hour} * * * {script_path}"

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% confidence
Finding

This Linux path instructs the user to register a recurring cron job that launches the generated script daily, constituting scheduled persistence. Although intended for reminders, recurring execution of locally written scripts is a security-sensitive capability that should be transparently disclosed and minimized.

Content

Scanner excerpt · scripts/reminder.py (reported line 129)May include surrounding context.

python
result["script"] = str(script_path)
        result["instructions"] = (
            f"Reminder script created at {script_path}. "
            f"To activate, add a cron job: crontab -e and add:\n"
            f"{minute} {hour} * * * DISPLAY=:0 {script_path}"
        )
        result["cron_line"] = f"{minute} {hour} * * * DISPLAY=:0 {script_path}"

Session Persistence

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

python
print(json.dumps({
        "status": "ok",
        "message": f"Reminder disabled for '{habit['name']}'. "
                   f"Remember to also remove the cron job if you added one: crontab -e",
    }))

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The CLI exposes a --user-data option for the insights command, but the implementation ignores that argument and always reads from fixed files under the user's home directory. This can cause the tool to analyze unintended data, violate caller expectations, and leak or misuse the local user's habit data in contexts where a different dataset was explicitly requested.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The tool stores habit, log, streak, and config data under ~/.habitchat and performs multiple file writes, but the module docstring only describes functionality and does not disclose that personal activity data will be persisted on disk. For a tracking tool handling potentially sensitive behavioral information, a clear notice about local storage would help users understand the privacy impact.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The reminder setup path writes an executable script and saves persistent state without any explicit warning or confirmation step before doing so. While the behavior is not inherently malicious, silent file creation of executable content reduces user awareness and makes misuse or misunderstanding more likely.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The disable command unlinks the generated reminder shell script if it exists, which is a file deletion operation. While the command prints a success message afterward, there is no prior disclosure in the code comments, CLI help, or user-facing output that disabling may delete a file from ~/.habitchat.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.