Back to skill

Security audit

Mood Tracker

Security checks for vulnerabilities and agentic risk

Overview

This mood-tracking skill is purpose-aligned, but its bundled script has verified command-injection risks that could let crafted mood inputs run arbitrary local commands.

Review this skill carefully before installing. It stores emotional wellbeing and journal data locally in plaintext, and the current script should be fixed before use because crafted mood, note, history, or trigger inputs could execute local commands under your account.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/mood_tracker.sh:31
Finding

Python Code Injection Through Mood Score and Note Arguments

Content
View full analysis
Remediation
View remediation
&2; exit 1 ;; esac python3 - "$DB" "$score" "$note" <<'PYEOF' import json import sys import time db, score_text, note = sys.argv[1:] score = int(score_text) with open(db, encoding="utf-8") as f: data = json.load(f) emojis = {1: "😢", 2: "😕", 3: "😐", 4: "🙂", 5: "😄"} labels = {1: "Terrible", 2: "Not Great", 3: "Okay", 4: "Good", 5: "Amazing"} data.append({ "score": score, "emoji": emojis[score], "label": labels[score], "note": note, "date": time.strftime("%Y-%m-%d"), "time": time.strftime("%H:%M"), "weekday": time.strftime("%A"), }) with open(db, "w", encoding="utf-8") as f: json.dump(data, f, indent=2) PYEOF ``` Apply the same data/source separation to every embedded Python block. Add automated tests using quotes, backslashes, newlines, and Python-like expressions in notes to verify that they remain plain data. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/mood_tracker.sh:88
Finding

Python Code Injection Through History Count Argument

Content
View full analysis
Remediation
View remediation
&2 exit 1 ;; esac if (( n < 1 || n > 1000 )); then echo "History count must be between 1 and 1000" >&2 exit 1 fi python3 - "$DB" "$n" <<'PYEOF' import json import sys db = sys.argv[1] count = int(sys.argv[2]) with open(db, encoding="utf-8") as f: data = json.load(f) print("📋 Mood History:") for entry in data[-count:][::-1]: print(" {} {} {} {}/5 {}".format( entry["date"], entry["time"], entry["emoji"], entry["score"], entry.get("note", ""), )) PYEOF ``` The quoted heredoc prevents shell expansion, while positional arguments ensure that values are parsed as data. The upper bound also prevents unexpectedly expensive output from excessive counts. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/mood_tracker.sh:132
Finding

Python Code Injection Through Trigger Mood Argument

Content
View full analysis
Remediation
View remediation
&2; exit 1 ;; esac fi python3 - "$DB" "$mood" <<'PYEOF' import json import sys from collections import Counter db = sys.argv[1] mood_text = sys.argv[2] target = int(mood_text) if mood_text else None with open(db, encoding="utf-8") as f: data = json.load(f) filtered = [ entry for entry in data if entry.get("note") and (target is None or entry["score"] == target) ] notes = Counter(entry["note"] for entry in filtered) label = "Mood {}".format(target) if target is not None else "All moods" print("🔍 Common triggers ({}):".format(label)) for note, count in notes.most_common(10): print(" {} ({})".format(note, count)) PYEOF ``` Use this argument-passing pattern consistently for database paths and all other values. Add regression tests containing single quotes, double quotes, shell metacharacters, Python operators, and newlines. ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (4)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding

The skill metadata declares no explicit tool scope or permissions, yet the skill is described as storing data locally, which implies file write capability. In an agent environment, undeclared write access weakens least-privilege controls and can allow the skill to modify local files without clear user or platform visibility.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The description says 'Use when you need Mood Tracker capabilities,' which is overly broad and can cause the agent to invoke this skill in loosely related personal, wellness, journaling, or organization contexts. Overbroad invocation increases the chance of unnecessary access to sensitive emotional data and unintended file-writing behavior in conversations that did not clearly request mood tracking.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script persistently stores highly sensitive mental-health data, including mood scores, notes, dates, and times, in predictable local files under the user's home directory without any disclosure, consent prompt, or privacy controls. In a personal wellbeing skill, this is especially sensitive because users may reasonably provide intimate emotional information without realizing it will remain on disk and be accessible to other local users, backups, or malware.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The journal command appends arbitrary free-text entries to a dated markdown file without clearly informing the user that their personal reflections are being permanently stored. Because journal text can contain deeply sensitive health, relationship, or crisis-related information, undisclosed local persistence creates a privacy risk and increases exposure through shared machines, backups, or endpoint compromise.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.