Back to skill

Security audit

agent-project-structure

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a straightforward project-structure helper, but its creation script can overwrite existing files and follow symlinks outside the chosen project path.

Review before installing if you work in existing projects or shared directories. Use the create script only on a new empty directory or after checking for existing files and symlinks, because accepting the prompt on an existing path may overwrite configuration placeholders such as config/settings.json.

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/create_structure.py:61
Finding
Unsafe Overwrite and Symlink Following During Project Structure Creation## Vulnerability Details **File Location**: `scripts/create_structure.py`, lines 61-65 **Vulnerability Type**: Unsafe file overwrite and symlink traversal **Risk Level**: Medium ### Vulnerable Code ```python for file_path, content in example_files.items(): full_path = project_path / file_path full_path.parent.mkdir(parents=True, exist_ok=True) with open(full_path, 'w') as f: f.write(content) ``` The relevant generic confirmation logic is at lines 84-89: ```python if project_path.exists(): print(f"警告: 路径已存在: {project_path}") response = input("是否继续? (y/N): ") if response.lower() != 'y': print("已取消") sys.exit(0) ``` ### Technical Analysis The script opens every placeholder file with mode `w`, which truncates an existing file before writing the new content. It does not check whether individual files already exist or disclose which files will be replaced. For example, an existing `config/settings.json` is unconditionally replaced with `{}` after the user accepts only a generic project-level confirmation. The script also does not reject symbolic links or verify resolved-path containment. If a target file such as `config/settings.json`, or one of its parent directories, is a symbolic link, Python follows that link when opening the destination. A crafted project directory can therefore redirect a write outside the selected project root. This is a fixed-content arbitrary file-write primitive rather than arbitrary-content code execution: the attacker can choose a writable target through a symlink, while the content written is determined by the script's `example_files` mapping. ### Attack Path 1. An attacker prepares a directory that appears to be an existing project. 2. The attacker creates a symbolic link at a generated path, such as `config/settings.json`, pointing to a file writable by the victim. Alternatively, the directory already contains legitimate files at the placeholder paths. 3. The victim or an Agent ...[truncated 1305 chars]
Remediation
## Remediation Suggestions 1. **Do not overwrite existing files by default.** Use exclusive creation mode and handle `FileExistsError`: ```python with open(full_path, "x", encoding="utf-8") as f: f.write(content) ``` Alternatively, explicitly skip every destination that already exists. 2. **Require granular overwrite consent.** If replacement is supported, enumerate the exact files that would be changed and require explicit confirmation before modifying them. 3. **Reject symbolic links.** Check every existing destination and parent path component with `is_symlink()` or `os.lstat()` and abort if a symbolic link is encountered. 4. **Enforce path containment.** Resolve the project root and each destination, then verify that every destination remains beneath the resolved root before writing: ```python root = project_path.resolve() destination = full_path.resolve(strict=False) destination.relative_to(root) ``` Abort when `relative_to` raises `ValueError`. 5. **Reduce race-condition exposure.** Path checks alone can be bypassed if an attacker can modify directories concurrently. On supported platforms, use directory-relative file operations with no-follow semantics, such as `openat`-style operations and `O_NOFOLLOW`. 6. **Use atomic replacement only when intentional.** Write to a safely and exclusively created temporary file within the verified destination directory, set appropriate permissions, and atomically rename it after explicit authorization. 7. **Add regression tests** covering existing files, symlinked target files, symlinked parent directories, paths outside the project root, and cancellation without filesystem changes.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (13)

Credential Access

High
Category
Privilege Escalation
Content
Thumbs.db

# 环境变量文件
.env
.env.local
.env.*.local
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# 环境变量文件
.env
.env.local
.env.*.local

# 构建和依赖
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
│   └── cache/
├── config/            # 配置文件目录
│   ├── settings.json
│   └── secrets.json
├── data/              # 数据文件目录
│   ├── input/
│   └── output/
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
│   └── cache/
├── config/            # 配置文件目录
│   ├── settings.json
│   └── secrets.json
├── data/              # 数据文件目录
│   ├── input/
│   └── output/
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
│   └── cache/
├── config/            # 配置文件目录
│   ├── settings.json
│   └── secrets.json
├── data/              # 数据文件目录
│   ├── input/
│   └── output/
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
│   └── cache/
├── config/            # 配置文件目录
│   ├── settings.json
│   └── secrets.json
├── data/              # 数据文件目录
│   ├── input/
│   └── output/
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The markdown content is entirely in Chinese, including headings and usage instructions, with no indication that users may choose another language or that the skill is intentionally limited to a Chinese-speaking audience. This can violate a language/locale policy when a skill mandates one language without opt-in or justification.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill instructs the agent to create or adjust project directory structures and explicitly references scripts that would write files, but the skill metadata does not declare any tool scope such as permissions or allowed-tools. This creates an authorization gap where a broadly triggered skill could cause filesystem modifications without clear least-privilege boundaries or reviewer visibility.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The trigger phrases are generic terms like 'create a project', 'new project', and 'project structure', and the skill says it should default-trigger unless the user specifies otherwise. That makes unintended activation likely during ordinary conversations, increasing the chance the agent applies this skill and performs directory creation or reorganization when the user did not explicitly request filesystem changes.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This markdown file uses Chinese section headings throughout, such as the labels for logs, temporary files, screenshots, and other categories. Under the stated policy, forcing a specific language without opt-in or justification is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The title and the document content are written in Chinese, and there is no indication that other languages are supported or that Chinese is required for a region-specific purpose. Under the language/locale policy rule, forcing a specific language without user opt-in can be a policy violation.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The file's docstrings and all user-facing CLI messages are written only in Chinese, including usage, errors, and success output. This imposes a language choice on users without offering an alternative or documenting that the tool is intended only for a Chinese-speaking audience.

Natural-Language Policy Violations

Low
Confidence
98% confidence
Finding
The docstrings, usage text, warnings, prompts, and status messages are all hard-coded in Chinese throughout the script. This creates a language/locale policy concern because the skill does not offer any user-selectable language option or document a justified locale restriction.

Static analysis

No suspicious patterns detected.