Back to skill

Security audit

CLI Scaffold Generator

Security checks for vulnerabilities and agentic risk

Overview

This CLI scaffold skill is not clearly malicious, but its generator can overwrite unintended files and can create unsafe npm project metadata.

Review before installing or running. Only use trusted scaffold names and metadata, run it in a disposable or empty directory, avoid absolute paths or ../ path components, and do not run npm install in generated output from untrusted inputs unless the generated package.json has been inspected.

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
cli-scaffold-generator.sh:4
Finding
Unrestricted project path permits files to be overwritten outside the intended output directory<![CDATA[ ## Vulnerability Details **File Location**: `cli-scaffold-generator.sh`, lines 4 and 22-45 **Vulnerability Type**: Path traversal and arbitrary file overwrite **Risk Level**: High ### Vulnerable Code ```bash NAME="${1:-my-cli}" ``` ```bash # Create directory structure mkdir -p "$NAME"/{bin,lib,test} # Generate package.json cat > "$NAME/package.json" << JSON { "name": "$NAME", "version": "1.0.0", "description": "$DESCRIPTION", "main": "bin/$NAME.js", "bin": { "$NAME": "bin/$NAME.js" }, "scripts": { "test": "jest", "start": "node bin/$NAME.js" }, "keywords": ["cli", "command-line", "$FRAMEWORK"], "author": "$AUTHOR", "license": "MIT", "dependencies": { "commander": "^11.0.0", "chalk": "^4.1.2" }, "devDependencies": { "jest": "^29.0.0" } } JSON ``` ### Technical Analysis The project name is accepted directly from the first positional argument and used as a filesystem path. The script does not reject: - Absolute paths - Parent-directory components such as `..` - Directory separators - Existing output directories - Symlinks that resolve outside the expected output location Shell quoting prevents word splitting and wildcard expansion, but it does not constrain where the path resolves. The `cat >` redirection truncates an existing `package.json` at the resolved destination before writing the generated content. Consequently, the caller can direct the script to create directories and overwrite predictable files outside the current working directory. Redirections also follow symbolic links. ### Attack Path 1. An attacker influences the project name supplied to the generator. 2. The attacker supplies a traversal or absolute path, for example: ```bash ./cli-scaffold-generator.sh ../../target ``` 3. `mkdir -p` creates or reuses the attacker-selected destination. 4. The package-generation redirection opens `../../target/package.json` with truncation enabled. 5. Any existing file at that loca ...[truncated 876 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate the project name as an identifier rather than accepting it as a path: ```bash if [[ ! "$NAME" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]]; then printf 'Error: invalid project name\n' >&2 exit 1 fi ``` 2. Use a dedicated, explicit output root and construct the destination beneath it. 3. Resolve the output root and destination to canonical paths, then verify that the destination remains inside the approved root. 4. Reject absolute paths, `..` components, directory separators, and symbolic-link destinations. 5. Refuse to overwrite an existing directory or file unless the caller provides an explicit overwrite option. 6. Create output atomically where possible and use restrictive default permissions. 7. Apply the same validated destination to every generated file instead of repeatedly constructing paths from raw input. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
cli-scaffold-generator.sh:4
Finding
Unescaped metadata permits package.json injection and npm lifecycle command execution<![CDATA[ ## Vulnerability Details **File Location**: `cli-scaffold-generator.sh`, lines 4-7 and 25-45 **Vulnerability Type**: JSON injection leading to generated-package command execution **Risk Level**: High ### Vulnerable Code ```bash NAME="${1:-my-cli}" FRAMEWORK="${2:-commander}" DESCRIPTION="${3:-A awesome CLI tool}" AUTHOR="${4:-Developer}" ``` ```bash # Generate package.json cat > "$NAME/package.json" << JSON { "name": "$NAME", "version": "1.0.0", "description": "$DESCRIPTION", "main": "bin/$NAME.js", "bin": { "$NAME": "bin/$NAME.js" }, "scripts": { "test": "jest", "start": "node bin/$NAME.js" }, "keywords": ["cli", "command-line", "$FRAMEWORK"], "author": "$AUTHOR", "license": "MIT", "dependencies": { "commander": "^11.0.0", "chalk": "^4.1.2" }, "devDependencies": { "jest": "^29.0.0" } } JSON ``` The same inputs are also embedded into generated JavaScript without JavaScript-string escaping: ```bash const { Command } = require('commander'); const program = new Command()); program .name('$NAME') .description('$DESCRIPTION') .version('1.0.0'); ``` ### Technical Analysis Caller-controlled values are inserted directly into JSON string literals without JSON serialization or escaping. A value containing quotes, commas, braces, or newlines can terminate the intended property and introduce additional package metadata. The `AUTHOR` value is especially dangerous because it appears after the legitimate `scripts` object. An attacker can close the `author` string and inject a second `scripts` object containing an npm lifecycle command. Common JSON parsers used by Node.js retain the later duplicate property, allowing the injected scripts object to supersede the legitimate one. For example, an author value conceptually equivalent to the following can produce valid JSON with a new lifecycle script: ```text x", "scripts": {"preinstall": "attacker-command"}, "injected": "x ``` If the user follows the ...[truncated 2032 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not construct JSON through direct heredoc interpolation. Generate it with a JSON-aware serializer, such as Node.js: ```bash NAME="$NAME" FRAMEWORK="$FRAMEWORK" DESCRIPTION="$DESCRIPTION" AUTHOR="$AUTHOR" \ node -e ' const fs = require("fs"); const data = { name: process.env.NAME, version: "1.0.0", description: process.env.DESCRIPTION, main: `bin/${process.env.NAME}.js`, bin: { [process.env.NAME]: `bin/${process.env.NAME}.js` }, scripts: { test: "jest", start: `node bin/${process.env.NAME}.js` }, keywords: ["cli", "command-line", process.env.FRAMEWORK], author: process.env.AUTHOR, license: "MIT", dependencies: { commander: "^11.0.0", chalk: "^4.1.2" }, devDependencies: { jest: "^29.0.0" } }; fs.writeFileSync(process.argv[1], JSON.stringify(data, null, 2) + "\n"); ' "$DESTINATION/package.json" ``` 2. Validate the package name against npm naming requirements and reject control characters. 3. Serialize values embedded in JavaScript with `JSON.stringify` or use a template system that performs context-sensitive JavaScript escaping. 4. Correct the generated syntax error: ```javascript const program = new Command(); ``` 5. Add tests using quotes, backslashes, newlines, braces, Unicode characters, and attempted lifecycle-script injection. 6. Parse the generated `package.json` in automated tests and assert that its `scripts` object contains only the intended fixed keys. 7. Consider installing generated dependencies with lifecycle scripts disabled when handling untrusted templates: ```bash npm install --ignore-scripts ``` This is defense in depth and does not replace safe serialization. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill claims multi-framework scaffold generation, but the documented output only shows a fixed Commander.js example and does not substantiate real framework-specific behavior. This mismatch can mislead users and downstream agents into making unsafe assumptions about generated project structure, dependencies, and command behavior, increasing the chance of incorrect automation or insecure manual follow-up steps.

Lp3

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

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The manifest description and primary user-facing documentation are written entirely in Chinese, which implies a fixed language experience. The file does not offer an opt-in language choice or explain that the skill is intended only for a Chinese-language audience, which can violate language/locale policy requirements.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
This shell script performs file-system writes by creating a directory tree and then writing package.json, source, and README files into the target path. Although it prints that it is generating a scaffold, it does not clearly warn that existing files in the target directory may be overwritten or modified, and there is no confirmation prompt before these writes.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
program
  .command('init')
  .description('Initialize the project')
  .option('-y, --yes', 'Skip prompts')
  .action((options) => {
    console.log('Initializing project...');
    if (options.yes) {
Confidence
85% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
if (options.yes) {
      console.log('Created config files!');
    } else {
      console.log('Run with --yes to skip prompts');
    }
  });
Confidence
85% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Natural-Language Policy Violations

Low
Confidence
89% confidence
Finding
The manifest description is written only in Chinese ("生成 CLI 脚手架"), which indicates a language-specific presentation without any visible opt-in, alternative locale, or justification for a region-specific skill. Under the policy, language constraints should either offer user choice or be clearly documented as intentional and necessary.

Static analysis

No suspicious patterns detected.