T09 · Insecure Skill Coding Practices
- Location
SKILL.md:518- Finding
Unrestricted Execution of Repository-Controlled Shell Commands
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This autonomous optimization skill is open about running commands and changing repositories, but its headless mode, credential exposure, and destructive rollback behavior need careful review before use.
Install only if you are comfortable with an agent that can edit project files, run project-supplied shell commands, create commits, and reset repository history. Use it first in an isolated clone, container, or disposable worktree with no secrets in the environment, no production kubeconfig or database credentials, and a reviewed improve.md. Avoid headless overnight runs until you have verified the exact scope, commands, backup branch, and recovery process.
SKILL.md:518Unrestricted Execution of Repository-Controlled Shell Commands
references/protocol.md:42Unsafe Destructive Git Rollback Using Unconditional Hard Reset
docs/index.html:634Remote JavaScript Dependencies Loaded Without Subresource Integrity
The README explicitly recommends headless execution with powerful tool permissions: bash, read, write, and edit. In the context of an autonomous optimization loop that can modify files, run commands, and iterate unattended, this creates a high-risk pathway for uncontrolled code execution, repository tampering, secrets exposure, or persistence of harmful changes if the agent behaves unexpectedly or the project contents are adversarial.
/autoimprove
claude -p "run /autoimprove on improve.md" --allowedTools bash,read,write,edit
## The `improve.md` format
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.
2. **Goal-aware threat modeling**: The optimization goal predicts what the agent will try, which predicts what it will break. Generate tests that guard against the failure modes of THAT specific goal:
**When goal = faster (lower latency, fewer allocations):**
The agent will skip work, take shortcuts, and remove safety checks.
- Unicode/multibyte input still works (fast paths assume ASCII)
- Empty, nil, zero-length inputs don't crash (nil checks removed for speed)
- Error messages are still correct and informative (error formatting skipped)
The workflow performs 'git reset --hard HEAD~1' automatically after failed experiments. Although intended for rollback, hard reset is a destructive operation; combined with a skill that auto-commits and runs in loops, a mistake in repository state handling, wrong working directory, or weak guardrails can irreversibly discard local work or amplify operational damage.
4. Run the test command (if Check.test is specified)
5. IF tests fail:
→ git reset --hard HEAD~1
→ Log as "test_failed"
→ consecutive_failures += 1
→ Print: "✗ Experiment {id}: {title} — tests failed"
This is another automatic 'git reset --hard HEAD~1' path triggered on guard failures. The repetition across multiple branches increases the chance of destructive rollback being exercised frequently during unattended runs, making accidental data loss or incorrect repository rollback more likely.
7.5. Check guard metrics (if Check.guard is specified):
→ Extract guard metric value from stdout
→ IF guard threshold violated (e.g., error_rate > 0.05):
→ git reset --hard HEAD~1
→ Log as "guard_failed"
→ consecutive_failures += 1
→ Print: "✗ Experiment {id}: {title} — guard violated: {guard_name} = {value}"
This rollback path hard-resets the repository when the score command errors or times out. Since the score command itself is arbitrary and domain-specific, errors may happen often; coupling arbitrary command execution with destructive history rewriting creates a substantial safety risk in autonomous mode.
8. DECIDE:
IF score command failed (non-zero exit, timeout):
→ git reset --hard HEAD~1
→ Log as "error"
→ consecutive_failures += 1
The default non-improvement path also executes 'git reset --hard HEAD~1', making destructive rollback part of normal operation rather than an exceptional path. In the broader skill context, where scope enforcement is only policy and commands are arbitrary, this elevates the danger because unattended experimentation can repeatedly mutate and then forcibly rewrite state.
→ Print: "≈ Experiment {id}: {title} — {score} (kept, equal score)"
ELSE:
→ git reset --hard HEAD~1
→ Log as "discarded"
→ consecutive_failures += 1
→ Print: "✗ Experiment {id}: {title} — {score} (no improvement)"
The skill explicitly states it runs arbitrary shell commands from improve.md and inherits ambient credentials such as AWS keys, DB credentials, kubeconfigs, and API tokens. Even though this is framed as a warning, it confirms the design permits command execution in a credential-rich environment, which can expose secrets or allow privileged actions if improve.md is malicious, mistaken, or compromised.
**Runtime requirements**: git is required. The check commands in your improve.md determine what else is needed (go, python, npm, docker, kubectl, psql, etc.). Verify these are installed before starting.
**Credentials**: The agent runs arbitrary shell commands from your improve.md. It inherits whatever credentials are available to the process (AWS keys, DB creds, kubeconfigs, API tokens). Run autoimprove with least-privilege credentials. Strip environment variables you don't want the agent to access.
**First run**: Always interactive. The readiness check (Step 1) confirms scope, reviews generated tests, and establishes a baseline before the loop starts. Don't run headless until you've verified one interactive run works correctly.
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.
<div class="reveal">
<div class="slides">
<!-- TITLE -->
<section class="title-slide" data-background="#000">
<h1>From <span class="red">autoresearch</span><br>to <span class="red">autoimprove</span></h1>
<p class="subtitle">Generalizing the agentic experiment loop</p>
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.
<p><span class="inline-code">exclude</span> prevents the agent from grading its own homework.</p>
</section>
<!-- THREE-LAYER CHECK -->
<section data-background="#000">
<h2>Three-layer check</h2>
<div class="red-bar"></div>
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.
<tr><th>Goal</th><th>Agent will try to...</th><th>Tests guard against...</th></tr>
</thead>
<tbody>
<tr><td>Faster</td><td>Skip work, remove checks</td><td>Edge cases, unicode, nil, concurrency</td></tr>
<tr><td>Smaller</td><td>Remove things, swap deps</td><td>Features still work, runtime deps present</td></tr>
<tr><td>More accurate</td><td>Overfit, leak data</td><td>Data leakage, reproducibility, valid outputs</td></tr>
<tr><td>Better RAG</td><td>Game retrieval, stuff context</td><td>Format consistency, hallucination, empty results</td></tr>
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.
query expansion, chain-of-thought generation.</code></pre>
</section>
<!-- EXAMPLE: AUTOML -->
<section data-background="#000">
<h2>Example: tabular ML</h2>
<div class="red-bar"></div>
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.
</table>
</section>
<!-- REAL WORLD: ROUND 2 -->
<section data-background="#000">
<h2>Real-world test: round 2</h2>
<div class="red-bar"></div>
Skill selects an external model or provider that may use a different account or billing plan than the operator expects. Undisclosed model switches can cause unexpected cost or quota consumption.
<div class="red-bar"></div>
<p>The skill runs in Claude Code. The protocol runs anywhere.</p>
<pre><code class="language-bash">/autoimprove # Claude Code (interactive)
claude -p "run /autoimprove on improve.md" # headless overnight
/autoimprove --export # generates program.md
codex -p "follow program.md" # any agent can follow it
gemini -p "follow program.md"</code></pre>
This section authorizes destructive repository operations such as repeated commits and hard resets during an autonomous loop, but provides no mandatory user warning, backup, or checkpointing beyond git history assumptions. That is risky because repositories may contain untracked work, nested repos, or unexpected states, and git reset --hard can irreversibly discard local changes.
The protocol directly instructs use of git reset --hard HEAD~1 after test failures, which is a destructive command that can wipe local modifications in the working tree. In an autonomous agent context, this is especially dangerous because the command is triggered programmatically and repeatedly, increasing the chance of unintended data loss.
3. **Commit**: `git add <changed files> && git commit -m "autoimprove: <short description>"`. Verify HEAD changed by comparing `git rev-parse HEAD` before and after. If HEAD didn't change, the commit failed — stop and report.
4. **Test**: If `Check.test` is specified, run it. If tests fail: `git reset --hard HEAD~1`, log as "test_failed", continue to next iteration.
5. **Evaluate**: Run the score command (`Check.run`). If it times out, kill it and treat as failure.
This instance again mandates git reset --hard HEAD~1 on guard failures, coupling an evaluation condition directly to a destructive repository reset. If guard extraction or evaluation logic is wrong, the agent could discard valid work automatically, causing silent loss of changes.
6. **Score**: Extract the score from stdout using the extraction method in `Check.score`.
7. **Guard**: If `Check.guard` is specified, extract the guard metric and check the threshold. If violated: `git reset --hard HEAD~1`, log as "guard_failed", continue.
8. **Decide**:
- If the score command failed (non-zero exit or timeout): `git reset --hard HEAD~1`, log as "error"
The protocol uses git reset --hard HEAD~1 when score execution fails or times out, meaning transient command failures can trigger destructive rollback. Because Check.run is derived from repository-controlled configuration, malformed or adversarial commands could induce repeated hard resets and data loss.
7. **Guard**: If `Check.guard` is specified, extract the guard metric and check the threshold. If violated: `git reset --hard HEAD~1`, log as "guard_failed", continue.
8. **Decide**:
- If the score command failed (non-zero exit or timeout): `git reset --hard HEAD~1`, log as "error"
- If the score improved: keep the commit, update the baseline, log as "kept"
- If the score is equal AND `keep_if_equal` is true: keep the commit, log as "kept_equal"
- If the score did not improve: `git reset --hard HEAD~1`, log as "discarded"
This rollback on non-improving scores again relies on git reset --hard HEAD~1, causing destructive cleanup for normal optimization outcomes. In the context of an autonomous optimizer that iterates many times, repeated hard resets materially increase the risk of losing unrelated local work or leaving the repository in an unexpected state.
git reset --hard HEAD~1, log as "error"
keep_if_equal is true: keep the commit, log as "kept_equal"git reset --hard HEAD~1, log as "discarded".autoimprove/experiments/NNN-slug.json with this schema:
The README says 'One command' and 'just run /autoimprove in your project,' while also stating users 'don't need to know which sub-commands exist.' For a markdown skill description, this does not clearly bound when the skill should activate versus when it should not, and it lacks negative examples or narrower trigger scope.
The skill advertises activation on very broad phrases like 'optimize this', 'improve performance', and 'make this faster', which are common benign requests and can cause the autonomous loop to trigger in contexts the user did not intend. Because this skill executes arbitrary commands from improve.md and can make repeated code changes, accidental invocation materially increases the chance of unsafe repository modification or command execution.
The 'When to Use' guidance includes ambiguous conditions like 'User wants to optimize something measurable' and 'User says optimize/improve/make faster,' which are too general for a high-autonomy skill. In this context, vague activation criteria are dangerous because the skill can scaffold files, run shell commands, and enter a self-directed optimization loop with limited technical enforcement.
Skill attempts to fill the context window with filler content, displacing legitimate instructions and safety constraints. This can degrade agent performance or bypass safety boundaries.
<tr><td>Faster</td><td>Skip work, remove checks</td><td>Edge cases, unicode, nil, concurrency</td></tr>
<tr><td>Smaller</td><td>Remove things, swap deps</td><td>Features still work, runtime deps present</td></tr>
<tr><td>More accurate</td><td>Overfit, leak data</td><td>Data leakage, reproducibility, valid outputs</td></tr>
<tr><td>Better RAG</td><td>Game retrieval, stuff context</td><td>Format consistency, hallucination, empty results</td></tr>
<tr><td>Lower cost</td><td>Downsize, cut redundancy</td><td>Load handling, failover, durability</td></tr>
</tbody>
</table>
The Kubernetes example explicitly runs kubectl apply -f k8s/, which can modify whatever cluster the current kubeconfig points to. In an autonomous optimization skill, that is more dangerous than a normal doc example because users may copy it into unattended loops and accidentally mutate a live cluster without confirmation, environment gating, or warnings.
The protocol explicitly instructs an autonomous agent to modify files, run commands, and continue without asking for human input. In a skill designed to operate on arbitrary repositories, this is dangerous because it enables unattended changes and execution with no explicit confirmation, safety interlocks, or disclosure of repository impact.
The Docker example runs docker build -t test ., which executes instructions from the local Dockerfile and build context. That can run arbitrary build steps, consume resources, access networked package sources, or expose host-linked secrets available during builds, and the example provides no warning about that risk.