zeroclaw-labs/zeroclaw · error · anyhow::Error
Skill security audit failed: {}
Error message
Skill security audit failed: {} What it means
enforce_skill_security_audit runs audit_skill_directory_with_options over the skill directory and bails when the report has findings. Findings include: no SKILL.md (or deprecated manifest) at the skill root, symlinks anywhere inside, script-like files when allow_scripts is false (the default), markdown/toml files over 512 KiB, and forbidden-content findings in markdown/manifests. The message embeds report.summary(), so each finding names a file and a reason.
Source
Thrown at crates/zeroclaw-runtime/src/skills/mod.rs:2011
_ => anyhow::bail!(
"Unable to determine installed skill directory after clone (multiple new directories found)"
),
}
}
fn enforce_skill_security_audit(
skill_path: &Path,
allow_scripts: bool,
) -> Result<audit::SkillAuditReport> {
let report = audit::audit_skill_directory_with_options(
skill_path,
audit::SkillAuditOptions { allow_scripts },
)?;
if report.is_clean() {
return Ok(report);
}
anyhow::bail!("Skill security audit failed: {}", report.summary());
}
fn remove_git_metadata(skill_path: &Path) -> Result<()> {
let git_dir = skill_path.join(".git");
if git_dir.exists() {
std::fs::remove_dir_all(&git_dir)
.with_context(|| format!("failed to remove {}", git_dir.display().to_string()))?;
}
Ok(())
}
fn copy_dir_recursive_secure(src: &Path, dest: &Path) -> Result<()> {
let src_meta = std::fs::symlink_metadata(src)
.with_context(|| format!("failed to read metadata for {}", src.display().to_string()))?;
if src_meta.file_type().is_symlink() {
anyhow::bail!(
"Refusing to copy symlinked skill source path: {}",
src.display()View on GitHub (pinned to 88bb9c8533)
Solutions
- Read the findings in the message — each names a relative path and the reason it was flagged
- If the finding is 'script-like files are blocked by skill security policy' and you trust the skill, set skills.allow_scripts = true in your zeroclaw config and reinstall
- Add a SKILL.md at the skill root and remove symlinks (replace with real files)
- Shrink oversized markdown/toml below the 512 KiB static-audit limit
Example fix
# before: install of a script-carrying skill fails zeroclaw skills install ./my-skill # audit failed: scripts/setup.sh blocked # after: trust the skill explicitly # zeroclaw config: # [skills] # allow_scripts = true zeroclaw skills install ./my-skill
Defensive patterns
Strategy: validation
Validate before calling
// Pre-audit with the library's public API before installing:
use zeroclaw_runtime::skills::audit::{audit_skill_directory_with_options, SkillAuditOptions};
let report = audit_skill_directory_with_options(
std::path::Path::new(source),
SkillAuditOptions { allow_scripts },
)?;
if !report.is_clean() {
eprintln!("would be rejected: {}", report.summary());
// fix findings (remove scripts/symlinks, add SKILL.md) or set allow_scripts
} Try / catch
match install_local_skill_source(source, &skills_path, allow_scripts) {
Err(e) if e.to_string().starts_with("Skill security audit failed") => {
// parse the ';'-joined findings; scripts_blocked => hint allow_scripts=true
}
r => r,
} Prevention
- Pre-audit skill directories with audit_skill_directory_with_options before install
- Keep a SKILL.md at every skill root and avoid symlinks inside skills
- Only enable skills.allow_scripts for skills you have reviewed
When it happens
Trigger: install_local_skill_source or install_git_skill_source on a skill that ships shell/python helper scripts while config skills.allow_scripts is false; skill root lacking SKILL.md; any symlink inside the skill tree; SKILL.md larger than 512 KiB.
Common situations: Installing tool-style skills that carry .sh/.py helpers; copying a skill folder without its SKILL.md; vendored repos that symlink shared assets; generated skills with huge markdown.
Related errors
- Refusing to copy symlinked skill source path: {}
- Refusing to copy symlink within skill source: {}
- skill '{$skill}' in {$url} is a symlink; catalog skills must
- skill '{$skill}' in {$url} resolves outside the cloned catal
- cli-skills-audit-failed
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/944186d3f5eea45a.
Report an issue: GitHub.