claude-cac 1.5.0-beta.2 → 1.5.0

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.
Files changed (3) hide show
  1. package/cac +10 -14
  2. package/fingerprint-hook.js +16 -31
  3. 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.2"
14
+ CAC_VERSION="1.5.0"
15
15
 
16
16
  _read() { [[ -f "$1" ]] && tr -d '[:space:]' < "$1" || echo "${2:-}"; }
17
17
  _die() { printf '%b\n' "$(_red "error:") $*" >&2; exit 1; }
@@ -63,7 +63,7 @@ _new_hostname() { echo "host-$(_gen_uuid | cut -d- -f1 | tr '[:upper:]' '[:lower
63
63
  _new_mac() { printf '02:%02x:%02x:%02x:%02x:%02x' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)); }
64
64
  _new_git_remote() { echo "https://github.com/user-$(_gen_uuid | cut -d- -f1)/project-$(_gen_uuid | cut -d- -f2).git"; }
65
65
  _new_git_email() { echo "user-$(_gen_uuid | cut -d- -f1 | tr '[:upper:]' '[:lower:]')@users.noreply.github.com"; }
66
- _new_device_token() { python3 -c "import os; print(os.urandom(32).hex())" || _die "python3 required"; }
66
+ _new_device_token() { _new_user_id; }
67
67
 
68
68
  # Get real command path (bypass shim)
69
69
  _get_real_cmd() {
@@ -1232,12 +1232,10 @@ if [[ -n "$PROXY" ]]; then
1232
1232
  fi
1233
1233
 
1234
1234
  # ── git identity spoofing ──
1235
- # Prevent git email leakage (Claude runs `git config --get user.email` on startup)
1235
+ # Intercept `git config --get user.email` at process level (telemetry read only)
1236
+ # Do NOT set GIT_AUTHOR_EMAIL/GIT_COMMITTER_EMAIL — those would affect real git commits
1236
1237
  if [[ -f "$_env_dir/git_email" ]]; then
1237
- _git_email=$(tr -d '[:space:]' < "$_env_dir/git_email")
1238
- export GIT_AUTHOR_EMAIL="$_git_email"
1239
- export GIT_COMMITTER_EMAIL="$_git_email"
1240
- export CAC_GIT_EMAIL="$_git_email"
1238
+ export CAC_GIT_EMAIL=$(tr -d '[:space:]' < "$_env_dir/git_email")
1241
1239
  fi
1242
1240
 
1243
1241
  # ── repository fingerprint (rh) spoofing ──
@@ -1255,31 +1253,29 @@ fi
1255
1253
  # ── persona (Docker/server environment spoofing) ──
1256
1254
  if [[ -f "$_env_dir/persona" ]]; then
1257
1255
  _persona=$(tr -d '[:space:]' < "$_env_dir/persona")
1256
+ export TERM="xterm-256color"
1258
1257
  case "$_persona" in
1259
1258
  macos-vscode)
1260
1259
  export TERM_PROGRAM="vscode"
1261
1260
  export VSCODE_GIT_ASKPASS_MAIN="/Applications/Visual Studio Code.app/Contents/Resources/app/extensions/git/dist/askpass-main.js"
1262
1261
  export __CFBundleIdentifier="com.microsoft.VSCode"
1263
- export TERM="xterm-256color"
1264
1262
  ;;
1265
1263
  macos-cursor)
1266
1264
  export TERM_PROGRAM="vscode"
1267
- export CURSOR_TRACE_ID="cursor-$(head -c 8 /dev/urandom 2>/dev/null | od -An -tx1 | tr -d ' \n')"
1265
+ [[ -f "$_env_dir/cursor_trace_id" ]] || printf 'cursor-%s' "$(od -An -tx1 -N8 /dev/urandom | tr -d ' \n')" > "$_env_dir/cursor_trace_id"
1266
+ export CURSOR_TRACE_ID=$(tr -d '[:space:]' < "$_env_dir/cursor_trace_id")
1268
1267
  export __CFBundleIdentifier="com.todesktop.230313mzl4w4u92"
1269
- export TERM="xterm-256color"
1270
1268
  ;;
1271
1269
  macos-iterm)
1272
1270
  export TERM_PROGRAM="iTerm.app"
1273
1271
  export __CFBundleIdentifier="com.googlecode.iterm2"
1274
- export TERM="xterm-256color"
1275
- export ITERM_SESSION_ID="w0t0p0:$(head -c 16 /dev/urandom 2>/dev/null | od -An -tx1 | tr -d ' \n')"
1272
+ [[ -f "$_env_dir/iterm_session_id" ]] || printf 'w0t0p0:%s' "$(od -An -tx1 -N16 /dev/urandom | tr -d ' \n')" > "$_env_dir/iterm_session_id"
1273
+ export ITERM_SESSION_ID=$(tr -d '[:space:]' < "$_env_dir/iterm_session_id")
1276
1274
  ;;
1277
1275
  linux-desktop)
1278
1276
  export TERM_PROGRAM="vscode"
1279
- export TERM="xterm-256color"
1280
1277
  ;;
1281
1278
  esac
1282
- # Hide Docker signals when persona is active
1283
1279
  export CAC_HIDE_DOCKER=1
1284
1280
  fi
1285
1281
 
@@ -115,11 +115,7 @@ if (fakeGitRemote) {
115
115
  const _origExecSyncFp = child_process.execSync.bind(child_process);
116
116
  child_process.execSync = function(cmd, options) {
117
117
  var cmdStr = typeof cmd === 'string' ? cmd : cmd.toString();
118
- if (isGitRemoteCmd(cmdStr)) {
119
- var result = fakeGitRemote + '\n';
120
- return (typeof options === 'string' || (options && options.encoding))
121
- ? result : Buffer.from(result);
122
- }
118
+ if (isGitRemoteCmd(cmdStr)) return fakeResult(options, fakeGitRemote + '\n');
123
119
  return _origExecSyncFp(cmd, options);
124
120
  };
125
121
 
@@ -130,11 +126,7 @@ if (fakeGitRemote) {
130
126
  var cb = typeof args[args.length - 1] === 'function' ? args[args.length - 1] : null;
131
127
  if (isGitRemoteCmd(cmdStr)) {
132
128
  if (cb) process.nextTick(cb, null, fakeGitRemote + '\n', '');
133
- var { EventEmitter } = require('events');
134
- var cp = new EventEmitter();
135
- cp.stdout = new EventEmitter(); cp.stderr = new EventEmitter();
136
- cp.stdin = null; cp.pid = 0; cp.kill = function() { return false; };
137
- return cp;
129
+ return makeFakeChildProcess();
138
130
  }
139
131
  return _origExecFp.apply(child_process, args);
140
132
  };
@@ -145,9 +137,7 @@ if (fakeGitRemote) {
145
137
  var fullCmd = file + ' ' + fileArgs.join(' ');
146
138
  if (isGitRemoteCmd(fullCmd)) {
147
139
  var opts = Array.isArray(argsOrOpts) ? options : argsOrOpts;
148
- var result = fakeGitRemote + '\n';
149
- return (typeof opts === 'string' || (opts && opts.encoding))
150
- ? result : Buffer.from(result);
140
+ return fakeResult(opts, fakeGitRemote + '\n');
151
141
  }
152
142
  return _origExecFileSyncFp(file, argsOrOpts, options);
153
143
  };
@@ -158,14 +148,11 @@ if (fakeGitRemote) {
158
148
  // Intercept to prevent real email leakage (wrapper also sets GIT_AUTHOR_EMAIL)
159
149
  const fakeGitEmail = process.env.CAC_GIT_EMAIL;
160
150
  if (fakeGitEmail) {
161
- // Re-wrap execSync if not already wrapped for git remote
162
151
  var _prevExecSync = child_process.execSync;
163
152
  child_process.execSync = function(cmd, options) {
164
153
  var cmdStr = typeof cmd === 'string' ? cmd : cmd.toString();
165
154
  if (/git\s+config\s+(--global\s+|--get\s+)*user\.email/i.test(cmdStr)) {
166
- var result = fakeGitEmail + '\n';
167
- return (typeof options === 'string' || (options && options.encoding))
168
- ? result : Buffer.from(result);
155
+ return fakeResult(options, fakeGitEmail + '\n');
169
156
  }
170
157
  return _prevExecSync(cmd, options);
171
158
  };
@@ -183,20 +170,18 @@ if (process.env.CAC_HIDE_DOCKER === '1') {
183
170
  };
184
171
 
185
172
  // Intercept /proc/1/cgroup reads to remove docker references
186
- if (fakeMachineId || true) {
187
- var _prevReadFileSync = fs.readFileSync;
188
- fs.readFileSync = function(path, options) {
189
- var ps = typeof path === 'string' ? path : (path && path.toString ? path.toString() : '');
190
- if (ps === '/proc/1/cgroup') {
191
- var content;
192
- try { content = _prevReadFileSync(path, options); } catch(e) { throw e; }
193
- var str = typeof content === 'string' ? content : content.toString();
194
- str = str.replace(/docker|containerd|kubepods/gi, 'system.slice');
195
- return (typeof options === 'string' || (options && options.encoding)) ? str : Buffer.from(str);
196
- }
197
- return _prevReadFileSync(path, options);
198
- };
199
- }
173
+ var _prevReadFileSync = fs.readFileSync;
174
+ fs.readFileSync = function(path, options) {
175
+ var ps = typeof path === 'string' ? path : (path && path.toString ? path.toString() : '');
176
+ if (ps === '/proc/1/cgroup') {
177
+ var content;
178
+ try { content = _prevReadFileSync(path, options); } catch(e) { throw e; }
179
+ var str = typeof content === 'string' ? content : content.toString();
180
+ str = str.replace(/docker|containerd|kubepods/gi, 'system.slice');
181
+ return fakeResult(options, str);
182
+ }
183
+ return _prevReadFileSync(path, options);
184
+ };
200
185
  }
201
186
 
202
187
  // --- Windows: intercept child_process for wmic / reg queries ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-cac",
3
- "version": "1.5.0-beta.2",
3
+ "version": "1.5.0",
4
4
  "description": "Isolate, protect, and manage your Claude Code — versions, environments, identity, and proxy.",
5
5
  "bin": {
6
6
  "cac": "cac"