T09 · Insecure Skill Coding Practices
- Location
scripts/sentinel.sh:81- Finding
Git Snapshot Commits Unrelated Staged Content and Executes Repository Hooks
- Content
View full analysis
/dev/null || true if git diff --cached --quiet; then log "No git snapshot created (no staged changes)" else git commit -m "config-sentinel: pre-change snapshot $ts" >/dev/null 2>&1 || true if git rev-parse HEAD >/dev/null 2>&1; then git rev-parse HEAD > "$LAST_GOOD_FILE" log "Git snapshot committed: $(cat "$LAST_GOOD_FILE")" fi fi ``` ### Technical Analysis The script stages the configuration file and then runs a normal `git commit`. A Git commit records the entire current index, not only the file just passed to `git add`. Consequently, files that were already staged before the skill ran will also be included in the snapshot commit. A normal `git commit` also invokes applicable repository hooks, including `pre-commit`, `prepare-commit-msg`, `commit-msg`, and `post-commit`. These hooks are executable code controlled by the local repository. If the configuration directory is an untrusted or compromised Git repository, invoking the snapshot operation can therefore execute attacker-controlled commands with the privileges of the user running the skill. The commands suppress errors through redirection and `|| true`. This can conceal staging or commit failures and may cause the script to treat an existing `HEAD` revision as the intended recovery point even if the new snapshot commit failed. ### Attack Path 1. An attacker or compromised local process places an executable malicious hook in the configuration repository, or causes sensitive/unrelated files to be staged in its Git index. 2. The user approves an OpenClaw configuration change. 3. The documented workflow invokes `scripts/sentinel.sh pre-change`. 4. The script stages the configuration file and calls `git commit`. 5. Git executes the repository hooks with ...[truncated 957 chars]- Remediation
View remediation
/dev/null || true` from security-critical Git operations. Check each command's exit status and abort with a clear error if staging or committing fails. 7. Write `LAST_GOOD_FILE` only after verifying that a new commit was successfully created and contains the expected configuration path. 8. Where practical, avoid operating on repositories whose ownership or trust status cannot be established. ]]>
