claude-cac 1.5.0-beta.1 → 1.5.0-beta.2
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.
- package/cac +75 -69
- package/package.json +1 -1
package/cac
CHANGED
|
@@ -11,7 +11,7 @@ VERSIONS_DIR="$CAC_DIR/versions"
|
|
|
11
11
|
# ── utils: colors, read/write, UUID, proxy parsing ───────────────────────
|
|
12
12
|
|
|
13
13
|
# shellcheck disable=SC2034 # used in build-concatenated cac script
|
|
14
|
-
CAC_VERSION="1.5.0-beta.
|
|
14
|
+
CAC_VERSION="1.5.0-beta.2"
|
|
15
15
|
|
|
16
16
|
_read() { [[ -f "$1" ]] && tr -d '[:space:]' < "$1" || echo "${2:-}"; }
|
|
17
17
|
_die() { printf '%b\n' "$(_red "error:") $*" >&2; exit 1; }
|
|
@@ -2351,22 +2351,74 @@ cmd_check() {
|
|
|
2351
2351
|
fi
|
|
2352
2352
|
fi
|
|
2353
2353
|
|
|
2354
|
-
# ──
|
|
2354
|
+
# ── identity spoofing (consolidated) ──
|
|
2355
|
+
local os; os=$(_detect_os)
|
|
2356
|
+
local _id_ok=0 _id_total=0 _id_issues=()
|
|
2357
|
+
|
|
2358
|
+
# fingerprint hook
|
|
2359
|
+
local _fp_ok=false
|
|
2355
2360
|
if [[ -f "$CAC_DIR/fingerprint-hook.js" ]] && [[ -f "$env_dir/hostname" ]]; then
|
|
2356
2361
|
local expected_hn; expected_hn=$(_read "$env_dir/hostname")
|
|
2357
2362
|
local actual_hn
|
|
2358
2363
|
actual_hn=$(NODE_OPTIONS="--require $CAC_DIR/fingerprint-hook.js" CAC_HOSTNAME="$expected_hn" \
|
|
2359
2364
|
node -e "process.stdout.write(require('os').hostname())" 2>/dev/null || true)
|
|
2365
|
+
(( _id_total++ )) || true
|
|
2360
2366
|
if [[ "$actual_hn" == "$expected_hn" ]]; then
|
|
2361
|
-
|
|
2367
|
+
_fp_ok=true; (( _id_ok++ )) || true
|
|
2362
2368
|
else
|
|
2363
|
-
|
|
2364
|
-
|
|
2369
|
+
_id_issues+=("fingerprint hook not working")
|
|
2370
|
+
fi
|
|
2371
|
+
fi
|
|
2372
|
+
# git email
|
|
2373
|
+
(( _id_total++ )) || true
|
|
2374
|
+
if [[ -f "$env_dir/git_email" ]]; then
|
|
2375
|
+
(( _id_ok++ )) || true
|
|
2376
|
+
else
|
|
2377
|
+
_id_issues+=("git email not spoofed")
|
|
2378
|
+
fi
|
|
2379
|
+
# repo hash
|
|
2380
|
+
(( _id_total++ )) || true
|
|
2381
|
+
if [[ -f "$env_dir/fake_git_remote" ]]; then
|
|
2382
|
+
(( _id_ok++ )) || true
|
|
2383
|
+
else
|
|
2384
|
+
_id_issues+=("repo hash not spoofed")
|
|
2385
|
+
fi
|
|
2386
|
+
# user_id consistency
|
|
2387
|
+
local _uid_ok=true
|
|
2388
|
+
local _env_uid; _env_uid=$(_read "$env_dir/user_id" "")
|
|
2389
|
+
if [[ -n "$_env_uid" ]]; then
|
|
2390
|
+
local _config_dir="${CLAUDE_CONFIG_DIR:-$ENVS_DIR/$current/.claude}"
|
|
2391
|
+
local _cj="$_config_dir/.claude.json"
|
|
2392
|
+
[[ -f "$_cj" ]] || _cj="$HOME/.claude.json"
|
|
2393
|
+
if [[ -f "$_cj" ]]; then
|
|
2394
|
+
local _actual_uid
|
|
2395
|
+
_actual_uid=$(python3 -c "import json,sys; print(json.load(open(sys.argv[1])).get('userID',''))" "$_cj" 2>/dev/null || true)
|
|
2396
|
+
(( _id_total++ )) || true
|
|
2397
|
+
if [[ -n "$_actual_uid" ]] && [[ "$_actual_uid" != "$_env_uid" ]]; then
|
|
2398
|
+
_uid_ok=false
|
|
2399
|
+
_id_issues+=("user_id mismatch")
|
|
2400
|
+
else
|
|
2401
|
+
(( _id_ok++ )) || true
|
|
2402
|
+
fi
|
|
2365
2403
|
fi
|
|
2366
2404
|
fi
|
|
2405
|
+
# billing header
|
|
2406
|
+
(( _id_total++ )) || true
|
|
2407
|
+
[[ "$wrapper_content" == *"CLAUDE_CODE_ATTRIBUTION_HEADER"* ]] && { (( _id_ok++ )) || true; } || _id_issues+=("billing header exposed")
|
|
2408
|
+
|
|
2409
|
+
# display consolidated identity line
|
|
2410
|
+
local _id_extra=""
|
|
2411
|
+
[[ -f "$env_dir/persona" ]] && _id_extra=" + $(_read "$env_dir/persona")"
|
|
2412
|
+
if [[ "$_id_ok" -eq "$_id_total" ]]; then
|
|
2413
|
+
echo " $(_green "✓") identity ${_id_ok}/${_id_total} spoofed${_id_extra}"
|
|
2414
|
+
else
|
|
2415
|
+
echo " $(_red "✗") identity ${_id_ok}/${_id_total} spoofed${_id_extra}"
|
|
2416
|
+
for _ii in "${_id_issues[@]}"; do
|
|
2417
|
+
problems+=("$_ii")
|
|
2418
|
+
done
|
|
2419
|
+
fi
|
|
2367
2420
|
|
|
2368
2421
|
# ── IPv6 leak detection ──
|
|
2369
|
-
local os; os=$(_detect_os)
|
|
2370
2422
|
local ipv6_leak=false
|
|
2371
2423
|
if [[ "$os" == "macos" ]]; then
|
|
2372
2424
|
local ipv6_addrs
|
|
@@ -2378,80 +2430,28 @@ cmd_check() {
|
|
|
2378
2430
|
[[ "$ipv6_addrs" -gt 0 ]] && ipv6_leak=true
|
|
2379
2431
|
fi
|
|
2380
2432
|
if [[ "$ipv6_leak" == "true" ]]; then
|
|
2381
|
-
echo " $(_yellow "⚠") IPv6
|
|
2433
|
+
echo " $(_yellow "⚠") IPv6 global address detected (potential leak)"
|
|
2382
2434
|
else
|
|
2383
|
-
echo " $(_green "✓") IPv6
|
|
2435
|
+
echo " $(_green "✓") IPv6 no global address"
|
|
2384
2436
|
fi
|
|
2385
2437
|
|
|
2386
|
-
# ──
|
|
2438
|
+
# ── warnings (only shown when relevant) ──
|
|
2387
2439
|
if [[ -d "$HOME/.claude/telemetry" ]]; then
|
|
2388
2440
|
local tel_files
|
|
2389
2441
|
tel_files=$(find "$HOME/.claude/telemetry" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
2390
2442
|
if [[ "$tel_files" -gt 0 ]]; then
|
|
2391
|
-
echo " $(_yellow "⚠") residual
|
|
2392
|
-
echo " $(_dim "hint: rm -rf ~/.claude/telemetry/")"
|
|
2443
|
+
echo " $(_yellow "⚠") residual $tel_files telemetry files in ~/.claude/telemetry/"
|
|
2393
2444
|
fi
|
|
2394
2445
|
fi
|
|
2395
|
-
|
|
2396
|
-
# ── concurrent sessions ──
|
|
2397
2446
|
local _claude_count
|
|
2398
2447
|
_claude_count=$(pgrep -x "claude" 2>/dev/null | wc -l | tr -d '[:space:]') || _claude_count=0
|
|
2399
2448
|
local _max_sessions; _max_sessions=$(_cac_setting max_sessions 10)
|
|
2400
2449
|
if [[ "$_claude_count" -gt "$_max_sessions" ]]; then
|
|
2401
|
-
echo " $(_yellow "⚠") sessions
|
|
2402
|
-
fi
|
|
2403
|
-
|
|
2404
|
-
# ── metadata.user_id consistency ──
|
|
2405
|
-
local _env_uid; _env_uid=$(_read "$env_dir/user_id" "")
|
|
2406
|
-
if [[ -n "$_env_uid" ]]; then
|
|
2407
|
-
local _config_dir="${CLAUDE_CONFIG_DIR:-$ENVS_DIR/$current/.claude}"
|
|
2408
|
-
local _cj="$_config_dir/.claude.json"
|
|
2409
|
-
[[ -f "$_cj" ]] || _cj="$HOME/.claude.json"
|
|
2410
|
-
if [[ -f "$_cj" ]]; then
|
|
2411
|
-
local _actual_uid
|
|
2412
|
-
_actual_uid=$(python3 -c "import json,sys; print(json.load(open(sys.argv[1])).get('userID',''))" "$_cj" 2>/dev/null || true)
|
|
2413
|
-
if [[ -n "$_actual_uid" ]] && [[ "$_actual_uid" != "$_env_uid" ]]; then
|
|
2414
|
-
echo " $(_yellow "⚠") user_id mismatch — Claude may have overwritten it"
|
|
2415
|
-
echo " $(_dim "env: ${_env_uid:0:16}... json: ${_actual_uid:0:16}...")"
|
|
2416
|
-
problems+=("user_id mismatch between env file and .claude.json")
|
|
2417
|
-
else
|
|
2418
|
-
echo " $(_green "✓") user_id consistent"
|
|
2419
|
-
fi
|
|
2420
|
-
fi
|
|
2421
|
-
fi
|
|
2422
|
-
|
|
2423
|
-
# ── git email spoofing ──
|
|
2424
|
-
if [[ -f "$env_dir/git_email" ]]; then
|
|
2425
|
-
echo " $(_green "✓") git email spoofed ($(_dim "$(_read "$env_dir/git_email")"))"
|
|
2426
|
-
else
|
|
2427
|
-
echo " $(_yellow "⚠") git email not spoofed (real email exposed)"
|
|
2428
|
-
fi
|
|
2429
|
-
|
|
2430
|
-
# ── repository fingerprint (rh) ──
|
|
2431
|
-
if [[ -f "$env_dir/fake_git_remote" ]]; then
|
|
2432
|
-
echo " $(_green "✓") repo hash spoofed"
|
|
2433
|
-
else
|
|
2434
|
-
echo " $(_yellow "⚠") repo hash not spoofed (rh links activity across accounts)"
|
|
2450
|
+
echo " $(_yellow "⚠") sessions $_claude_count running (threshold: $_max_sessions)"
|
|
2435
2451
|
fi
|
|
2436
|
-
|
|
2437
|
-
# ── billing header ──
|
|
2438
|
-
if [[ "$wrapper_content" == *"CLAUDE_CODE_ATTRIBUTION_HEADER"* ]]; then
|
|
2439
|
-
echo " $(_green "✓") billing header disabled"
|
|
2440
|
-
fi
|
|
2441
|
-
|
|
2442
|
-
# ── Keychain residual (macOS) ──
|
|
2443
2452
|
if [[ "$os" == "macos" ]]; then
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
if [[ "$_kc_found" == "true" ]]; then
|
|
2447
|
-
echo " $(_yellow "⚠") keychain Trusted Device Token found in macOS Keychain"
|
|
2448
|
-
echo " $(_dim "hint: security delete-generic-password -s 'claude-code-credentials'")"
|
|
2449
|
-
fi
|
|
2450
|
-
fi
|
|
2451
|
-
|
|
2452
|
-
# ── persona ──
|
|
2453
|
-
if [[ -f "$env_dir/persona" ]]; then
|
|
2454
|
-
echo " $(_green "✓") persona $(_dim "$(_read "$env_dir/persona")")"
|
|
2453
|
+
security find-generic-password -s "claude-code-credentials" >/dev/null 2>&1 && \
|
|
2454
|
+
echo " $(_yellow "⚠") keychain Trusted Device Token residual"
|
|
2455
2455
|
fi
|
|
2456
2456
|
|
|
2457
2457
|
# ── network check (slow — streaming output) ──
|
|
@@ -2551,13 +2551,19 @@ cmd_check() {
|
|
|
2551
2551
|
|
|
2552
2552
|
# ── verbose mode ──
|
|
2553
2553
|
if [[ "$verbose" == "true" ]]; then
|
|
2554
|
+
echo " $(_bold "Identity")"
|
|
2555
|
+
echo " $([[ "$_fp_ok" == "true" ]] && _green "✓" || _red "✗") hostname $(_read "$env_dir/hostname" "—")"
|
|
2556
|
+
echo " $([[ -f "$env_dir/git_email" ]] && _green "✓" || _yellow "⚠") git email $(_read "$env_dir/git_email" "—")"
|
|
2557
|
+
echo " $([[ -f "$env_dir/fake_git_remote" ]] && _green "✓" || _yellow "⚠") repo hash $(_read "$env_dir/fake_git_remote" "—")"
|
|
2558
|
+
echo " $([[ "$_uid_ok" == "true" ]] && _green "✓" || _yellow "⚠") user_id $(_read "$env_dir/user_id" "—" | cut -c1-16)..."
|
|
2559
|
+
echo " $([[ "$wrapper_content" == *"CLAUDE_CODE_ATTRIBUTION_HEADER"* ]] && _green "✓" || _yellow "⚠") billing $([[ "$wrapper_content" == *"CLAUDE_CODE_ATTRIBUTION_HEADER"* ]] && echo "disabled" || echo "exposed")"
|
|
2560
|
+
[[ -f "$env_dir/persona" ]] && echo " $(_green "✓") persona $(_read "$env_dir/persona")"
|
|
2561
|
+
echo
|
|
2554
2562
|
echo " $(_bold "Details")"
|
|
2555
2563
|
echo " $(_dim "UUID") $(_read "$env_dir/uuid")"
|
|
2556
2564
|
echo " $(_dim "stable_id") $(_read "$env_dir/stable_id")"
|
|
2557
|
-
echo " $(_dim "
|
|
2558
|
-
echo " $(_dim "
|
|
2559
|
-
echo " $(_dim "rh_remote") $(_read "$env_dir/fake_git_remote" "—")"
|
|
2560
|
-
echo " $(_dim "persona") $(_read "$env_dir/persona" "—")"
|
|
2565
|
+
echo " $(_dim "MAC") $(_read "$env_dir/mac_address" "—")"
|
|
2566
|
+
echo " $(_dim "machine_id") $(_read "$env_dir/machine_id" "—")"
|
|
2561
2567
|
echo " $(_dim "TZ") $(_read "$env_dir/tz" "—")"
|
|
2562
2568
|
echo " $(_dim "LANG") $(_read "$env_dir/lang" "—")"
|
|
2563
2569
|
echo " $(_dim "env") ${env_dir/#$HOME/~}/.claude/"
|