@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.
@@ -23,6 +23,7 @@ import math
23
23
  import os
24
24
  import re
25
25
  import shlex
26
+ import shutil
26
27
  import stat
27
28
  import sys
28
29
  import time
@@ -64,7 +65,7 @@ STATE_LOCK_TIMEOUT_SECONDS = 2.0
64
65
  STATE_LOCK_POLL_SECONDS = 0.01
65
66
  CGW1_SENTINEL = "--context-guard-wrapper-v1"
66
67
  CGW1_COMMAND_SEARCH_DIFF = "command_search_diff"
67
- CGW1_SHELL_ARGV = ("bash", "-lc")
68
+ CGW1_SHELL_ARGV = ("bash", "-c")
68
69
  LEGACY_V0_MAX_LINES = "220"
69
70
  PROTOCOL_CGW1 = "cgw1"
70
71
  PROTOCOL_LEGACY_V0 = "legacy-v0"
@@ -236,6 +237,60 @@ def _wrapper_prefixes() -> dict[str, tuple[str, ...]]:
236
237
  }
237
238
 
238
239
 
240
+ def _approved_python_runtime() -> str:
241
+ canonical = os.path.realpath(sys.executable)
242
+ if not canonical or not os.path.isabs(canonical) or not os.path.isfile(canonical) or not os.access(canonical, os.X_OK):
243
+ raise RuntimeError("approved Python runtime is unavailable")
244
+ return canonical
245
+
246
+
247
+ def _approved_bash_runtime() -> str:
248
+ found = shutil.which("bash", path=os.defpath)
249
+ if not found:
250
+ raise RuntimeError("approved Bash runtime is unavailable")
251
+ canonical = os.path.realpath(found)
252
+ if not os.path.isfile(canonical) or not os.access(canonical, os.X_OK):
253
+ raise RuntimeError("approved Bash runtime is unavailable")
254
+ return canonical
255
+
256
+
257
+ def _approved_env_runtime() -> str:
258
+ found = shutil.which("env", path=os.defpath)
259
+ if not found:
260
+ raise RuntimeError("approved env runtime is unavailable")
261
+ canonical = os.path.realpath(found)
262
+ if not os.path.isfile(canonical) or not os.access(canonical, os.X_OK):
263
+ raise RuntimeError("approved env runtime is unavailable")
264
+ return canonical
265
+
266
+
267
+ def _runtime_shell_argv() -> tuple[str, ...]:
268
+ return (
269
+ _approved_env_runtime(),
270
+ "-u", "BASH_ENV",
271
+ "-u", "ENV",
272
+ "-u", "PYTHONHOME",
273
+ "-u", "PYTHONPATH",
274
+ "-u", "PYTHONSTARTUP",
275
+ "-u", "SHELLOPTS",
276
+ "-u", "BASHOPTS",
277
+ "-u", "PS4",
278
+ _approved_bash_runtime(),
279
+ "--noprofile",
280
+ "--norc",
281
+ "-p",
282
+ "-c",
283
+ )
284
+
285
+
286
+ def _runtime_wrapper_prefixes() -> dict[str, tuple[str, ...]]:
287
+ adjacent = _wrapper_prefixes()
288
+ return {
289
+ kind: (_approved_python_runtime(), "-I", prefix[-1])
290
+ for kind, prefix in adjacent.items()
291
+ }
292
+
293
+
239
294
  def _argv(command: str) -> tuple[str, ...] | None:
240
295
  try:
241
296
  values = shlex.split(command, posix=True)
@@ -263,7 +318,14 @@ def _is_wrapper_shaped(argv: tuple[str, ...]) -> bool:
263
318
  return (
264
319
  re.fullmatch(r"python(?:\d+(?:\.\d+)?)?", first) is not None
265
320
  and len(argv) > 1
266
- and os.path.basename(argv[1]) in known
321
+ and (
322
+ os.path.basename(argv[1]) in known
323
+ or (
324
+ len(argv) > 2
325
+ and argv[1] == "-I"
326
+ and os.path.basename(argv[2]) in known
327
+ )
328
+ )
267
329
  )
268
330
 
269
331
 
@@ -274,32 +336,42 @@ def command_identity(command: str) -> CommandIdentity:
274
336
  return CommandIdentity(PROTOCOL_FOREIGN, sha256_text(command))
275
337
 
276
338
  prefixes = _wrapper_prefixes()
277
- sanitize_cgw1 = prefixes["sanitize"] + (
278
- CGW1_SENTINEL,
279
- CGW1_COMMAND_SEARCH_DIFF,
280
- "--",
281
- *CGW1_SHELL_ARGV,
282
- )
283
- if len(argv) == len(sanitize_cgw1) + 1 and argv[:-1] == sanitize_cgw1:
284
- logical = argv[-1]
285
- if logical and not _is_wrapper_shaped(_argv(logical) or ()):
286
- return CommandIdentity(PROTOCOL_CGW1, sha256_text(logical))
339
+ runtime_prefixes = _runtime_wrapper_prefixes()
340
+ current_shell_argv = _runtime_shell_argv()
341
+ for prefix, shell_argv in (
342
+ (runtime_prefixes["sanitize"], current_shell_argv),
343
+ (prefixes["sanitize"], CGW1_SHELL_ARGV),
344
+ ):
345
+ sanitize_cgw1 = prefix + (
346
+ CGW1_SENTINEL,
347
+ CGW1_COMMAND_SEARCH_DIFF,
348
+ "--",
349
+ *shell_argv,
350
+ )
351
+ if len(argv) == len(sanitize_cgw1) + 1 and argv[:-1] == sanitize_cgw1:
352
+ logical = argv[-1]
353
+ if logical and not _is_wrapper_shaped(_argv(logical) or ()):
354
+ return CommandIdentity(PROTOCOL_CGW1, sha256_text(logical))
287
355
 
288
356
  # The frozen A1 producer still emits this exact v0 envelope for trim.
289
357
  # The historical producer emitted it for sanitize as well, so both known
290
358
  # adjacent wrapper identities remain allowlisted for one compatibility
291
359
  # window. No other --/bash/-lc spelling is unwrapped.
292
- for prefix in prefixes.values():
293
- legacy_v0 = prefix + (
294
- "--max-lines",
295
- LEGACY_V0_MAX_LINES,
296
- "--",
297
- *CGW1_SHELL_ARGV,
298
- )
299
- if len(argv) == len(legacy_v0) + 1 and argv[:-1] == legacy_v0:
300
- logical = argv[-1]
301
- if logical and not _is_wrapper_shaped(_argv(logical) or ()):
302
- return CommandIdentity(PROTOCOL_LEGACY_V0, sha256_text(logical))
360
+ for prefix_set, shell_argv in (
361
+ (prefixes, CGW1_SHELL_ARGV),
362
+ (runtime_prefixes, current_shell_argv),
363
+ ):
364
+ for prefix in prefix_set.values():
365
+ legacy_v0 = prefix + (
366
+ "--max-lines",
367
+ LEGACY_V0_MAX_LINES,
368
+ "--",
369
+ *shell_argv,
370
+ )
371
+ if len(argv) == len(legacy_v0) + 1 and argv[:-1] == legacy_v0:
372
+ logical = argv[-1]
373
+ if logical and not _is_wrapper_shaped(_argv(logical) or ()):
374
+ return CommandIdentity(PROTOCOL_LEGACY_V0, sha256_text(logical))
303
375
 
304
376
  protocol = PROTOCOL_FOREIGN if (
305
377
  _is_wrapper_shaped(argv) or CGW1_SENTINEL in argv
@@ -520,9 +520,13 @@ def raw_read_range_outcome(
520
520
  def find_read_symbol_command() -> str:
521
521
  script_dir = Path(__file__).resolve().parent
522
522
  if (script_dir / "context-guard-read-symbol").exists():
523
- return "context-guard-read-symbol"
523
+ return shlex.join(
524
+ [os.path.realpath(sys.executable), "-I", str((script_dir / "context-guard-read-symbol").resolve())]
525
+ )
524
526
  if (script_dir / "read_symbol.py").exists():
525
- return "python3 context-guard-kit/read_symbol.py"
527
+ return shlex.join(
528
+ [os.path.realpath(sys.executable), "-I", str((script_dir / "read_symbol.py").resolve())]
529
+ )
526
530
  return "context-guard-read-symbol"
527
531
 
528
532
 
@@ -32,6 +32,7 @@ MAX_CALLS = 1000
32
32
  MAX_ARTIFACTS = 1000
33
33
  MAX_VISITED_ENTRIES = 4000
34
34
  HELPER_TIMEOUT = 10.0
35
+ HELPER_TERMINATE_GRACE = 0.1
35
36
  MAX_HELPER_STDERR = 16 * 1024
36
37
  MAX_HELPER_OUTPUT = 5 * 1024 * 1024
37
38
  MAX_RESPONSE_BYTES = 128 * 1024
@@ -456,7 +457,7 @@ class Server:
456
457
  # process group and inherited pipes alive. Give the whole group a
457
458
  # bounded TERM grace period, then escalate the group independently
458
459
  # of the direct child's return code.
459
- grace_deadline = time.monotonic() + 0.5
460
+ grace_deadline = time.monotonic() + HELPER_TERMINATE_GRACE
460
461
  group_exists = True
461
462
  while time.monotonic() < grace_deadline:
462
463
  try: