T09 · Insecure Skill Coding Practices
- Location
scripts/self_improve.py:552- Finding
Arbitrary Code Execution Through Automatic Execution of Target Test Suites
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This appears to be a real skill-improvement tool, but it can modify repositories, run target test code, send SKILL.md content to an external Claude CLI, and create git commits without clear opt-in.
Install or run this only on a disposable copy of skills you trust. Do not use it on private or third-party skill directories unless you run in a sandbox with no sensitive environment variables and no network. Use --mock to avoid the Claude CLI path, inspect diffs before keeping changes, and do not assume the documented evaluation command is read-only.
scripts/self_improve.py:552Arbitrary Code Execution Through Automatic Execution of Target Test Suites
scripts/self_improve.py:88Target Skill Content Is Sent to an External LLM CLI Without Explicit Consent
scripts/self_improve.py:1126Accepted Improvements Automatically Stage Files and Create Git Commits
Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.
声明描述的是一个较全面的 skill 评估/自改进能力,包含质量评分、结构优化、扣分解释以及特定评估方法论。实际代码仅完成其中一小部分:从已有 JSON 报告读取历史数据,做均值对比式趋势判断,输出建议和可视化。因此,虽然“追踪评估分数变化趋势”这一点与代码相符,但其余核心宣称能力均未在该代码中体现,且代码的主要目的明显偏向历史趋势报告生成,而不是完整的质量评分与自动优化。未见越权资源访问,主要问题是声明能力显著大于实际行为。
The tool executes arbitrary pytest suites under the target skill directory, giving analyzed content a path to run code on the host. Given the skill's stated purpose of scoring and self-improvement, this is an unjustified and dangerous capability escalation that can be abused by malicious test files.
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.
(skill / "SKILL.md").write_text("original\n", encoding="utf-8")
backup = backup_skill(skill)
# Modify skill
(skill / "SKILL.md").write_text("modified\n", encoding="utf-8")
# Revert
revert_to_backup(skill, backup)
The skill advertises CLI commands that read/write files and invoke shell-based Python scripts, but it declares no explicit tool scope such as permissions or allowed-tools. This creates an authorization gap: an agent may infer broad file and shell access from the instructions and execute them without a least-privilege boundary, increasing the risk of unintended filesystem modification or command execution.
This manifest/markdown file defines activation triggers, and "self-improve" is a generic phrase that could naturally appear in many unrelated conversations. Although the surrounding description narrows the skill's purpose, the trigger itself lacks domain-specific constraints or negative examples, increasing the risk of unintended invocation.
The phrase means "quality scoring" and is broad enough to apply to many contexts beyond evaluating AI skill files. Because the trigger list does not constrain it to skills or this tool's workflow, it may cause accidental activation.
This phrase roughly means "where were points deducted," which is common conversational language and not uniquely tied to this skill. Without explicit scope limits or negative examples, it risks colliding with ordinary feedback or grading discussions.
"Automatic optimization" is a general phrase that could refer to many tasks unrelated to improving SKILL.md quality. The trigger list would be safer if it tied optimization explicitly to skill evaluation or self-improvement of the skill file.
The implementation invokes an external LLM CLI to evaluate SKILL.md content, which introduces undisclosed third-party processing and possible data leakage beyond local self-improvement. Because the skill is advertised mainly as evaluation/optimization, users may not expect contents of their skills to be transmitted outside the machine.
The subprocess call sends skill content to an external LLM without explicit user disclosure, which can expose proprietary prompts, internal procedures, or embedded secrets. This is especially risky because the target skill content is treated as analysis input, and users may assume evaluation remains local.
This subprocess invocation calls an external claude CLI and sends up to 8000 characters of SKILL.md content to it. Even though shell injection is avoided by passing an argument list, it still expands the skill's trust boundary by exfiltrating repository content to an external model/process without explicit consent, which is risky for private or sensitive skills.
)
try:
result = subprocess.run(
["claude", "-p", "--output-format", "json"],
input=prompt,
capture_output=True,
Running pytest against a target skill directory executes Python test code from that directory, which may be attacker-controlled if the evaluated skill is untrusted. In this context, a quality-evaluation tool is effectively granting arbitrary code execution during analysis, which can lead to local compromise, secret access, file tampering, or persistence.
# Base score from tests (0.0-1.0)
if has_tests:
try:
result = subprocess.run(
[sys.executable, "-m", "pytest",
str(skill_path / "tests"), "-q", "--tb=no"],
capture_output=True, text=True, timeout=30,
The implementation performs direct file mutation, backup/restore, reference extraction, autogenerated tests, and git operations, which goes beyond passive evaluation and guidance. This broad write capability can alter repositories in unexpected ways, damage user work, or create supply-chain risks if run against sensitive projects without clear consent.
The _apply_coverage_improvement docstring explicitly states the system does not auto-create tests, README, or scripts, framing those artifacts as author-intent-only. Elsewhere, _apply_reliability_improvement does auto-generate tests/test_smoke.py, which contradicts that documented intent at the module behavior level.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def commit_change(skill_path: Path, message: str) -> None:
"""Attempt a git commit (best-effort, non-fatal)."""
try:
subprocess.run(
["git", "add", "SKILL.md", "references/", "scripts/", "tests/"],
cwd=str(skill_path), capture_output=True, timeout=10,
)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
["git", "add", "SKILL.md", "references/", "scripts/", "tests/"],
cwd=str(skill_path), capture_output=True, timeout=10,
)
subprocess.run(
["git", "commit", "-m", message],
cwd=str(skill_path), capture_output=True, timeout=10,
)
The main loop automatically applies changes, reverts, writes memory snapshots, and may commit results without any user-facing confirmation. In a developer tool operating on repositories, silent mutation materially increases the risk of unintended file changes, destructive edits, and trust-boundary violations.
This Python file contains user-facing natural-language strings exclusively in Chinese, including the module description, CLI argument descriptions, warnings, and status messages. The stated policy forbids forcing a specific language without user opt-in, and the file does not provide any language selection mechanism or justification for a Chinese-only locale.
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.
"### 禁止行为\n- ❌ Skip evaluation\n- ❌ Ignore failures\n\n"
"### 正确做法\n- ✅ Run full pipeline\n- ✅ Check all dims\n\n"
"MUST run evaluation before reporting.\n"
"即使 scores look good, NEVER skip verification.\n\n"
"## Output Artifacts\n\n| Request | Deliverable |\n|---------|------------|\n"
"| Run tests | JSON report |\n\n"
"## Related Skills\n\n- **benchmark-store**: For frozen benchmarks\n",
No suspicious patterns detected.