Back to skill

Security audit

Self-Evolved dev-tools

Security checks for vulnerabilities and agentic risk

Overview

This is a local developer toolkit, but its installer and CLI run broad, unpinned commands and contain unsafe shell handling that could execute unintended code in a crafted repository.

Install only if you trust the publisher and plan to use it in trusted repositories. Avoid running install.sh as root, prefer pinned local tool dependencies, and do not run dev-tk review, fmt, or dep on untrusted code until the shell handling and unpinned package execution are fixed.

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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/dev-tk.js:45
Finding

Shell Command Injection Through Attacker-Controlled Git Filenames

Content
View full analysis
&1 || python3 -m py_compile {} 2>&1" 2>/dev/null || true'); ``` The `run` function executes this string through a shell: ```javascript function run(cmd, opts = {}) { try { const out = execSync(cmd, { encoding: 'utf8', stdio: 'pipe', ...opts }); return { ok: true, out: out.trim() }; } catch (e) { return { ok: false, out: e.stdout?.trim() || '', err: e.stderr?.trim() || e.message }; } } ``` ### Technical Analysis The command obtains filenames from `git diff` and passes them through `xargs` into a `sh -c` command. The `{}` placeholder is inserted directly into shell source without shell-safe quoting. Git permits filenames containing spaces, quotes, command substitutions, semicolons, and other shell metacharacters. Consequently, a repository can contain a changed filename that modifies the syntax of the generated shell command. Because `sh -c` interprets the resulting text as shell code, a malicious filename can cause arbitrary commands to execute. The filename is substituted three times: once in `echo`, once as an argument to `node -c`, and once as an argument to `python3 -m py_compile`. Any of these unquoted substitutions may alter shell parsing. The use of `|| true` suppresses the resulting failure status and may make exploitation less visible to the user. ### Attack Path 1. An attacker creates or modifies a Git-tracked file whose filename contains shell metacharacters and an injected command. 2. The attacker distributes the repository or submits the change for review. 3. A victim checks out the repository and runs `dev-tk review`. 4. `git diff --name-only` emits the attacker-controlled filename. 5. `xargs ...[truncated 1054 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/dev-tk.js:235
Finding

Path Traversal in Project Scaffolding

Content
View full analysis
<类型: node|python|vue|go>\n'); return; } const dir = './' + name; if (fs.existsSync(dir)) { console.log('❌ 目录已存在: ' + name); return; } fs.mkdirSync(dir, { recursive: true }); switch (type) { case 'node': fs.writeFileSync(dir + '/package.json', JSON.stringify({ name, version: '1.0.0', private: true, scripts: { start: 'node src/index.js', test: 'jest' } }, null, 2)); fs.mkdirSync(dir + '/src'); fs.writeFileSync(dir + '/src/index.js', 'console.log("Hello from ' + name + '");\n'); fs.mkdirSync(dir + '/test'); fs.writeFileSync(dir + '/.gitignore', 'node_modules/\n.env\n'); console.log('✅ Node.js 项目已创建: ' + name); break; case 'python': fs.writeFileSync(dir + '/pyproject.toml', `[project]\nname = "${name}"\nversion = "1.0.0"\n`); fs.mkdirSync(dir + '/src/' + name, { recursive: true }); fs.writeFileSync(dir + '/src/' + name + '/__init__.py', ''); fs.writeFileSync(dir + '/.gitignore', '__pycache__/\n.venv/\n.env\n'); console.log('✅ Python 项目已创建: ' + name); break; case 'vue': fs.writeFileSync(dir + '/vite.config.js', 'import { defineConfig } from "vite";\nexport default defineConfig({});\n'); console.log('✅ Vue 项目骨架已创建: ' + name); break; default: console.log('❌ 不支持的模板: ' + type); } } ``` ### Technical Analysis The scaffold name is accepted directly from a command-line argument and concatenated into filesystem paths: ```javascript const dir = './' + name; ``` There is no validation that `name` is a single s ...[truncated 2054 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/dev-tk.js:112
Finding

Implicit Retrieval and Execution of Unpinned npm Packages Through npx

Content
View full analysis
&1 || true'); ``` ### Technical Analysis The CLI uses `npx` to locate and execute `prettier`, `eslint`, and `madge`. Depending on the npm version, configuration, environment, and whether a local executable exists, `npx` can resolve and download a package from a configured registry before executing it. The package versions are not pinned in these commands, and the CLI does not require a project lockfile or verify package integrity. As a result, behavior can change after the Skill itself has been reviewed. The executed package may come from: - The current project's dependencies. - A mutable package registry. - A user-controlled or compromised npm registry configured in `.npmrc`. - A compromised package release or dependency chain. Using `npx --version` as an availability check is especially problematic because checking for the tool can itself trigger package resolution or installation. ### Attack Path 1. A user runs `dev-tk fmt` or `dev-tk dep` in a project where the relevant executable is not safely locked and installed locally. 2. `npx` attempts to resolve the named package using npm's current configuration. 3. The package may be obtained from a remote or attacker-controlled registry, depending on the environment. 4. npm installation life ...[truncated 975 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
install.sh:8
Finding

Unpinned Global and Environment-Wide Dependency Installation

Content
View full analysis
/dev/null; then echo " ✅ Node.js $(node -v)" npm install -g prettier 2>/dev/null && echo " ✅ prettier 已安装" || echo " ⚠️ prettier 安装失败" else echo " ⚠️ 需要 Node.js: https://nodejs.org" fi # Python 工具 echo "" echo "📦 Python 工具..." if command -v python3 &>/dev/null; then pip install flake8 black 2>/dev/null && echo " ✅ flake8 + black 已安装" || echo " ⚠️ Python 工具安装失败" fi ``` ### Technical Analysis The installation script installs the latest resolvable versions of `prettier`, `flake8`, and `black` without version constraints, lockfiles, or hash verification. `npm install -g prettier` modifies the user's or system's global npm environment. Depending on npm configuration and invocation privileges, this may affect software outside the audited Skill. `pip install flake8 black` installs into whichever Python environment the `pip` executable references. The script checks for `python3` but does not bind installation to `python3 -m pip`, verify that `pip` belongs to that interpreter, or create an isolated virtual environment. Package-manager operations can execute package build or installation logic and resolve transitive dependencies. Because the selected versions and artifacts are mutable, the installed code may differ across executions after the Skill has been reviewed. The redirection of standard error to `/dev/null` also hides useful security and provenance warnings. ### Attack Path 1. A user follows the documented installation procedure and runs `bash install.sh`. 2. The script invokes npm and pip using the user's current registry and index configuration. 3. The package managers resolve current, unpinned releases and their transitive dependencies. 4. Download ...[truncated 958 chars]
Remediation
View remediation
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (13)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

整体上,代码确实属于“开发工具箱”,并且与脚手架、技术债务、依赖分析等描述部分吻合。但声明明显比实际能力更宽、更强:尤其是 Git、CI/CD、规范管理、完整测试与代码审查等,在代码中没有对应的实质性实现,或只以非常有限的辅助检查形式出现。代码的主要行为是一个本地 CLI 工具,侧重预提交检查、格式化、依赖统计、TODO 扫描和简单脚手架,而不是完整覆盖声明中的全部功能范围。因此应判定为描述与实际行为存在不匹配,属于过度声明能力。

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
65% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · SKILL.md (reported line 54)May include surrounding context.

md
### 安全回滚
- 用 `git stash` 保存当前工作
- 用 `git revert` 代替 `git reset --hard`

---

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill advertises actions that install software, modify repositories, generate files, and run local commands, but it does not present a clear, centralized risk warning or consent model. In an agent context, this increases the chance of unintended code execution, workspace modification, dependency installation, or documentation generation without the user understanding the side effects.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

该 markdown 文件在“使用示例”中把“帮我搭个Node项目”“检查代码能不能提交”“分析一下这个项目的依赖关系”“格式化所有代码”等自然语言直接映射为技能调用,但没有给出限定上下文、明确触发短语集合或排除示例。这些表达都属于开发场景中常见的普通请求,可能导致技能在用户只是讨论需求时被过度触发。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script’s comments and all user-facing echo messages are in Chinese, which imposes a specific language on users without any opt-in or locale selection mechanism. Under the policy criteria, forced language/locale behavior is a natural-language policy violation unless the constraint is explicitly justified or optional.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The banner and command descriptions are written in Chinese, and all user-facing output throughout the script follows that locale. There is no indication that the tool is region-specific or that users can opt into another language, which may violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding

The CLI invokes npx prettier without pinning a version, so execution may resolve to whatever version is locally available or fetched at runtime. In a developer-tool skill that runs commands on the host, this introduces supply-chain and reproducibility risk because a compromised or unexpected package version could execute arbitrary code in the user's environment.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding

This command again executes npx prettier without an exact version, creating a runtime trust boundary to the npm ecosystem. Because the tool is a local developer CLI intended to modify repository contents, an unintended package version could run arbitrary code and alter files.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding

The skill checks for ESLint using npx eslint --version without pinning, which can trigger execution of an untrusted or drifting package version. In a dev-tooling context, this is meaningful because the command runs on the developer machine and may fetch or execute code from the package registry.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding

Running npx eslint --fix . without version pinning combines supply-chain exposure with write access to the working tree. If a malicious or incompatible package version is executed, it could run arbitrary code and silently change repository files.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

The dependency analysis feature uses npx madge without pinning a version, exposing users to arbitrary package execution or inconsistent analysis results. Since this skill is a developer utility expected to be run locally, any registry-resolved execution increases host compromise risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The scaffold workflow creates directories and writes several project files directly to disk, but there is no confirmation prompt or explicit warning that files and folders will be created. Although existence of the top-level directory is checked, the user is not otherwise informed of the write side effects beyond success messages after the fact.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

文件标题、描述和全部使用说明均固定为中文,未说明是否支持其他语言,也未给出用户可选择语言/locale 的方式。根据该规则,若技能在自然语言层面强制单一语言且没有用户选择或明确的区域性理由,应视为语言/locale 政策风险。

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/dev-tk.js:14