Back to skill

Security audit

workspace-organizer

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stated workspace organization and memory purpose, but its file-writing scripts do not safely constrain task and step names, which can let operations escape the intended task area and corrupt recovery data.

Review before installing. Use only trusted, simple task and step names, avoid values containing slashes, backslashes, drive prefixes, or '..', and avoid the PowerShell fallback until metadata preservation and path containment are fixed. Enable the heartbeat template only if recurring recovery checks are desired.

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

Error
Location
scripts/safe-writer.py:141
Finding
Workspace Path Traversal Through Unsanitized Task and Step Identifiers<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/safe-writer.py:141-143` - `scripts/task-memory-manager.py:61-76` - `scripts/task-memory-manager.py:107-108` - `scripts/task-memory-manager.py:132-133` - `scripts/task-memory-manager.py:215-216` - `scripts/safe-writer-ps1.txt:144-150` **Vulnerability Type**: Path traversal and insufficient path validation **Risk Level**: High ### Vulnerable Code From `scripts/safe-writer.py:141-143`: ```python task_output_dir = OUTPUT_DIR / task_id if not task_output_dir.exists(): print(f"⚠️ 任务目录不存在: {task_id}") ``` The resulting path is subsequently used to construct the metadata file: ```python meta_file = task_output_dir / ".task-meta.json" ``` From `scripts/task-memory-manager.py:61-76`: ```python def init_task(self, task_id, steps, description=""): task_dir = self.output_dir / task_id if not task_dir.exists(): print(f"⚠️ 任务目录不存在: {task_id}") return False meta_file = task_dir / ".task-meta.json" if meta_file.exists(): print(f"⚠️ 元数据已存在: {task_id}") return False for step in steps: step_dir = task_dir / step.strip() step_dir.mkdir(exist_ok=True) ``` From `scripts/task-memory-manager.py:107-108`: ```python def update_task(self, task_id, **kwargs): meta_file = self.output_dir / task_id / ".task-meta.json" ``` From `scripts/task-memory-manager.py:132-133`: ```python def add_memory_point(self, task_id, step, memory_type, summary, files=None): meta_file = self.output_dir / task_id / ".task-meta.json" ``` From `scripts/task-memory-manager.py:215-216`: ```python for task_id in task_ids: meta_file = self.output_dir / task_id / ".task-meta.json" ``` From `scripts/safe-writer-ps1.txt:144-150`: ```powershell $taskOutputDir = Join-Path $OutputDir $TaskId if (-not (Test-Path $taskOutputDir)) { Write-Host "[WARN] Task directory not found: $TaskId" return $false } $metaFile = Join-Path $taskOutputD ...[truncated 2607 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define a strict identifier format for task and step names. For example, allow only letters, digits, underscores, and hyphens: ```python import re SAFE_COMPONENT = re.compile(r"^[A-Za-z0-9_-]+$") def validate_component(value, field_name): if not value or not SAFE_COMPONENT.fullmatch(value): raise ValueError(f"Invalid {field_name}") return value ``` 2. Resolve every derived path and confirm that it remains under the trusted base: ```python def safe_child(base: Path, component: str) -> Path: validate_component(component, "path component") resolved_base = base.resolve() candidate = (resolved_base / component).resolve() try: candidate.relative_to(resolved_base) except ValueError: raise ValueError("Path escapes the permitted workspace") return candidate ``` 3. Apply containment validation separately to: - Task identifiers - Step directory names - Metadata read paths - Metadata write paths 4. Reject absolute paths, drive-qualified paths, `.` and `..`, path separators, null bytes, and alternate separator forms before filesystem access. 5. Account for symbolic-link traversal. Validate the resolved parent directory immediately before reading, creating, or replacing the target. 6. Implement equivalent canonicalization in PowerShell: - Obtain the fully resolved candidate path. - Obtain the fully resolved output root. - Verify that the candidate is a descendant of the output root using a separator-aware comparison. - Reject the operation if containment cannot be established. 7. Add automated tests covering Unix and Windows traversal forms, absolute paths, drive prefixes, UNC paths, mixed separators, and symbolic-link escapes. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/safe-writer-ps1.txt:143
Finding
PowerShell Fallback Destructively Replaces Existing Task Metadata<![CDATA[ ## Vulnerability Details **File Location**: `scripts/safe-writer-ps1.txt:143-161` **Vulnerability Type**: Unsafe destructive file replacement and state corruption **Risk Level**: Medium ### Vulnerable Code ```powershell function Update-TaskMetadata($TaskId, $Step, $MemorySnippet) { if (-not $TaskId) { return $true } $taskOutputDir = Join-Path $OutputDir $TaskId if (-not (Test-Path $taskOutputDir)) { Write-Host "[WARN] Task directory not found: $TaskId" return $false } $metaFile = Join-Path $taskOutputDir ".task-meta.json" $metadata = @{ task_id = $TaskId last_active = Get-Date -Format "yyyy-MM-ddTHH:mm:ss" } if ($Step) { $metadata.current_step = $Step } try { $jsonContent = $metadata | ConvertTo-Json $jsonContent | Out-File $metaFile -Encoding UTF8 -Force ``` ### Technical Analysis The PowerShell fallback creates a new metadata object without first loading or merging the existing `.task-meta.json`. It then writes the reduced object with `Out-File -Force`, replacing any existing metadata. As a result, fields maintained by the Python implementation are deleted, including: - Task status - Creation timestamp - Progress - Description - Step list - Memory points - File mappings The `MemorySnippet` parameter is accepted but never stored. The write is also not atomic, despite the Skill advertising safe or atomic checkpoint persistence. An interruption during `Out-File` may leave a truncated or otherwise unusable JSON document. ### Attack Path 1. A workspace contains an existing task with a populated `.task-meta.json`. 2. A user follows the documented fallback procedure by renaming and invoking `safe-writer-ps1.txt`, or Python invocation fails and the fallback path is used. 3. `Update-TaskMetadata` creates a new hash table containing only `task_id`, `last_active`, and optionally `current_step`. 4. `Out-File -Force` replaces the existing metadata fil ...[truncated 876 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Read and parse an existing metadata file before changing it: ```powershell if (Test-Path $metaFile) { $metadata = Get-Content -Raw -LiteralPath $metaFile | ConvertFrom-Json -AsHashtable } else { $metadata = @{ task_id = $TaskId status = "in_progress" created = (Get-Date).ToString("o") progress = 0 memory_points = @() file_mappings = @{} } } ``` 2. Update only the intended fields. Preserve all unknown and existing fields rather than reconstructing the document from a reduced schema. 3. Store the supplied memory snippet consistently with the Python implementation, including an identifier, timestamp, step, summary, and associated files. 4. Perform an atomic replacement: - Serialize to a uniquely named temporary file in the same directory. - Flush and close the temporary file. - Validate that it contains parseable JSON. - Replace the destination atomically where supported. - Retain the original file if any operation fails. 5. Do not use a predictable shared temporary filename. Generate a cryptographically random or GUID-based temporary name to avoid collisions between concurrent writers. 6. Add file locking or optimistic concurrency checks to prevent simultaneous updates from silently overwriting one another. 7. Create a backup before migration or replacement and restore it automatically if validation or replacement fails. 8. Add compatibility tests ensuring that the PowerShell implementation preserves every metadata field produced by the Python implementation. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (18)

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding
The skill claims a timestamp-folder creation capability, but the visible content mainly describes memory and metadata management rather than clearly implementing the advertised file-organization function. Overstating one function while under-describing other persistent storage actions creates a trust and review gap that can hide unintended data handling.

Tp4

High
Category
MCP Tool Poisoning
Confidence
84% confidence
Finding
The skill claims a timestamp-folder creation capability, but the visible content mainly describes memory and metadata management rather than clearly implementing the advertised file-organization function. Overstating one function while under-describing other persistent storage actions creates a trust and review gap that can hide unintended data handling.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill instructs use of shell commands and scripts that can read environment state and write files, but it does not declare any tool scope or permissions boundary. This makes the skill harder to sandbox and review, and increases the chance it will be invoked with broader capabilities than intended.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The natural-language content, including the manifest description, triggers, and operating instructions, is entirely in Chinese, while the file title is English and no user opt-in or locale justification is provided. This can violate language or locale policy because the skill implicitly requires a specific language for invocation and use.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The trigger phrases are broad everyday requests such as organizing files or saving progress, which can cause the skill to activate in situations the user did not intend. For a skill that writes files and invokes scripts, accidental invocation can lead to unreviewed state changes across the workspace.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The entire skill content is written in Chinese and does not indicate any option for the user to choose another language or locale. Under the policy rule, enforcing a specific language without opt-in is a natural-language policy violation unless the locale restriction is clearly documented and justified.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The entire guide, including headings, task metadata examples, statuses, and command argument examples, is written exclusively in Chinese with no indication that other languages are supported. This can violate language/locale policy when a skill implicitly requires a specific language without user opt-in or documented regional justification.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This markdown file presents all guidance in Chinese and does not indicate that the user can choose another language or that the skill is intentionally limited to a Chinese-speaking context. Under the language/locale policy, forcing a specific language without user opt-in is a natural-language policy concern.

Natural-Language Policy Violations

Medium
Confidence
87% confidence
Finding
The natural-language description in the script is written only in Chinese and presents the tool identity/instructions in that language, with no indication that other languages are supported or that the user can opt in to a locale. Per the policy, forcing a specific language without user choice is a natural-language policy concern.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
This code presents its description and user-facing messages in Chinese, starting with the module docstring, and continues that pattern throughout the script. The file provides no option for user language selection and no documented justification that the skill is intended only for a Chinese-language environment, which matches the locale-policy violation criteria.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The skill's primary human-facing description is written only in Chinese, and the CLI help/messages throughout the file are also Chinese-only. This imposes a specific language on users without any opt-in or alternative locale handling, which matches the language/locale policy violation criteria.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
`init_task` uses untrusted `task_id` and `steps` directly in filesystem path construction (`self.output_dir / task_id`, `task_dir / step.strip()`) without validating that the resolved paths remain under the intended workspace directory. An attacker can supply path traversal values such as `../` or absolute paths to create directories and metadata files outside the managed task area, potentially overwriting or planting files elsewhere on the host.

Context-Inappropriate Capability

Medium
Confidence
97% confidence
Finding
`add_memory_point` builds `meta_file = self.output_dir / task_id / '.task-meta.json'` from attacker-controlled `task_id` and then reads and rewrites that file with no containment check. This enables path traversal to target arbitrary `.task-meta.json` files outside the workspace and, if such a file exists, modify its contents, causing unauthorized file tampering and possible corruption of unrelated application state.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
try:
        # Run scan command
        result = subprocess.run(
            ['py', str(manager_script), 'scan'],
            capture_output=True,
            text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The script hard-codes Chinese status values (`进行中`, `已暂停`) and user instructions (`恢复上次任务`) without offering any language or locale choice. This can force a specific language experience on users and create a natural-language policy issue where language selection is not user-driven or explicitly justified.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The auto-recover mode restores task state automatically based on discovered active tasks, with no confirmation, trust boundary check, or warning about what content will be loaded. In a workspace/memory-management skill, loading prior task state can reintroduce untrusted instructions or stale context into a new session, increasing the chance of prompt/state injection and unintended actions.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if active_tasks:
                latest_task = active_tasks[0]['task_id']
                print(f"\nINFO: Auto-recovering: {latest_task}")
                subprocess.run([
                    'py', str(manager_script), 'load', 
                    '--task-ids', latest_task,
                    '--max-per-task', '5'
Confidence
79% confidence
Finding
This subprocess call passes latest_task, which is parsed from another script's stdout, into a state-loading command without validation or user confirmation. While list-based argument passing prevents shell injection, it can still trigger unintended recovery/loading behavior or argument confusion if the upstream output is malformed or attacker-controlled within the workspace context.

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
The comment 'Workspace Organizer quick commands (English)' indicates an English-only language constraint. There is no nearby opt-in, alternative locale support, or justification that this skill is region-specific, so it appears to impose a specific language without user choice.

Static analysis

No suspicious patterns detected.