@ictechgy/context-guard 0.4.16 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,40 @@
1
1
  #!/usr/bin/env bash
2
2
  set -euo pipefail
3
3
 
4
+ # This script is also callable directly, so do not let workspace-controlled
5
+ # command lookup or Python startup hooks select its runtime dependencies.
6
+ PATH=/usr/bin:/bin
7
+ export PATH
8
+ unset BASH_ENV ENV CDPATH PYTHONHOME PYTHONPATH PYTHONSTARTUP
9
+
10
+ approved_python=''
11
+ statusline_args=()
12
+ while (( $# > 0 )); do
13
+ case "$1" in
14
+ --approved-python)
15
+ if (( $# < 2 )); then
16
+ printf '[runtime-error] missing approved Python path\n'
17
+ exit 0
18
+ fi
19
+ approved_python=$2
20
+ shift 2
21
+ ;;
22
+ *)
23
+ statusline_args+=("$1")
24
+ shift
25
+ ;;
26
+ esac
27
+ done
28
+
4
29
  if [[ -t 0 ]]; then
5
30
  echo "usage: pass Claude Code statusline JSON on stdin"
6
31
  exit 0
7
32
  fi
8
33
 
9
- if ! command -v python3 >/dev/null 2>&1; then
34
+ if [[ -z "$approved_python" ]]; then
35
+ approved_python=$(command -v python3 2>/dev/null || true)
36
+ fi
37
+ if [[ "$approved_python" != /* || ! -f "$approved_python" || -L "$approved_python" || ! -x "$approved_python" ]]; then
10
38
  echo "[needs-python3] install python3 for Claude token statusline"
11
39
  exit 0
12
40
  fi
@@ -643,4 +671,7 @@ except BrokenPipeError:
643
671
  raise SystemExit(0)
644
672
  PYEOF
645
673
 
646
- exec python3 -I -c "$CONTEXT_GUARD_STATUSLINE_PY" "$@"
674
+ if (( ${#statusline_args[@]} > 0 )); then
675
+ exec "$approved_python" -I -c "$CONTEXT_GUARD_STATUSLINE_PY" "${statusline_args[@]}"
676
+ fi
677
+ exec "$approved_python" -I -c "$CONTEXT_GUARD_STATUSLINE_PY"
@@ -14,17 +14,54 @@
14
14
  # 입력: stdin 으로 Claude Code 가 넘기는 statusline JSON 한 줄.
15
15
  # 출력: stdout 한 줄.
16
16
  #
17
- # 환경변수(선택, 테스트/커스텀 설치용):
18
- # OMC_HUD_SCRIPT OMC HUD 스크립트 경로 (기본 $HOME/.claude/hud/omc-hud.mjs)
19
- # CONTEXT_GUARD_STATUSLINE_BIN context-guard-statusline 바이너리 경로
20
- # (legacy: CLAUDE_TOKEN_STATUSLINE_BIN)
21
- # (미지정 시 자기 옆 디렉토리만 사용; PATH 탐색 안 함)
17
+ # 외부 HUD/runtime 연동은 ambient 환경변수가 아니라 setup이 고정한 절대 경로
18
+ # 옵션으로만 허용한다. 미지정 자기 옆 ContextGuard statusline만 사용한다.
22
19
  set -u
23
20
 
24
- if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
25
- printf 'ContextGuard helper: context-guard-statusline-merged\n'
26
- exit 0
27
- fi
21
+ PATH=/usr/bin:/bin
22
+ export PATH
23
+ unset BASH_ENV ENV CDPATH PYTHONHOME PYTHONPATH PYTHONSTARTUP
24
+ unset OMC_HUD_SCRIPT CONTEXT_GUARD_STATUSLINE_BIN CLAUDE_TOKEN_STATUSLINE_BIN
25
+
26
+ approved_bash=''
27
+ approved_python=''
28
+ approved_token_statusline=''
29
+ approved_node=''
30
+ approved_omc_script=''
31
+ while (( $# > 0 )); do
32
+ case "$1" in
33
+ --help|-h)
34
+ printf 'ContextGuard helper: context-guard-statusline-merged\n'
35
+ exit 0
36
+ ;;
37
+ --approved-bash|--approved-python|--approved-token-statusline|--approved-node|--approved-omc-script)
38
+ if (( $# < 2 )); then
39
+ printf '[runtime-error] missing approved runtime path\n'
40
+ exit 0
41
+ fi
42
+ case "$1" in
43
+ --approved-bash) approved_bash=$2 ;;
44
+ --approved-python) approved_python=$2 ;;
45
+ --approved-token-statusline) approved_token_statusline=$2 ;;
46
+ --approved-node) approved_node=$2 ;;
47
+ --approved-omc-script) approved_omc_script=$2 ;;
48
+ esac
49
+ shift 2
50
+ ;;
51
+ *)
52
+ printf '[runtime-error] unsupported statusline option\n'
53
+ exit 0
54
+ ;;
55
+ esac
56
+ done
57
+
58
+ approved_regular_file() {
59
+ [[ "$1" = /* && -f "$1" && ! -L "$1" ]]
60
+ }
61
+
62
+ approved_executable_file() {
63
+ approved_regular_file "$1" && [[ -x "$1" ]]
64
+ }
28
65
 
29
66
  statusline_input_tmp=''
30
67
 
@@ -81,8 +118,8 @@ read_bounded_statusline_input() {
81
118
  read_bounded_statusline_input
82
119
 
83
120
  strip_terminal_sequences() {
84
- if command -v perl >/dev/null 2>&1; then
85
- perl -pe 's/\e\][^\a\e]*(?:\a|\e\\)//g; s/\e[@-_][0-?]*[ -\/]*[@-~]//g'
121
+ if [[ -x /usr/bin/perl && -f /usr/bin/perl && ! -L /usr/bin/perl ]]; then
122
+ /usr/bin/perl -pe 's/\e\][^\a\e]*(?:\a|\e\\)//g; s/\e[@-_][0-?]*[ -\/]*[@-~]//g'
86
123
  else
87
124
  cat
88
125
  fi
@@ -106,18 +143,17 @@ sanitize_statusline() {
106
143
 
107
144
  # ── 1) OMC HUD 출력 ──────────────────────────────────────────────────────────
108
145
  omc_out=''
109
- omc_script="${OMC_HUD_SCRIPT:-$HOME/.claude/hud/omc-hud.mjs}"
110
- if [[ -r "$omc_script" ]] && command -v node >/dev/null 2>&1; then
111
- omc_out=$(printf '%s' "$input" | node "$omc_script" 2>/dev/null || true)
146
+ if approved_executable_file "$approved_node" && approved_regular_file "$approved_omc_script"; then
147
+ omc_out=$(printf '%s' "$input" | "$approved_node" "$approved_omc_script" 2>/dev/null || true)
112
148
  omc_out=$(sanitize_statusline "$omc_out")
113
149
  fi
114
150
 
115
151
  # ── 2) context-guard-statusline 바이너리 위치 결정 ────────────────────────────
116
- # 우선순위: 환경변수 → 자기 옆 디렉토리
117
- # PATH fallback 은 workspace/plugin 경로 shadowing 으로 untrusted binary 를
118
- # 실행할 있어 사용하지 않는다. 외부 바이너리를 쓰려면 명시적으로
119
- # CONTEXT_GUARD_STATUSLINE_BIN 을 지정해야 한다.
120
- tok_bin="${CONTEXT_GUARD_STATUSLINE_BIN:-${CLAUDE_TOKEN_STATUSLINE_BIN:-}}"
152
+ # setup이 고정한 절대 helper → 자기 옆 디렉토리 순서만 허용한다.
153
+ tok_bin=''
154
+ if approved_executable_file "$approved_token_statusline"; then
155
+ tok_bin=$approved_token_statusline
156
+ fi
121
157
  if [[ -z "$tok_bin" ]]; then
122
158
  self_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd || true)"
123
159
  for cand in \
@@ -131,7 +167,22 @@ if [[ -z "$tok_bin" ]]; then
131
167
  fi
132
168
  tok_out=''
133
169
  if [[ -n "$tok_bin" && -x "$tok_bin" ]]; then
134
- tok_out=$(printf '%s' "$input" | "$tok_bin" 2>/dev/null || true)
170
+ tok_basename=${tok_bin##*/}
171
+ if [[ "$tok_basename" == "context-guard-statusline" || "$tok_basename" == "claude-token-statusline" || "$tok_basename" == "statusline.sh" ]]; then
172
+ tok_bash=$approved_bash
173
+ if ! approved_executable_file "$tok_bash"; then
174
+ tok_bash=$(command -v bash 2>/dev/null || true)
175
+ fi
176
+ if approved_executable_file "$tok_bash"; then
177
+ tok_command=("$tok_bash" --noprofile --norc "$tok_bin")
178
+ if approved_executable_file "$approved_python"; then
179
+ tok_command+=(--approved-python "$approved_python")
180
+ fi
181
+ tok_out=$(printf '%s' "$input" | "${tok_command[@]}" 2>/dev/null || true)
182
+ fi
183
+ else
184
+ tok_out=$(printf '%s' "$input" | "$tok_bin" 2>/dev/null || true)
185
+ fi
135
186
  tok_out=$(sanitize_statusline "$tok_out")
136
187
  fi
137
188