Back to skill

Security audit

Workspace Init

Security checks for vulnerabilities and agentic risk

Overview

This workspace setup skill is not deceptive, but it needs review because it can run unpinned third-party code, change agent-facing workspace files, and install persistent repository hooks.

Install only if you intend this skill to make broad workspace changes. Review the repo list, generated CLAUDE.md, OpenSpec config, dependency install steps, and any template-update diff before allowing execution; avoid using untrusted repo URLs or free-form values supplied by someone else, and be aware that package installs and pre-commit hooks can run code from those repositories.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (3)

T02 · Agent Memory Poisoning

Error
Location
SKILL.md:51
Finding
Persistent Agent Instruction Injection Through Generated Configuration<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:51-109`, `SKILL.md:156-169`, `SKILL.md:200-209`, and `SKILL.md:400-405` **Vulnerability Type**: Persistent instruction and configuration injection **Risk Level**: High ### Vulnerable Code Snippet ```markdown ### 1.2 User profile 1. **Role** -- what they do. Goes into CLAUDE.md `[ROLE]`. Example: "a backend developer", "a full-stack engineer" 1. **Experience level** -- "experienced" or "learning while developing". Goes into CLAUDE.md `[LEVEL]`. 1. **Preferred language** -- for AI conversations and documentation. Goes into CLAUDE.md `[YOUR_LANGUAGE]`. Example: "English", "简体中文", "日本語" ``` ```markdown ### 2.3 Customize CLAUDE.md Read the template CLAUDE.md and replace all placeholders. For the complete mapping of placeholders to collected values, read `references/claude-md-fields.md`. Key replacements: - `[ROLE: e.g., ...]` -> collected role - `[LEVEL: e.g., ...]` -> collected level - `[YOUR_LANGUAGE: e.g., ...]` -> collected language (appears twice) - `[YOUR_FORMAT_COMMAND]` -> confirmed formatter - `[YOUR_LINT_COMMAND]` -> confirmed linter - `[YOUR_TYPE_CHECK_COMMAND]` -> confirmed type checker - `[YOUR_TEST_COMMAND]` -> confirmed test runner - `[PROJECT_STYLE_GUIDE: e.g., ...]` -> style guide based on tech stack - Repository table in section 1 -> generated from repo list ``` ```markdown ### 3.2 Generate config.yaml Read `references/config-template.yaml` and populate it with: - `{project_name}` -> collected project name - `{description}` -> collected description - `{repos_list}` -> formatted repo list, one per line: ```text - **{name}**: {description} ``` Write the result to `openspec/config.yaml`. ``` ```markdown **CLAUDE.md** (partially customized): - Fetch the new template version - Extract the user's current filled values (role, level, language, commands, repo table) - Apply the new template structure - Re-fill the extracted values into the new template - Show the us ...[truncated 2544 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define strict schemas for every collected value: - Restrict project and repository names to safe identifiers. - Require role, language, and descriptions to be single-line values. - Enforce reasonable length limits. - Reject control characters and unexpected Markdown headings, code fences, or instruction-like blocks. 2. Do not place untrusted user content directly into Agent instruction sections. Store user metadata in a separate structured data file and reference it as data. 3. Allow only predefined development commands, or construct commands from an allowlist of executable names and fixed arguments. 4. Generate YAML with a maintained YAML serialization library rather than textual placeholder replacement. 5. Escape Markdown table delimiters, line breaks, backticks, and other structural characters before generating `CLAUDE.md`. 6. Show the complete generated diff and require explicit confirmation before writing instruction-bearing files. 7. During update mode, validate previously stored values again before reinserting them. Do not assume existing workspace content is trusted. 8. Mark generated data boundaries clearly so that future Agents can distinguish user-supplied metadata from authoritative instructions. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:78
Finding
Command Injection and Workspace Escape Through Unvalidated Project and Repository Names<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:78-89`, `SKILL.md:147-157`, `SKILL.md:215-234`, and `SKILL.md:256-266` **Vulnerability Type**: Command injection and path traversal **Risk Level**: High ### Vulnerable Code Snippet ```markdown ### 1.4 Sub-repositories Collect repos one at a time in a loop: 1. For each repo, ask: - **Name** -- identifier, used as directory name. Example: "sunlite-backend" - **Git URL** -- clone URL. Example: `git@github.com:org/repo.git` - **Description** -- short description for CLAUDE.md table. Example: "Backend API service" ``` ```json { "repos": [ { "name": "{name}", "url": "{git_url}", "path": "repos/{name}" } ] } ``` ```bash cd repos/{name} python3 -m venv venv source venv/bin/activate pip install -e ".[dev]" 2>/dev/null || pip install -e . ``` ```bash cd repos/{name} # Use bun if bun.lockb exists, otherwise npm if [ -f bun.lockb ]; then bun install else npm install fi ``` ```markdown Generate `{project-name}.code-workspace`: ```json { "folders": [ { "path": ".", "name": "Config" }, { "path": "repos/{name1}", "name": "{Name1}" }, { "path": "repos/{name2}", "name": "{Name2}" } ] } ``` ``` ### Technical Analysis Repository names and project names are user-controlled and are reused as directory names, shell fragments, JSON values, and filenames. The instructions do not require validation, quoting, canonicalization, or a workspace-containment check. If an Agent follows the command templates by textual substitution, shell metacharacters in `{name}` can terminate or alter the `cd` command and introduce additional commands. Separately, names containing `../`, absolute path syntax, or path separators can cause generated paths to escape the intended `repos/` directory. Direct string interpolation into JSON can also produce malformed or attacker-modified `repos.json` and VSCode workspace configuration if quotation marks, backslashes, or control ...[truncated 1530 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate project and repository names with a restrictive pattern such as: ```text ^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$ ``` 2. Explicitly reject: - `..` - `/` and `\` - absolute paths - shell metacharacters - quotation marks - newlines and control characters 3. Resolve every generated path with `Path.resolve()` and verify that it remains under the expected workspace or `repos/` root using a containment check. 4. Do not build executable shell strings. Invoke programs through argument-array APIs such as Python `subprocess.run([...], shell=False)`. 5. Use process working-directory parameters instead of generating `cd` commands. 6. Generate JSON using a JSON serializer rather than textual interpolation. 7. Normalize and validate filenames before creating the `.code-workspace` file. 8. Validate repository URLs against supported Git URL formats and require confirmation before cloning from an unfamiliar host. 9. Add test cases covering shell characters, quotes, Unicode control characters, traversal sequences, absolute paths, and excessively long names. ]]>

T08 · Insecure Dependencies

Error
Location
SKILL.md:21
Finding
Execution of Unpinned and Unreviewed Third-Party Dependency Code<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:21-27`, `SKILL.md:173-180`, `SKILL.md:215-243`, and `SKILL.md:390-405` **Vulnerability Type**: Unsafe dependency installation and mutable upstream code execution **Risk Level**: High ### Vulnerable Code Snippet ```markdown | Tool | Required | Install | |------|----------|---------| | git | Yes | Pre-installed on most systems | | jq | Yes | `brew install jq` (macOS) / `sudo apt install jq` (Ubuntu) | | openspec | Yes | `npm install -g openspec` | ``` ```bash ./script/setup ``` ```bash cd repos/{name} python3 -m venv venv source venv/bin/activate pip install -e ".[dev]" 2>/dev/null || pip install -e . ``` ```bash cd repos/{name} # Use bun if bun.lockb exists, otherwise npm if [ -f bun.lockb ]; then bun install else npm install fi ``` ```bash cd repos/{name} pre-commit install ``` ```markdown For each changed template file: **script/setup, .gitignore, .editorconfig** (non-customized files): - Fetch the new version and overwrite directly **CLAUDE.md** (partially customized): - Fetch the new template version - Extract the user's current filled values (role, level, language, commands, repo table) - Apply the new template structure - Re-fill the extracted values into the new template - Show the user a diff of structural changes for review ``` ### Technical Analysis The Skill installs the global `openspec` npm package without a pinned version or integrity constraint. It also clones user-selected repositories and runs package installation commands inside them. Python editable installation can invoke the repository's selected build backend. `npm install` and `bun install` can execute package lifecycle scripts. Installing pre-commit configuration creates executable Git hooks whose behavior is controlled by repository configuration. In addition, `./script/setup` is executed from the workspace template, and update mode can replace this script with content fetched from the mutable remote ` ...[truncated 1775 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin `openspec` to a reviewed exact version and verify package integrity before installation. 2. Prefer a project-local dependency over a global npm installation. 3. Pin cloned repositories and template updates to reviewed commit SHAs rather than mutable branches. 4. Display remote origin, commit SHA, signatures where available, and a complete diff before executing or replacing any file. 5. Require separate, explicit approval before each operation capable of executing third-party code. 6. For Node.js dependencies: - Use lockfiles with immutable or frozen installation modes. - Initially disable lifecycle scripts. - Review scripts before permitting execution. 7. For Python dependencies: - Use pinned requirements with hashes. - Inspect `pyproject.toml`, the selected build backend, and setup code before installation. - Build and install in an isolated environment with minimal credentials. 8. Review `.pre-commit-config.yaml` before installing hooks, pin hook revisions, and inform the user that hooks persist in the repository. 9. Never execute a remotely replaced `script/setup` automatically. Require review of its exact contents and commit before execution. 10. Run dependency installation in a sandbox or container without SSH agents, cloud credentials, signing keys, or unrelated workspace access whenever practical. ]]>
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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Lp3

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding
The skill instructs the agent to read multiple local files such as `CLAUDE.md`, `references/claude-md-fields.md`, `references/config-template.yaml`, `.workspace-init-version`, and repository contents, but it does not declare an explicit tool scope like `permissions` or `allowed-tools`. In an agent environment, missing scope boundaries can lead to broader-than-expected file access and makes it harder for users or policy layers to constrain what the skill may read.

Vague Triggers

Medium
Confidence
96% confidence
Finding
Broad trigger phrases like `initialize` and `set up my project` are generic and can cause this skill to activate in contexts unrelated to `dev-config-template`. Because the skill performs cloning, file writes, environment setup, and commits, accidental invocation can lead to unintended workspace changes and network activity.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
| Tool | Required | Install |
|------|----------|---------|
| git | Yes | Pre-installed on most systems |
| jq | Yes | `brew install jq` (macOS) / `sudo apt install jq` (Ubuntu) |
| openspec | Yes | `npm install -g openspec` |

> Do NOT verify prerequisites on skill load. Check them at the start of
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
| Tool | Required | Install |
|------|----------|---------|
| git | Yes | Pre-installed on most systems |
| jq | Yes | `brew install jq` (macOS) / `sudo apt install jq` (Ubuntu) |
| openspec | Yes | `npm install -g openspec` |

> Do NOT verify prerequisites on skill load. Check them at the start of
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The `When to Use` section repeats broad trigger examples without adding clear scope checks, reinforcing the chance of over-triggering. In this skill's context, mistaken activation is more dangerous than usual because later phases perform automated repository cloning, dependency installation, and git commits without further prompts.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The finalization step performs `gh api` calls to GitHub to retrieve the upstream template commit SHA, but the skill description frames the behavior mainly as local workspace initialization/update. Undisclosed network access is dangerous because it expands the trust boundary, may leak repository context or metadata, and can surprise users in restricted or compliance-sensitive environments.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
Update mode fetches remote template state and diffs from GitHub using `gh api`, which goes beyond purely local workspace manipulation and introduces remote-content trust. This is risky because the skill may ingest and apply externally fetched changes into local files, enabling unintended modification if the remote source changes or the user did not expect network-backed updates.

Static analysis

No suspicious patterns detected.