Back to skill

Security audit

Improvement Orchestrator

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed automation tool for improving other skills, but it can automatically modify skill files and has loose validation and scoping controls that warrant review before installation.

Install only if you intentionally want an automation tool that can modify skill files. Run it in a version-controlled or disposable workspace, use explicit target and state directories, review generated diffs and state artifacts, and do not rely on evaluator failure to block execution until that fail-open behavior is fixed.

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
scripts/orchestrate.py:188
Finding

Evaluator Failure Allows Candidate Execution Without Requested Validation

Content
View full analysis

Vulnerability Details

File Location: scripts/orchestrate.py:188-197 and scripts/orchestrate.py:397-421
Vulnerability Type: Fail-open validation and safety-control bypass
Risk Level: High

Vulnerable Code

python
try:
    artifact_path = _run_script(cmd, "evaluator")
    result = read_json(Path(artifact_path))
    verdict = result.get("verdict", "skipped")
    if verdict == "skipped":
        print("  Evaluator: skipped (no task suite)")
        return None
    print(f"  Evaluator: {verdict} (pass_rate={result.get('evaluation_results', {}).get('execution_pass_rate', 'N/A')})")
    return result
except RuntimeError as exc:
    print(f"  Evaluator: error ({exc}), continuing without evaluation")
    return None

The returned None value permits the pipeline to continue into execution:

python
eval_result = None if skip_eval else run_evaluator(
    ranking_artifact_path,
    candidate_id,
    state_root,
    task_suite=task_suite,
    eval_threshold=cat_threshold,
    mock=eval_mock,
)
eval_artifact_path: str | None = None
if eval_result:
    eval_artifact_path = eval_result.get("truth_anchor")
if eval_result and eval_result.get("verdict") == "fail":
    # Evaluation failed — treat as revert and retry
    trace = {
        "type": "evaluation_failure_trace",
        "candidate_id": candidate_id,
        "evaluation_results": eval_result.get("evaluation_results", {}),
        "timestamp": utc_now_iso(),
    }
    trace_dir = Path(state_root) / "traces"
    trace_dir.mkdir(parents=True, exist_ok=True)
    trace_path = trace_dir / f"eval-trace-{candidate_id}.json"
    write_json(trace_path, trace)
    active_sources.append(str(trace_path))
    print(f"  Evaluation failed, retrying ({attempt}/{max_retries})")
    continue

# 4. EXECUTE
execution_artifact = run_executor(
    ranking_artifact_path,
    candidate_id,
    state_root,
)

Technical Analysis

When evaluation is required, an explicit fail verdict prevents execution an ...[truncated 2099 chars]

Remediation
View remediation

Remediation Suggestions

  1. Fail closed when evaluation was requested but cannot complete:

    • Stop the pipeline;
    • Mark the candidate as rejected;
    • Or create a failure trace and retry without executing the candidate.
  2. Return a structured evaluator status instead of overloading None, for example:

python
{
    "status": "error",
    "verdict": "blocked",
    "reason": str(exc),
}
  1. Track whether evaluation is mandatory:
python
evaluation_required = bool(task_suite) and not skip_eval

If evaluation_required is true, require all of the following before execution:

  • A valid evaluation artifact;
  • A recognized verdict;
  • A passing verdict;
  • A valid truth_anchor.
  1. Make the gate reject missing evaluator evidence whenever evaluation was required. This provides defense in depth if the orchestration layer is bypassed.

  2. Add tests covering:

    • Evaluator timeout;
    • Evaluator non-zero exit;
    • Malformed evaluator artifact;
    • Missing truth_anchor;
    • Confirmation that the executor is not called after any mandatory-evaluation error.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/orchestrate.py:257
Finding

Unvalidated Artifact Identifiers Permit Path Traversal in Trace Writes

Content
View full analysis

Vulnerability Details

File Location: scripts/orchestrate.py:257-261 and scripts/orchestrate.py:372-384, 411-414
Vulnerability Type: Path traversal and arbitrary file write
Risk Level: Medium

Vulnerable Code

A gate-provided run identifier is embedded directly into a filename:

python
run_id = receipt.get("run_id", "unknown")
trace_dir = Path(state_root) / "traces"
trace_path = trace_dir / f"trace-{run_id}.json"
write_json(trace_path, trace)
return str(trace_path)

A ranking-provided candidate identifier is trusted and later embedded directly into another filename:

python
best = find_best_accepted(ranking_artifact)
if not best:
    final_decision = "no_accepted_candidates"
    print(f"  No accepted candidates in attempt {attempt}/{max_retries}")
    break

candidate_id = best["id"]
python
trace_dir = Path(state_root) / "traces"
trace_dir.mkdir(parents=True, exist_ok=True)
trace_path = trace_dir / f"eval-trace-{candidate_id}.json"
write_json(trace_path, trace)
active_sources.append(str(trace_path))

Technical Analysis

The orchestrator treats run_id and candidate_id from subprocess-generated JSON artifacts as safe filename components. It does not apply:

  • A character allowlist;
  • Path-separator rejection;
  • .. traversal rejection;
  • Basename normalization;
  • A resolved-path containment check.

A malicious identifier can contain traversal components. When joined with trace_dir, these components may cause the resulting path to resolve outside the intended trace directory.

Although the fixed trace- or eval-trace- prefix limits some simple payload forms, crafted identifiers containing separators and parent-directory components can still alter the destination path. The final .json suffix does not prevent overwriting or creating JSON-named files elsewhere.

Exploitation requires control over, or compromise of, a pipeline stage that produces the ranking or gate artifact. These artifacts cross a subproces ...[truncated 1493 chars]

Remediation
View remediation

Remediation Suggestions

  1. Validate all artifact identifiers before using them as filename components. Use a strict allowlist such as:
python
import re

SAFE_ID = re.compile(r"^[A-Za-z0-9._-]+$")

def validate_identifier(value: str, field: str) -> str:
    if not isinstance(value, str) or not SAFE_ID.fullmatch(value):
        raise RuntimeError(f"Invalid {field}")
    return value
  1. Reject identifiers containing:
  • / or \;
  • ..;
  • Null bytes;
  • Control characters;
  • Absolute-path syntax;
  • Platform-specific path separators.
  1. Resolve and verify the final path remains inside the trace directory:
python
trace_root = (Path(state_root) / "traces").resolve()
trace_path = (trace_root / filename).resolve()

if trace_root not in trace_path.parents:
    raise RuntimeError("Trace path escapes the trace directory")
  1. Prefer orchestrator-generated UUIDs for filenames. Store external candidate_id and run_id only as JSON fields inside the artifact rather than using them in paths.

  2. Apply the same validation to every artifact-derived path or identifier, including truth_anchor values returned through subprocess standard output.

  3. Add tests using identifiers containing parent-directory components, absolute paths, backslashes, control characters, and oversized values. Confirm that no file is written outside the trace directory.

Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (17)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill explicitly orchestrates subprocess execution and applies changes to target skills, implying file read/write and shell-like execution capabilities, yet it declares no tool scope or permissions. In an orchestration skill that can modify files and run a full improvement pipeline, missing capability boundaries materially increases the chance of over-privileged or unintended execution.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger phrase "improve skill" is broad enough to match routine user requests and could invoke this skill in contexts where the user did not intend a full end-to-end pipeline. Because this skill can execute changes and retries automatically, accidental activation is more dangerous than it would be for a read-only or advisory skill.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The phrase "orchestrate improvement" is ambiguous and does not clearly signal that the skill may run generator, evaluator, executor, and gate stages with retries. This ambiguity can cause unintended routing into a powerful orchestration workflow rather than a narrower analysis-only skill.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The Chinese trigger "一键优化" is extremely broad and likely to match many ordinary optimization requests unrelated to this specific pipeline. In this skill's context, that broad matching is risky because activation may lead to actual file modifications and subprocess execution rather than simple advice.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This markdown file explicitly instructs that SKILL.md may be read/edited/written and provides a git checkout rollback command, which indicates the skill can modify user-managed files. Under the markdown variant of SQP-2, descriptions should warn when behavior can affect user data or system integrity, but no warning or caution is provided here.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The markdown states that config.yaml will be read/edited/written and rules will be atomically replaced, which can directly alter automation behavior and persisted configuration. The file does not include any caution about reviewing changes, protecting existing configs, or potential impact before these writes occur.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

This section says selectors.json will be read/edited/written and flows will receive versioned updates, which can materially change browser automation behavior. The markdown lacks a user warning about these changes, their operational impact, or the need to review diffs before deployment.

Content

No source excerpt is available for this finding.

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · references/end-to-end-demo.md (reported line 83)May include surrounding context.

md
{
      "id": "cand-001",
      "title": "添加行业特定模板章节",
      "target_path": "$OPENCLAW_ROOT/workspace/skills/newsletter-creation-curation/SKILL.md",
      "category": "reference",
      "rationale": "用户反馈缺少行业模板,补充后可提升技能实用性",
      "risk_level": "low",

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · references/end-to-end-demo.md (reported line 106)May include surrounding context.

md
{
      "id": "cand-001",
      "title": "添加行业特定模板章节",
      "target_path": "$OPENCLAW_ROOT/workspace/skills/newsletter-creation-curation/SKILL.md",
      "category": "reference",
      "rationale": "用户反馈缺少行业模板,补充后可提升技能实用性",
      "risk_level": "low",

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · references/end-to-end-demo.md (reported line 245)May include surrounding context.

md
{
      "id": "cand-001",
      "title": "添加行业特定模板章节",
      "target_path": "$OPENCLAW_ROOT/workspace/skills/newsletter-creation-curation/SKILL.md",
      "category": "reference",
      "rationale": "用户反馈缺少行业模板,补充后可提升技能实用性",
      "risk_level": "low",

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · references/end-to-end-demo.md (reported line 258)May include surrounding context.

md
{
      "id": "cand-001",
      "title": "添加行业特定模板章节",
      "target_path": "$OPENCLAW_ROOT/workspace/skills/newsletter-creation-curation/SKILL.md",
      "category": "reference",
      "rationale": "用户反馈缺少行业模板,补充后可提升技能实用性",
      "risk_level": "low",

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This markdown file is written entirely in Chinese, including headings, instructions, and operational notes, with no indication that language selection is optional or that the skill is intentionally limited to a Chinese-speaking audience. Under the policy rule for natural-language violations, forcing a specific language without opt-in or documented justification is a reportable locale/language constraint.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/orchestrate.py (reported line 79)May include surrounding context.

python
Raises RuntimeError on non-zero exit or timeout.
    """
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
    except subprocess.TimeoutExpired:
        raise RuntimeError(f"{label} timed out after {timeout}s")
    if result.returncode != 0:

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The file presents core usage guidance in Chinese while other sections remain in English, effectively imposing a mixed language experience without stating a locale policy or offering user opt-in. This can violate language-choice expectations where skills should not force a specific language absent justification.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This file presents the skill’s end-to-end behavior as a concrete lane workflow of Proposer → Critic → Executor → Gate, with examples only for candidate generation, ranking, execution, and gate decisions. That is narrower than the manifest description, which explicitly claims one-click orchestration of generation, scoring, evaluation, execution, and gating, plus automatic retry and batch improvement; those additional behaviors are not demonstrated or documented in this skill file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

This markdown file uses Chinese throughout, including headings and operational instructions, but does not indicate that the skill is region-specific or that users can opt into this language. Under the language/locale policy, forcing a specific language without user choice is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

This code writes structured failure trace data to disk via write_json, and similar writes also occur later for baseline feedback and pipeline summary. While the file contains developer-facing docstrings and comments, there is no runtime user-facing notice or confirmation that artifacts containing execution details and diffs will be persisted under the state directory.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.