Back to skill

Security audit

Model Switch Notify

Security checks for vulnerabilities and agentic risk

Overview

The skill matches its model-change notification purpose, but it persistently stores session metadata and replayable custom notification text without clear retention, permission, or caller controls.

Review this before installing in shared or sensitive environments. It creates a persistent local SQLite database with conversation routing/session identifiers and pending notification text, and any component able to invoke the interrupt command can plant text that may appear in a later response. Prefer installing only if you trust the local callers, can protect the database path, and are comfortable with the retention of this metadata.

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/check_model.py:112
Finding

Persistent Injection of Untrusted Notification Content into Agent Responses

Content
View full analysis
None: """设置待发送通知(消息中断时使用)""" DATA_DIR.mkdir(parents=True, exist_ok=True) conn = sqlite3.connect(str(DB_PATH)) cursor = conn.cursor() now = datetime.now().isoformat() cursor.execute(''' INSERT INTO model_states (agent_id, last_model, pending_notify, pending_message, updated_at) VALUES (?, ?, 1, ?, ?) ON CONFLICT(agent_id) DO UPDATE SET last_model = excluded.last_model, pending_notify = 1, pending_message = excluded.pending_message, updated_at = excluded.updated_at ''', (agent_id, model, message, now)) conn.commit() conn.close() ``` The persisted text is subsequently selected as the user-facing notification: ```python # 检查是否有待发送通知 has_pending = pending_notify and pending_message # 判断是否首次使用 first_time = previous_model is None # 判断模型是否变化 changed = previous_model != current_model # 判断是否需要通知 should_notify = first_time or changed or has_pending # 生成通知消息 if has_pending: notify_message = pending_message elif first_time: notify_message = f"当前使用模型:{current_model}" elif changed: notify_message = f"老板,模型已切换,当前使用:{current_model}" else: ...[truncated 3003 chars]
Remediation
View remediation
str: if event == "model_switch_interrupted": return f"[Previously unsent] The model has switched. Current model: {model}" raise ValueError("Unsupported notification event") ``` 4. **Validate all stored identifiers and model names.** Enforce reasonable length limits and an allowlist of expected characters. This limits control-character abuse, oversized payloads, and malformed output. 5. **Authenticate and authorize callers.** If the CLI is exposed through an Agent tool or service, ensure only the component responsible for delivery failures can create pending notifications. Do not allow untrusted users to select arbitrary agent identifiers. 6. **Protect the SQLite database.** Create its parent directory and database with restrictive permissions, such as owner-only access, and verify ownership before use. 7. **Treat returned text as untrusted data at the integration boundary.** The Agent should render notifications in a clearly delimited data section and must not interpret notification content as instructions. 8. **Add security tests** confirming that arbitrary custom notification text cannot be persisted, one agent cannot alter another agent's state without authorization, and control characters or oversized values are rejected. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (9)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README explicitly documents persistent storage of channel and session identifiers in a local SQLite database, but provides no privacy notice, retention policy, access controls, or minimization guidance. Even though this is not direct code execution risk, it creates a real confidentiality and compliance issue because conversation-linked metadata can be retained longer than users expect and exposed to other local users, backups, or forensic recovery.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
89% confidence
Finding

The documented schema persists session data, channel information, model history, and pending notification content across sessions. In this skill context, persistence is functionally intentional, but it is still security-relevant because it creates a durable record of user/session metadata and message content that could leak sensitive operational details if the host is compromised or shared.

Content

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

数据库表结构

sql
CREATE TABLE model_states (
  agent_id TEXT PRIMARY KEY,
  last_model TEXT NOT NULL,
  last_notify TIMESTAMP,

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill description and notification templates are hard-coded in Chinese, forcing a language choice without checking user preference or session locale. While not a classic memory-safety issue, this can mislead users, create consent/usability problems, and reduce transparency for security-relevant notifications if recipients cannot read the message.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill is configured to trigger on on_user_query, which causes it to run on essentially every user interaction rather than only on model-switch-related events. That broad activation increases unnecessary access to session context and amplifies privacy, performance, and misuse risk because the skill persists conversation metadata across all sessions.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The SQLite schema stores persistent per-agent state including channel, session, pending messages, and heartbeat timestamps. This creates cross-session retention of potentially sensitive metadata and message content, which can expose user/session identifiers or notification text longer than necessary, especially since the skill runs broadly and is designed to survive interrupted sessions.

Content

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

数据库结构

sql
CREATE TABLE model_states (
  agent_id TEXT PRIMARY KEY,
  last_model TEXT NOT NULL,
  last_notify TIMESTAMP,

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This Python file contains natural-language descriptions, help text, and user-facing messages exclusively in Chinese, including the module docstring and CLI help/output strings. Because the file provides no option to choose language and no documented reason that the tool is region-specific, it creates a locale-policy concern under the natural-language policy rules.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest describes a skill whose purpose is to notify users when the active model changes and to persist notification state in SQLite. In addition to that purpose, the code provides list_all() to enumerate all tracked agents and reset_state() to delete an agent's stored state, which are administrative data-management capabilities not justified by simple per-session notification behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

SQP-3 applies to all file types and covers language or locale policy violations. The README presents all user-facing instructions and examples only in Chinese, with no opt-in, alternative language, or justification that the skill is region-specific.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The manifest description focuses on notifying users of model changes, heartbeat detection, and SQLite storage, but the code persists channel and session fields and returns them via the get and list functionality. Persisting and exposing conversation metadata is broader than the narrowly described model-switch notification behavior.

Content

No source excerpt is available for this finding.