T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/package_skill.py:31
- Finding
- Packaging Proceeds Without Mandatory Sensitive-File Exclusions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/package_skill.py`, lines 31-41 and 196-216 **Vulnerability Type**: Sensitive-file disclosure through fail-open archive configuration **Risk Level**: High ### Vulnerable Code ```python def _load_ignore_patterns(skill_root: Path) -> list[str]: ignore_file = skill_root / ".clawhubignore" if not ignore_file.exists(): return [] patterns: list[str] = [] for raw_line in ignore_file.read_text(encoding="utf-8").splitlines(): line = raw_line.strip() if not line or line.startswith("#"): continue patterns.append(line) return patterns ``` ```python ignore_patterns = _load_ignore_patterns(skill_path) # Create the .skill file (zip format) try: with zipfile.ZipFile(skill_filename, "w", zipfile.ZIP_DEFLATED) as zipf: # Walk through the skill directory for file_path in skill_path.rglob("*"): # Security: never follow or package symlinks. if file_path.is_symlink(): print(f"[WARN] Skipping symlink: {file_path}") continue if _should_ignore(file_path, skill_path, ignore_patterns): continue if file_path.is_file(): resolved_file = file_path.resolve() if not _is_within(resolved_file, skill_path): print(f"[ERROR] File escapes skill root: {file_path}") return None ``` ### Technical Analysis The packager treats a missing `.clawhubignore` file as an empty exclusion list. It then recursively processes every regular, non-symlink file beneath the Skill root. The preceding validation only validates the structure and frontmatter of `SKILL.md`; it does not scan the package for credentials, environment files, private keys, tokens, logs, session data, or other sensitive artifacts. Although `init_skill.py` creates a default `.clawhubignore`, `package_skill.py` can package existing ...[truncated 1801 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Make `.clawhubignore` mandatory and abort packaging when it is absent. 2. Enforce a non-overridable internal denylist in addition to user-defined patterns. At minimum, exclude: - `.env*` - `.git/` and other VCS metadata - private-key and credential filenames - `.clawhub/` - session, diagnostics, profile, cache, coverage, log, and temporary directories - generated `.skill` archives 3. Scan the final file list for sensitive names and probable secret material before writing the archive. 4. Display the complete archive manifest and require explicit confirmation when suspicious files are detected. 5. Validate the finished archive rather than relying only on source-directory checks. 6. Add regression tests confirming that packaging fails when `.clawhubignore` is absent and that mandatory exclusions cannot be disabled by an incomplete ignore file. 7. Delete any partially created archive when packaging aborts because a prohibited file is detected. ]]>
