Back to skill

Security audit

Driftling Buddy

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a local companion skill, but it automatically builds persistent diary-like records from user behavior and has unsafe state/terminal handling that users should review before installing.

Review this before installing if you do not want a skill to keep a local, behavior-derived companion history. Use explicit slash commands, avoid storing sensitive task details in buddy names/context/profile fields, consider setting BUDDY_STATE_FILE to an isolated path, and inspect or remove ~/.buddy_mode_state.json if you want to clear its saved data.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/buddy.py:886
Finding

Unsanitized User-Controlled Content Can Inject Terminal Escape Sequences

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/check.sh:35
Finding

Validation Script Modifies the User’s Production State File

Content
View full analysis
/dev/null "$PYTHON_BIN" scripts/buddy.py /summon --theme coffee --lang zh --name Mori --main >/dev/null "$PYTHON_BIN" scripts/buddy.py /unlock --theme tea --lang zh --name Nilo --reason "你刚设置了一个茶歇提醒" >/dev/null "$PYTHON_BIN" scripts/buddy.py /collection --lang zh >/dev/null "$PYTHON_BIN" scripts/buddy.py /buddy-help --lang zh >/dev/null ``` The default state path points to the invoking user's home directory: ```python STATE_FILE = Path(os.environ.get("BUDDY_STATE_FILE", Path.home() / ".buddy_mode_state.json")) ``` State is loaded from and saved directly to that path: ```python def load_state() -> dict: default = {"unlocked": [], "main": None, "custom_pools": {}} if not STATE_FILE.exists(): return default try: state = json.loads(STATE_FILE.read_text(encoding="utf-8")) state.setdefault("custom_pools", {}) return state except (json.JSONDecodeError, OSError): return default def save_state(state: dict) -> None: STATE_FILE.write_text(json.dumps(state, ensure_ascii=False, indent=2), encoding="utf-8") ``` ### Technical Analysis The documented `./scripts/check.sh` command appears to be a local smoke test, but it does not configure an isolated `BUDDY_STATE_FILE`. As a result, its calls to `/buddy`, `/summon --main`, and `/unlock` use the default state file at `~/.buddy_mode_state.json`. Those commands are not read-only. They add demo buddies and modify the active main buddy. Redirecting standard output to `/dev/null` suppresses output only; it does not prevent file writes. Validation scripts ...[truncated 1072 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (15)

Memory Manipulation

High
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Content

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

md
- Multiple unlocks in a single session. One unlock per session is a special event. Two is the absolute maximum for an unusually varied session. Three or more means the threshold is too low.
- When the user just started. The first buddy is free; the second should take at least a few real interactions to arrive.

The ideal pacing: a regular user gets a new buddy every **3-5 sessions**. After a month, they have 8-15 buddies, each with a clear memory of when and why it appeared. This feels like a growing collection, not a firehose.

## Personality constraints

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README advertises that buddies remember shared experiences, grow from user habits, and persist memory, but it does not clearly disclose what data is retained, for how long, or how users can inspect and delete it. Because the feature is explicitly based on behavioral history, missing privacy notice and controls can lead to silent collection or retention of sensitive workflow patterns.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger list includes broad natural-language phrases like "enable buddy mode" and "be my coding buddy" that can plausibly occur in ordinary conversation, increasing the chance of unintended activation. In a skill that adds persistent memory and behavior changes, accidental invocation can expose user context to the skill or cause state changes without clear user intent.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill instructs the agent to invoke local scripts and maintain state, but the manifest does not declare any explicit tool scope or permissions. That mismatch can cause the runtime to grant broader-than-necessary capabilities by default or make the skill's file, environment, and persistence behavior insufficiently reviewable.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The direct activation section includes loose natural-language triggers such as asking for a mascot, companion, collectible, or more lively session, which are ambiguous and easy to match unintentionally. In context, accidental activation matters because the skill then begins tracking habits, generating persistent state, and modifying output style across the session.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The ambient activation rules are extremely broad and allow the buddy behavior to trigger from ordinary activities like reminders, research, debugging, travel, shopping, or casual check-ins. That creates a high risk of unexpected activation and silent collection of behavioral context outside clear user consent, especially because the skill is designed to persist observations over time.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill tells the system to notice repeated user actions within a session and comment on patterns in their behavior. While less severe than cross-session storage, this still encourages behavioral profiling and can surface sensitive work habits or activity patterns the user did not expect to be tracked or reflected back.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This section explicitly directs the system to store detailed cross-session records including obtained context, memorable moments, times shown, and diary-like notes tied to the user's habits and actions. Even if framed as a game mechanic, this creates a persistent behavioral profile that can reveal routines, interests, work patterns, and potentially sensitive personal details over time.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill explicitly states that the collection should function as a personal diary built from the user's story, habits, and memorable events. That purpose materially increases privacy risk because it incentivizes long-lived storage of personalized, behavior-derived notes rather than transient UX state.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill persists companion state and user-derived context to a local file even though the described functionality centers on interactive generation/display. This creates an undisclosed data retention surface that can store behavioral or contextual user information on disk, increasing privacy risk and exposure if the host is shared or compromised.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The language-selection logic maps the user-visible 'mixed' option directly to 'zh', causing the skill to force Chinese output rather than honoring an actual mixed or user-chosen locale. This is a natural-language policy issue because it imposes a specific language without clear opt-in to that exact behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

State is auto-saved to disk during normal operations without clear warning or consent, despite including fields like obtained_context, memorable notes, and unlocked history. This is a privacy and transparency issue rather than a memory-safety bug, but in a companion skill the mismatch between expected ephemeral interaction and silent persistence makes it materially risky.

Content

No source excerpt is available for this finding.

Tainted flow: 'STATE_FILE' from os.environ.get (line 78, credential/environment) → pathlib.Path.write_text (file write)

Medium
Category
Data Flow
Confidence
93% confidence
Finding

The state file path is derived from the BUDDY_STATE_FILE environment variable and then written to without validation. If an attacker can influence the execution environment, they can redirect writes to arbitrary filesystem locations writable by the process, causing unauthorized file overwrite or corruption; the skill context makes this more concerning because the file is written automatically during normal buddy interactions.

Content

Scanner excerpt · scripts/buddy.py (reported line 341)May include surrounding context.

python
def save_state(state: dict) -> None:
    STATE_FILE.write_text(json.dumps(state, ensure_ascii=False, indent=2), encoding="utf-8")


def add_to_collection(theme: str, name: str, custom_profile=None, context: str = "") -> dict:

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The register command accepts an arbitrary JSON profile and stores it as a custom pool, extending the skill beyond simple display into persistent, user-controlled content registration. In this context it is not direct code execution, but it broadens attack surface for data abuse, oversized input, malformed state, and persistence of deceptive or harmful content in a skill that users would expect to be a lightweight companion feature.

Content

No source excerpt is available for this finding.

Scope Creep

Low
Category
Excessive Agency
Confidence
70% confidence
Finding

Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Content

Scanner excerpt · README.md (reported line 8)May include surrounding context.

md
- Buddies react to what you are actually doing, not random flavor text.
- Stats grow over time based on shared experiences (+Focus from debugging, +Warmth from check-ins).
- Each buddy remembers when and why it appeared, building a personal history.
- New species and pools are generated dynamically from user behavior — not limited to a fixed catalog.
- Rarity has luck rolls: the same species can drop at different tiers.
- Cards are narrow and sidebar-friendly with rarity-styled frames.
- Supports Chinese, English, or mixed flavor text.