Skip to content

Commit d122c82

Browse files
committed
Fix path injection in shim generation, JSON escaping, and legacy tracker compat
- Escape runtime paths in bitlesson-selector shim using single-quoted strings to prevent command injection via paths containing shell metacharacters - JSON-escape runtime_root before template substitution in install-codex-hooks.sh to prevent JSON corruption from paths containing quotes or backslashes - Allow goal-tracker edits on legacy trackers that lack the IMMUTABLE SECTION header instead of blocking all writes
1 parent 2a0faf6 commit d122c82

File tree

3 files changed

+17
-8
lines changed

3 files changed

+17
-8
lines changed

hooks/lib/loop-common.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -888,7 +888,8 @@ goal_tracker_mutable_update_allowed() {
888888
current_immutable=$(extract_goal_tracker_immutable_from_file "$tracker_file" 2>/dev/null || true)
889889
updated_immutable=$(extract_goal_tracker_immutable_from_text "$updated_content" 2>/dev/null || true)
890890

891-
[[ -n "$current_immutable" ]] || return 1
891+
# Legacy trackers without IMMUTABLE SECTION: allow edits unconditionally.
892+
[[ -n "$current_immutable" ]] || return 0
892893
[[ "$current_immutable" == "$updated_immutable" ]]
893894
}
894895

scripts/install-codex-hooks.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,10 @@ template_file = pathlib.Path(sys.argv[2])
102102
runtime_root = sys.argv[3]
103103
104104
template_text = template_file.read_text(encoding="utf-8")
105-
template_text = template_text.replace("{{HUMANIZE_RUNTIME_ROOT}}", runtime_root)
105+
# JSON-escape the runtime root so metacharacters (quotes, backslashes) do not
106+
# corrupt the template before json.loads parses it.
107+
escaped_root = json.dumps(runtime_root)[1:-1] # strip outer quotes from dumps output
108+
template_text = template_text.replace("{{HUMANIZE_RUNTIME_ROOT}}", escaped_root)
106109
template = json.loads(template_text)
107110
108111
existing = {}

scripts/install-skill.sh

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -343,18 +343,23 @@ install_bitlesson_selector_shim() {
343343

344344
mkdir -p "$COMMAND_BIN_DIR"
345345

346-
cat > "$shim_path" <<EOF
346+
# Escape paths for safe embedding in the generated script.
347+
# Use single-quoted strings so shell metacharacters in paths are inert.
348+
_escaped_primary=$(printf '%s' "$primary_runtime_root" | sed "s/'/'\\\\''/g")
349+
350+
cat > "$shim_path" <<SHIM_EOF
347351
#!/usr/bin/env bash
348352
set -euo pipefail
349353
350354
candidate_paths=(
351-
"$primary_runtime_root/scripts/bitlesson-select.sh"
352-
EOF
355+
'${_escaped_primary}/scripts/bitlesson-select.sh'
356+
SHIM_EOF
353357

354358
if [[ -n "$secondary_runtime_root" ]]; then
355-
cat >> "$shim_path" <<EOF
356-
"$secondary_runtime_root/scripts/bitlesson-select.sh"
357-
EOF
359+
_escaped_secondary=$(printf '%s' "$secondary_runtime_root" | sed "s/'/'\\\\''/g")
360+
cat >> "$shim_path" <<SHIM_EOF
361+
'${_escaped_secondary}/scripts/bitlesson-select.sh'
362+
SHIM_EOF
358363
fi
359364

360365
cat >> "$shim_path" <<'EOF'

0 commit comments

Comments
 (0)