Back to skill

Security audit

version-master

Security checks for vulnerabilities and agentic risk

Overview

This skill does useful file versioning, but its shared snapshot storage can expose or alter histories across workspaces.

Review this carefully before installing. It stores complete file snapshots under your home directory and may let one workspace see, restore, or delete snapshots from another workspace with the same relative filename. Avoid using it for secrets or private project files unless the storage isolation and key-collision issues are fixed.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/version_tool.py:148
Finding
Cross-Workspace Snapshot Disclosure, Restoration, and Deletion## Vulnerability Details **File Location**: `scripts/version_tool.py:23-27, 148-162, 393, 467, 547, 652`; documented in `SKILL.md:144` **Vulnerability Type**: Missing workspace authorization and isolation **Risk Level**: High ### Vulnerable Code ```python def __init__(self, workspace_path: Optional[str] = None): self.workspace_path = Path(workspace_path or os.getcwd()).resolve() self.storage_path = Path.home() / ".workbuddy" / "versions" / "version-master" self.storage_path.mkdir(parents=True, exist_ok=True) # Global index file self.index_file = self.storage_path / "index.json" self._load_index() ``` ```python def _find_file_key_by_rel_path(self, rel_path: str) -> Optional[str]: """Find file_key by rel_path, including cross-workspace matching.""" current_key = self._file_key(rel_path) if current_key in self.index.get("files", {}): return current_key # Search every workspace by relative path normalized = rel_path.replace("\\", "/") for key, data in self.index.get("files", {}).items(): if data.get("rel_path", "").replace("\\", "/") == normalized: return key return None ``` The unsafe lookup is used by security-sensitive operations: ```python # Listing file_key = self._find_file_key_by_rel_path(rel_path) # Restoration file_key = self._find_file_key_by_rel_path(file_path) # Diffing file_key = self._find_file_key_by_rel_path(file_path) # Deletion file_key = self._find_file_key_by_rel_path(file_path) ``` The behavior is also explicitly documented in `SKILL.md`: ```markdown - All workspaces share the same storage directory, version snapshots are accessible across workspaces ``` ### Technical Analysis Every workspace uses the same storage directory and global index. When the current workspace has no exact key for a requested relative path, `_find_file_key_by_rel_path()` searches all indexed wo ...[truncated 2149 chars]
Remediation
## Remediation Suggestions 1. Remove implicit cross-workspace fallback from `_find_file_key_by_rel_path()`. Only return a key that belongs to the active workspace. 2. Partition storage and indexes by a stable workspace identifier rather than maintaining one unrestricted global namespace. 3. Store a canonical workspace identifier in every index entry and snapshot file. Verify it before listing, loading, restoring, diffing, or deleting a snapshot. 4. If cross-workspace sharing is required, implement an explicit import/export or sharing mechanism with clear authorization and user confirmation. Do not infer authorization from a matching relative path. 5. During restoration, validate both the destination workspace path and source snapshot ownership. 6. During cleanup, reject records whose workspace identifier does not exactly match the active workspace. 7. Add regression tests covering identical relative paths in separate workspaces and verify that all read and destructive operations remain isolated.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/version_tool.py:137
Finding
Lossy Storage-Key Generation Causes Cross-File and Cross-Workspace Collisions## Vulnerability Details **File Location**: `scripts/version_tool.py:137-146, 283-316, 320-350` **Vulnerability Type**: Non-unique resource identifier generation **Risk Level**: High ### Vulnerable Code ```python def _file_key(self, rel_path: str) -> str: """Convert a relative path to a storage key with a workspace prefix.""" normalized = rel_path.replace("\\", "/") # Use only the workspace directory name as the workspace identifier workspace_id = self.workspace_path.name # Replace separators and dots file_key = normalized.replace("/", "_").replace(".", "-") return f"{workspace_id}_{file_key}" ``` The generated key directly selects the shared index entry and storage directory: ```python file_key = self._file_key(rel_path) if file_key not in self.index["files"]: existing_key = self._find_file_key_by_rel_path(rel_path) if existing_key and existing_key != file_key: existing_data = self.index["files"][existing_key] self.index["files"][file_key] = { "rel_path": rel_path, "versions": existing_data["versions"], "next_version": existing_data["next_version"] } else: self.index["files"][file_key] = { "rel_path": rel_path, "versions": [], "next_version": 1 } file_index = self.index["files"][file_key] ``` Snapshot files are then written under the colliding key: ```python version_num = file_index["next_version"] file_index["next_version"] += 1 version_dir = self._get_file_versions_path(file_key) version_file = version_dir / f"v{version_num}.json" with open(version_file, 'w', encoding='utf-8') as f: json.dump(version_data, f, indent=2, ensure_ascii=False) ``` ### Technical Analysis The key-generation function is not injective: distinct inputs can produce the same storage key. The workspace component uses only `self.work ...[truncated 2205 chars]
Remediation
## Remediation Suggestions 1. Replace the workspace basename with a stable unique identifier, such as a generated workspace UUID or a SHA-256 digest of the canonical workspace path. 2. Replace lossy character substitution with a collision-resistant representation. Suitable approaches include: - hashing the exact normalized relative path; - URL-safe Base64 encoding of the path bytes; or - using a structured directory layout with validated path components. 3. Store the canonical workspace identifier and normalized relative path inside every index record and snapshot. 4. Before reading, appending, restoring, or deleting a snapshot, verify that both stored identifiers exactly match the active workspace and requested path. 5. Use atomic, exclusive file creation or transactional index updates to prevent silent overwrites of existing version files. 6. Detect existing key collisions and return a hard error rather than merging histories. 7. Provide a migration routine that assigns collision-resistant keys to existing snapshots without losing ownership metadata. 8. Add tests for known collision pairs, including `a/b.txt` versus `a_b.txt`, `a.b` versus `a-b`, and separate canonical workspaces with the same basename.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (15)

Self-Modification

High
Category
Rogue Agent
Content
The following operations require explicit user confirmation:

1. **Version restore** / 版本恢复 - Will overwrite current file content
2. **Version delete** / 版本删除 - Permanently deletes snapshot data

Before calling these operations, the AI must:
Confidence
90% confidence
Finding
The restore feature intentionally overwrites current file content, which is a real destructive capability even though the documentation requires confirmation. If confirmation handling is weak, spoofed, or bypassed, the skill can modify or destroy user work.

Credential Access

High
Category
Privilege Escalation
Content
3. Set `confirm=True` parameter / 设置 `confirm=True` 参数

**Path Security / 路径安全:**
All `file_path` parameters are validated server-side to stay within the workspace boundary. Paths containing `../` or absolute paths outside the workspace are rejected with an error. The AI must **never** pass system-level paths (e.g., `../../etc/passwd`, `C:\Windows\...`) as `file_path`.

## Technical Implementation
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding
The skill exposes file read/write capabilities through its documented use of `scripts/version_tool.py`, but it declares no explicit tool scope or permissions boundary. That omission increases the chance the agent can invoke file-modifying behavior without clear platform-level restrictions or reviewer visibility.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The activation guidance is broad enough to trigger on generic version-control or recovery requests, even though the skill only supports single-file snapshots. Over-activation can cause the agent to apply file-history behavior in contexts where users intended repository-level operations, increasing the chance of unintended reads, writes, or restores.

Ssd 3

Medium
Confidence
95% confidence
Finding
Auto-generating summaries and messages from file contents can copy sensitive data into metadata, indexes, logs, and UI responses. Because these derived fields may be more widely surfaced than the original file, they create an additional leakage channel for secrets or personal information.

Ssd 3

Medium
Confidence
91% confidence
Finding
The skill instructs the AI to infer the target file from previously edited or generated content in conversation context. That can cause the agent to operate on the wrong file or disclose information about prior user content without a fresh, explicit reference.

Session Persistence

Medium
Category
Rogue Agent
Content
The following operations require explicit user confirmation:

1. **Version restore** / 版本恢复 - Will overwrite current file content
2. **Version delete** / 版本删除 - Permanently deletes snapshot data

Before calling these operations, the AI must:
Confidence
87% confidence
Finding
The skill persists versioned copies of file contents and can rewrite files from stored snapshots, creating durable state across sessions. That persistence increases exposure if sensitive content is retained longer than expected or becomes reachable from other contexts, especially given the shared-storage design.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The documentation says `file_path` is validated to remain within the workspace, but the storage model undermines that guarantee by making snapshots globally accessible across workspaces. Even if input paths are sanitized, users may still access out-of-scope data indirectly through shared snapshot storage, defeating the stated boundary.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The skill claims single-file version management within a workspace, but the storage design explicitly places snapshots in shared global storage and states they are accessible across workspaces. That creates a cross-workspace data exposure risk where content, metadata, and history from one project may be listed or restored in another.

Ssd 3

Medium
Confidence
94% confidence
Finding
The version file structure stores full content and content-derived summaries, and the examples show those values being surfaced directly. In combination with shared storage and version listing, this creates a straightforward path for sensitive user data to persist and be exposed beyond its original context.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This code file contains natural-language descriptions that exclusively use Chinese for the module docstring and user-facing help text. Under the policy, forcing a specific language without offering a user choice or documenting a justified locale constraint is a natural-language policy violation.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The code explicitly falls back to matching version history by rel_path across all workspaces and can alias an existing history into the current workspace under a new key. This breaks the stated per-workspace/per-file isolation model and can cause a user in one workspace to read, diff, restore, or inherit snapshots originating from another workspace with the same relative filename, potentially exposing sensitive content across project boundaries.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
When listing versions for a file, the lookup uses _find_file_key_by_rel_path, which searches all indexed files and returns matches from other workspaces if the current workspace has no local entry. In this skill context, version metadata such as filenames, timestamps, summaries, and counts can reveal information about unrelated projects stored under the same user account, so the context makes this more dangerous because the tool is expected to operate on the active workspace only.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
All CLI descriptions, prompts, and status messages shown to end users are hardcoded in Chinese. The file does not offer a locale option, fallback language, or documented reason for restricting interaction to a single language.

Natural-Language Policy Violations

Low
Confidence
89% confidence
Finding
The natural-language module description is written only in Chinese, which can constitute a locale or language policy issue when no user choice or justification is provided. The file does not indicate that the skill is region-specific or that Chinese is an intentional, documented constraint.

Static analysis

No suspicious patterns detected.