Back to skill

Security audit

companion-checkin

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent local wellness check-in logger, but users should understand it keeps private check-in history in a local plaintext file.

Install only if you are comfortable with mood, sleep, meals, stress, and freeform notes being saved locally in data/checkins.jsonl. Treat that file as private, avoid using it on shared machines unless permissions are tightened, and delete or protect the log if you no longer want that history retained.

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
scripts/checkin_tracker.py:208
Finding

Private wellness data is stored without enforced access controls

Content
View full analysis
dict[str, Any]: ensure_data_dir() entry = { "timestamp": now_local().isoformat(), "moment": moment, "answers": answers, } with LOG_PATH.open("a", encoding="utf-8") as f: f.write(json.dumps(entry, ensure_ascii=False) + "\n") return entry ``` The associated directory creation also does not enforce a restrictive mode: ```python def ensure_data_dir() -> None: DATA_DIR.mkdir(parents=True, exist_ok=True) ``` ### Technical Analysis The check-in log contains private wellness information, including mood, sleep, meals, stressors, focus, and free-form personal notes. The implementation writes this information as plaintext JSON to `data/checkins.jsonl`. Neither the directory nor the file is created with explicitly restrictive permissions. `Path.mkdir()` and `Path.open()` therefore rely on the process umask and existing filesystem permissions. On a shared system with a permissive umask or an already accessible data directory, other local accounts may be able to read the log. This conflicts with the documented requirement in `SKILL.md` to treat the log as private personal data. The issue does not independently grant elevated privileges and is conditional on the host's filesystem configuration, but it may expose sensitive information in multi-user environments. ### Attack Path 1. A user invokes the `log` command and supplies mood, sleep, stress, or other personal answers. 2. `ensure_data_dir()` creates the data directory using permissions derived from the current process umask. 3. `log_ch ...[truncated 1025 chars]
Remediation
View remediation
None: DATA_DIR.mkdir(parents=True, exist_ok=True, mode=0o700) os.chmod(DATA_DIR, 0o700) ``` 2. Create or open the log with an explicit owner-only mode. Using `os.open()` ensures that a newly created file receives mode `0600` independently of a permissive umask: ```python def log_checkin(moment: str, answers: dict[str, Any]) -> dict[str, Any]: ensure_data_dir() entry = { "timestamp": now_local().isoformat(), "moment": moment, "answers": answers, } flags = os.O_WRONLY | os.O_APPEND | os.O_CREAT fd = os.open(LOG_PATH, flags, 0o600) try: with os.fdopen(fd, "a", encoding="utf-8") as file: file.write(json.dumps(entry, ensure_ascii=False) + "\n") except Exception: os.close(fd) raise return entry ``` 3. Validate and repair permissions on an existing log before reading or appending: ```python if LOG_PATH.exists(): os.chmod(LOG_PATH, 0o600) ``` 4. Consider encrypting records at rest when the threat model includes administrators, backups, device theft, or other actors that can bypass ordinary file permissions. 5. Document the retention policy and provide a safe command for deleting or exporting personal records. 6. Add automated tests that verify the data directory is mode `0700` and the log file is mode `0600` on supported POSIX platforms. ]]>
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 (5)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill instructs the agent to read and write local files via scripts and to store data in data/checkins.jsonl, but it does not declare any explicit tool scope or permission boundaries. This creates an authorization gap where a broadly activated skill handling sensitive personal data may perform file operations without clear user-visible limits or least-privilege controls.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The activation language is broad enough to match many ordinary wellness, habit, reminder, or recap requests, increasing the chance the skill runs in contexts where the user did not specifically intend persistent logging. Because this skill stores private check-in data, overbroad triggering materially raises privacy risk and the likelihood of unintended collection.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill explicitly stores sensitive mood, sleep, meals, stress, and daily progress data in a local JSONL file but does not instruct the agent to warn the user beforehand about persistence, retention, or privacy implications. This is dangerous because users may disclose health-adjacent or intimate personal information without informed consent, leaving a durable local record that could be exposed to other tools, users, or system operators.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The file fixes its timezone to Jakarta and all user-facing prompts and summaries are written in Indonesian, indicating a forced locale/language experience. There is no mechanism for user selection or documented justification that this skill is intentionally region-specific.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script stores highly personal wellness data such as mood, sleep, meals, stressors, and support needs in a plaintext JSONL file under a predictable local path without any consent flow, disclosure, retention control, or access protection. In the context of a companion check-in skill, this is genuinely sensitive behavioral and mental-health-adjacent data, so local compromise, shared-machine access, backups, or accidental inclusion in source control could expose private user information.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.