Back to skill

Security audit

CLI builder

Security checks for vulnerabilities and agentic risk

Overview

This CLI-building skill is coherent overall, but its scaffold script can overwrite unintended files and may allow command execution from a crafted project name.

Review and fix the scaffold script before running it: restrict project names to a safe basename, refuse existing destinations unless explicitly forced, avoid sed with untrusted input, and do not copy unpinned npx commands into trusted workflows without verifying and pinning the package.

Vulnerability Patterns
  • 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
  • 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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/scaffold.sh:239
Finding
Command Injection Through Unvalidated Project Name in GNU sed<![CDATA[ ## Vulnerability Details **File Location**: `scripts/scaffold.sh`, source at line 7 and injection sink at line 239 **Vulnerability Type**: Command injection through dynamically constructed sed program **Risk Level**: High ### Vulnerable Code ```bash NAME="${1:?Usage: ./scaffold.sh <name> [--node] [--python] [--go]}" ``` ```bash sed -i "s/APPNAME/$NAME/g" main.go ``` ### Technical Analysis The project name is accepted without validation and inserted directly into a double-quoted GNU `sed` program. Shell quoting prevents ordinary shell word splitting but does not prevent `sed` from interpreting attacker-controlled delimiters, commands, flags, backslashes, or newline characters. A crafted project name can terminate the intended substitution expression and introduce an additional GNU `sed` command. In particular, GNU sed's `e` command can execute a local shell command. This behavior is unnecessary for scaffolding a Go module and violates least-privilege design. ### Attack Path 1. An attacker supplies or recommends a specially crafted project name containing sed delimiters and embedded newline characters. 2. A victim invokes `scaffold.sh` with that name and the `--go` option. 3. Line 7 stores the value in `NAME` without checking its character set. 4. The script creates and enters the corresponding path. 5. Line 239 incorporates the value into the sed program. 6. GNU sed interprets the injected content as an additional command rather than replacement text. 7. An injected `e` command executes under the account running the scaffold script. ### Impact Assessment Successful exploitation provides arbitrary command execution with the invoking user's privileges. The attacker could read or modify user-accessible files, alter source repositories, access credentials available to that account, install user-level persistence, or run network commands. The script itself does not request elevated privileges, so the direct scope is normally the current user; runni ...[truncated 73 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate `NAME` before using it in paths or generated source: ```bash if [[ ! "$NAME" =~ ^[a-z0-9][a-z0-9_-]*$ ]]; then printf 'Error: project name must contain only lowercase letters, digits, underscores, and hyphens.\n' >&2 exit 2 fi ``` 2. Do not build a sed program from untrusted input. Generate `main.go` directly with a controlled heredoc or use a replacement mechanism that treats the name strictly as data. 3. If sed remains necessary, escape every sed-significant character, including the delimiter, backslash, ampersand, and newline. Validation should still be retained as the primary control. 4. Reject control characters and path separators independently. 5. Add regression tests using delimiters, backslashes, ampersands, newline characters, sed commands, and shell metacharacters. 6. Run the scaffold script only with ordinary user privileges. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/scaffold.sh:20
Finding
Arbitrary Directory Writes and Destructive File Overwrites<![CDATA[ ## Vulnerability Details **File Location**: `scripts/scaffold.sh`, lines 7 and 20–27; equivalent overwrite operations also occur throughout lines 53–241 **Vulnerability Type**: Unrestricted path selection and unsafe file clobbering **Risk Level**: Medium ### Vulnerable Code ```bash NAME="${1:?Usage: ./scaffold.sh <name> [--node] [--python] [--go]}" LANG="node" for arg in "$@"; do case $arg in --node) LANG="node" ;; --python) LANG="python" ;; --go) LANG="go" ;; esac done echo "[cli-builder] Creating $LANG CLI: $NAME" mkdir -p "$NAME" cd "$NAME" case $LANG in node) mkdir -p src cat > package.json << EOF ``` The same truncating redirection pattern is subsequently used for files including `tsconfig.json`, `src/cli.ts`, `.gitignore`, `pyproject.toml`, `src/cli.py`, `go.mod`, `cmd/root.go`, and `main.go`. ### Technical Analysis `NAME` is treated as both a project identifier and an unrestricted filesystem path. The script accepts absolute paths, relative traversal components, existing directories, control characters, and path separators. `mkdir -p` succeeds when the destination already exists, after which `cat > file` truncates existing files without confirmation. Shell redirection also follows symbolic links. Consequently, a user mistake or attacker-controlled argument can cause writes outside a newly created project directory or overwrite existing repository files. This write scope exceeds the minimum permissions required to create a fresh scaffold. ### Attack Path 1. An attacker persuades a user to invoke the script with an absolute path, a traversal path, or the path of an existing project directory. 2. `mkdir -p "$NAME"` succeeds even if the target directory already exists. 3. `cd "$NAME"` changes into the attacker-selected location. 4. The selected language branch opens known filenames using truncating redirection. 5. Existing files with those names are replaced. 6. If one of those paths is a symbolic link, the li ...[truncated 527 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Separate the project name from the destination path. 2. Require the name to be a simple basename and reject `/`, `\`, `.`, `..`, absolute paths, control characters, and empty values. 3. Refuse to operate when the destination already exists unless the user explicitly supplies a documented `--force` option. 4. Use no-clobber file creation and fail if any generated target exists: ```bash set -euo pipefail set -o noclobber ``` 5. Resolve and verify the destination against an explicitly selected parent directory before writing. 6. Check for symbolic links in the destination and generated file paths. Prefer creating a new directory atomically and writing only inside it. 7. If overwrite support is required, list affected files, request confirmation, and create backups before modification. 8. Add tests covering existing directories, absolute paths, traversal paths, symlinked files, and partially generated projects. ]]>

T08 · Insecure Dependencies

Note
Location
SKILL.md:436
Finding
Unpinned Third-Party Package Download and Immediate Execution Guidance<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 436 and 464 **Vulnerability Type**: Unsafe supply-chain guidance using unpinned npx packages **Risk Level**: Low ### Vulnerable Code ```bash npx mytool # Users can run without installing ``` ```bash # Using pkg npx pkg . --targets node20-linux-x64,node20-macos-x64,node20-win-x64 ``` ### Technical Analysis `npx` can retrieve a package from the configured npm registry and immediately execute its code. The examples do not specify exact versions, require a lockfile, verify package integrity, or establish the package publisher's identity. The name `mytool` is intended as a placeholder, but copying the example literally could resolve an unrelated public package. Likewise, unversioned execution of `pkg` allows the effective downloaded implementation to change after the Skill has been reviewed. This creates a dependency-confusion, package-takeover, or compromised-release exposure. ### Attack Path 1. A user or agent follows the documentation and runs one of the unpinned `npx` commands. 2. `npx` resolves the package name and current applicable version through the configured registry. 3. If the package name is unintended, compromised, taken over, or resolved through a malicious registry configuration, attacker-controlled package code is downloaded. 4. Package lifecycle behavior or the requested CLI executes with the user's privileges. ### Impact Assessment A malicious resolved package could execute arbitrary commands with the invoking user's permissions, access project files and environment variables, modify local source or configuration, and make network requests. Exploitation depends on registry resolution or package compromise; no evidence shows that the packages currently referenced are malicious. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace placeholder package names before publishing executable examples. 2. Pin trusted tools to reviewed exact versions, for example: ```bash npx --yes pkg@<reviewed-exact-version> . --targets node20-linux-x64,node20-macos-x64,node20-win-x64 ``` 3. Prefer installing dependencies into a project with a committed lockfile and invoking the local binary. 4. Verify package ownership, provenance, signatures where available, and registry configuration before execution. 5. Use npm integrity and lockfile controls in CI. 6. Clearly warn that `npx` may download and execute remote code and should not be run with elevated privileges. 7. For `mytool`, use a clearly non-runnable placeholder or instruct authors to replace it with their verified package name and exact version. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (7)

Vague Triggers

Medium
Confidence
94% confidence
Finding
The activation criteria are very broad, covering not only CLI construction but also terminal colors, ANSI escape codes, stdin/stdout piping, packaging, plugin systems, and cross-platform terminal behavior. Overly broad triggering can cause the agent to invoke this skill for common requests outside its intended scope, increasing the chance of irrelevant guidance, unsafe command suggestions, or unintended authority over packaging/execution-related tasks.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Natural-Language Policy Violations

Low
Confidence
90% confidence
Finding
The config example sets `lang` to `en` by default, which is a natural-language locale choice embedded in the skill. Under the policy, forcing a specific language without explicit user opt-in or a documented region-specific reason can be a violation.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
The config example includes a natural-language locale value of "lang": "en", which implies an English default without offering any visible opt-in, alternative locale selection, or justification. Under the language/locale policy rule, this is a policy concern because the file presents a fixed language setting rather than user choice.

Missing User Warnings

Low
Confidence
80% confidence
Finding
The script creates a directory and changes into it, then proceeds to generate multiple project files in that location. Although it prints a creation status message, there is no explicit user-facing warning or confirmation that running the script will write several files into the target path and may overwrite existing scaffold contents.

Missing User Warnings

Low
Confidence
75% confidence
Finding
This command rewrites main.go in place after it has been created, which is a file modification operation. While expected in a scaffold script, there is no specific disclosure that an in-place edit occurs, only generic success messages after the fact.

Static analysis

No suspicious patterns detected.