T09 · Insecure Skill Coding Practices
Warning
- Location
- bin/claw-lint.sh:343
- Finding
- Documented SHA256 integrity inventory is not generated in full or JSON modes## Vulnerability Details **File Location**: `bin/claw-lint.sh:343-390` **Vulnerability Type**: Integrity-monitoring implementation failure **Risk Level**: Medium ### Vulnerable Code ```bash run_text_full() { # Simple full mode: per-skill header + inventory hashes (can be large). for name in "${SKILL_NAMES[@]}"; do local dir="${SKILL_DIR_BY_NAME[$name]}" echo "== $name ==" echo "path: $dir" echo "(use --format json --full for structured inventory)" echo done } run_json() { need_bin python3 tmp="$(mktemp)" for n in "${SKILL_NAMES[@]}"; do audit_one_text_summary_tsv "$n" "${SKILL_DIR_BY_NAME[$n]}" >>"$tmp" done python3 - "$tmp" <<'PY' import sys, json tmp_path = sys.argv[1] skills = [] with open(tmp_path, 'r', encoding='utf-8', errors='replace') as f: for line in f: line = line.rstrip("\n") if not line: continue score, name, flags, files_s, bytes_s = line.split("\t") skills.append({ "name": name, "risk_score": int(score), "flags": [] if flags == "(none)" else flags.split(","), "summary": {"files": int(files_s), "bytes": int(bytes_s)}, }) print(json.dumps({"skills": skills}, indent=2)) PY rm -f "$tmp" } main() { if [[ "$FORMAT" == "json" ]]; then run_json exit 0 fi if [[ "$MODE" == "summary" ]]; then run_text_summary else run_text_full fi } ``` ### Technical Analysis The skill documentation states that `--full` produces a SHA256 inventory suitable for integrity monitoring and that `--full --format json` provides a structured inventory. The implementation does not fulfill either guarantee: - `run_text_full` prints only each skill's name and path. It does not enumerate files or calculate hashes. - `run_json` always invokes `audit_one_text_summary_tsv`, which only produce ...[truncated 2244 chars]
- Remediation
- ## Remediation Suggestions 1. Connect full JSON mode to the existing inventory implementation: - Pass `MODE` into the JSON output path. - Invoke `emit_json_records 1` when both JSON and full modes are selected. - Convert the generated records into documented JSON containing file paths, sizes, modes, SHA256 values, skipped-hash status, and symlink targets. 2. Implement the documented text inventory: - Enumerate every non-ignored regular file. - Print its relative path, size, permissions, and SHA256 digest. - Clearly mark files skipped because they exceed `MAX_BYTES`. - Report symbolic links separately without following them outside the skill root. 3. Make incomplete baselines explicit: - Return a nonzero status when required hashing tools fail. - Include an `inventory_complete` field in JSON. - Report counts of hashed and skipped files. - Warn prominently when any file is omitted from hashing. 4. Add automated regression tests that verify: - `--full` includes a digest for each eligible file. - `--full --format json` includes structured file records. - Modifying file contents changes the reported SHA256 digest. - Summary mode does not claim to provide an integrity inventory. - Oversized files and symlinks are represented accurately. 5. Until the implementation is corrected, revise `SKILL.md` so it does not claim that the current `--full` workflow creates a usable SHA256 integrity baseline.
