Back to skill

Security audit

Context Visualization

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it says, but it reads and inventories agent memory files by default, which is broader than a simple context-usage view.

Review this before installing if your workspace memory/ directory may contain private notes or sensitive records. The skill does not appear to transmit or persist data, but it will process local memory files to produce estimates; use it only on workspaces where that local inspection is acceptable.

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

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/estimate_tokens.py:30
Finding
Unrestricted Recursive Reading of Agent Memory Files## Vulnerability Details **File Location**: `scripts/estimate_tokens.py`, lines 30-65 and 89-91 **Vulnerability Type**: Excessive file access and insufficient path containment **Risk Level**: Medium ### Vulnerable Code ```python def scan_memory_dir(workspace: str): """Scan memory/ directory for all files, grouped by type.""" memory_dir = os.path.join(workspace, "memory") if not os.path.isdir(memory_dir): return [], 0, 0 entries = [] total_tokens = 0 total_bytes = 0 for root, dirs, files in os.walk(memory_dir): # Skip hidden dirs dirs[:] = [d for d in dirs if not d.startswith('.')] for fname in sorted(files): if fname.startswith('.'): continue fpath = os.path.join(root, fname) rel = os.path.relpath(fpath, workspace) try: size = os.path.getsize(fpath) total_bytes += size # Estimate tokens for text files only if fname.endswith(('.md', '.json', '.txt', '.yaml', '.yml')): with open(fpath, 'r', encoding='utf-8', errors='replace') as f: content = f.read() tokens = estimate_tokens(content) else: tokens = 0 # binary files total_tokens += tokens entries.append({ "path": rel, "bytes": size, "tokens": tokens, }) except (OSError, IOError): continue return entries, total_tokens, total_bytes ``` ```python # Memory files (NOT in context, but useful inventory) mem_entries, mem_tokens, mem_bytes = scan_memory_dir(workspace) ``` ### Technical Analysis The script accepts a caller-controlled workspace path and recursively traverses its `memory/` directory. It opens every non-hidden file with a supported text extension and reads the enti ...[truncated 2511 chars]
Remediation
## Remediation Suggestions 1. **Avoid reading memory contents by default.** Use `os.stat()` or `Path.stat()` to report file counts and byte sizes. If token estimation requires content access, make it an explicit opt-in operation with a clear privacy warning. 2. **Canonicalize and validate the workspace root.** Resolve the supplied workspace before traversal: ```python workspace_root = Path(workspace).resolve(strict=True) memory_root = (workspace_root / "memory").resolve(strict=True) memory_root.relative_to(workspace_root) ``` 3. **Enforce containment for every file.** Resolve each candidate and reject it unless it remains under `memory_root`: ```python candidate = Path(root, fname) if candidate.is_symlink(): continue resolved = candidate.resolve(strict=True) try: resolved.relative_to(memory_root) except ValueError: continue ``` 4. **Skip symbolic links.** Use `os.lstat()` or `Path.is_symlink()` before size checks and file opening. Where supported, use no-follow semantics and verify the opened file descriptor to reduce time-of-check/time-of-use risks. 5. **Apply resource limits.** Limit maximum file size, total bytes read, and traversal depth to prevent memory exhaustion or denial of service from unusually large files or directory trees. 6. **Handle decoding consistently.** The top-level workspace files are opened without `errors='replace'`, while memory files use replacement behavior. Apply explicit error handling so malformed input cannot unexpectedly terminate the audit operation. 7. **Document the data-access boundary.** Clearly state whether the Skill performs metadata-only inventory or content-based estimation, and require user confirmation before processing long-term Agent memory.
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • 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 (2)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The skill promises a trustworthy visualization of current context usage, but its method relies on rough heuristics, a fixed system-overhead estimate, and inferred message-token residuals rather than measuring the claimed components directly. That mismatch can mislead users about actual context occupancy and also encourages inventorying files under memory/, expanding data exposure beyond the narrowly described purpose and potentially revealing sensitive file names, categories, or approximate sizes.

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Static analysis

No suspicious patterns detected.