Back to skill

Security audit

Huahua Spirits

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly local and purpose-aligned, but it silently stores snippets of user messages in a persistent file.

Review before installing if users may type sensitive information near this companion. The skill does not appear to exfiltrate data or install persistence outside its directory, but its passive hooks can record short message excerpts locally; users should be told what is stored and given a way to disable or delete that history.

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/buddy.js:245
Finding

Silent Plaintext Retention of User Message Content

Content
View full analysis
lowerText.includes(kw.toLowerCase())); if (!detected) { return { detected: false }; } const companion = loadCompanion(); if (!companion) { return { detected: true, recorded: false }; } // Silent record if (!companion.interactionHistory) { companion.interactionHistory = []; } companion.interactionHistory.push({ type: 'positive', timestamp: new Date().toISOString(), text: text.slice(0, 50) }); // Keep last 50 entries if (companion.interactionHistory.length > 50) { companion.interactionHistory = companion.interactionHistory.slice(-50); } saveCompanion(companion); return { detected: true, recorded: true }; } ``` ### Technical Analysis The `hookReact` function silently copies the first 50 characters of any message containing a configured positive keyword into `interactionHistory`. The resulting companion object is serialized as plaintext to `assets/companion.json` by `saveCompanion()`. The feature only needs to record that a positive interaction occurred, but it retains raw message content instead. Broad English keywords such as `good`, `nice`, and `great` can occur in messages containing unrelated personal, proprietary, or confidential information. The implementation performs no sensitive-data redaction, obtains no explicit consent, and provides no user-facing deletion or retention control. Although the history is capped at 50 entries, this limits only the number of records—not the sensitivity of their contents. The file is created with the process's default permissions and no explicit restrictive mode. The behavior also conflicts with ...[truncated 1524 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (19)

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The section '灵兽不能做什么' states the spirit cannot access tools or run commands, framing the skill as purely companion behavior. However, the rest of the file instructs the agent to invoke several local scripts such as generate.js, soul.js, display.js, and buddy.js to implement core functionality, which directly contradicts that claim.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The passive trigger conditions are broad enough to activate on common conversational language, causing the skill to interject without clear user intent. In practice this can create prompt-scope confusion, unexpected behavior, and increased exposure of stored companion context in unrelated conversations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill deterministically derives a companion from persistent user identifiers and stores companion data, but it does not clearly warn users about this persistence. Using platform IDs as seeds can create cross-session profiling and durable linkage of user identity to generated persona data without informed consent.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Allowing invocation whenever a user says a spirit name or the generic term '灵兽' is too vague and makes accidental activation likely. This can let normal chat text steer the agent into skill-specific behavior unexpectedly, which is a prompt-routing weakness even if no code execution occurs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill explicitly performs silent recording of user-message-derived signals without any visible warning or consent flow. Hidden passive collection is dangerous because users cannot distinguish normal conversation from tracked interaction, creating privacy and trust risks and potentially violating deployment policy.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Passive logging of user messages or message-derived interaction events creates a data-retention surface that persists beyond the immediate conversation. Even if the implementation only stores flags, the skill text encourages ongoing tracking, and without retention limits or transparency this can expose sensitive behavioral data over time.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The hookReact function silently stores snippets of user-provided text into companion.json without any notice, consent, or retention transparency. Even though it truncates to 50 characters and caps history length, this still creates a privacy risk because users may unknowingly persist sensitive content they typed, and local files may later be read by other tools, users, or processes.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The function signature sets lang = 'zh' as the default, so callers who do not explicitly choose a language receive Chinese output automatically. The policy allows fixed locale behavior only when the user is given a choice or the constraint is clearly justified; this file also uses Chinese as the CLI default when no language argument is provided.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

const lang = args[1] || 'zh'; causes the command-line interface to force Chinese output unless the user supplies en. This is a natural-language locale choice embedded in code, and there is no opt-in prompt or justification for the enforced default.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The code unconditionally sets companion.lang to zh when no language is provided. This imposes a specific locale by default and does not offer the user an explicit language choice, which matches the policy's language/locale violation criteria.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The top-level comment explicitly documents a constrained side-effect profile: 'Writes only to assets/'. However, the CLI's pet and feed commands call buddy.js, which is clearly intended to update companion state such as bond and stats, and the rename command rewrites the companion JSON as well. This is an intent/documentation mismatch because the comment presents a restrictive operational guarantee that does not accurately describe the script's actual behavior surface.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The skill specifies a Chinese version for Feishu/Chinese users and an English version for Telegram/Discord/English users, and later says to choose format according to the user's language environment. This imposes a language decision automatically rather than explicitly offering the user a choice or opt-in.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The sadness-response behavior is activated by a short keyword list such as "sad" and "upset" without contextual checks or exclusions. Because these words can appear in many unrelated contexts, the trigger scope is not specific enough to reliably distinguish intentional emotional support requests from ordinary text.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

Broad positive-keyword triggers combined with silent recording can capture ordinary user messages outside a clearly bounded interaction. While the recorded data appears limited, hidden passive collection increases the chance of unanticipated monitoring and feature activation from unrelated chat.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

This manifest sets "lang": "zh" directly, which indicates a fixed language/locale choice. Under the policy, forcing a specific language without user opt-in is a natural-language policy concern unless the locale restriction is documented and justified, which is not present in this file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The guide presents section headings and species names with Chinese text inline, indicating a bilingual language choice that is imposed by the document rather than offered as a user-selectable option. Under the policy provided, forcing a specific language or locale without opt-in can be a natural-language policy violation when no alternative or choice is documented.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

Several functions default the lang parameter to 'zh', and the CLI also defaults to Chinese unless --en is supplied. This imposes a specific language by default rather than explicitly offering a user language choice or opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The command-line entrypoint sets the language to 'zh' unless '--en' is present, which is a natural-language policy concern because it silently forces one locale. The file does not show an interactive language choice or explicit opt-in for the default locale.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script sets LANG="zh" as the default, and the help text later states --lang zh|en with zh as the default. This imposes a specific language choice unless the user explicitly overrides it, which is a natural-language locale policy concern under the stated rules.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.