@node9/proxy 1.12.10 → 1.13.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.
package/dist/cli.js CHANGED
@@ -1266,7 +1266,8 @@ var init_dlp = __esm({
1266
1266
  name: "GitHub Token",
1267
1267
  regex: /\bgh[pous]_[A-Za-z0-9]{36}\b/,
1268
1268
  severity: "block",
1269
- keywords: ["ghp_", "gho_", "ghu_", "ghs_"]
1269
+ keywords: ["ghp_", "gho_", "ghu_", "ghs_"],
1270
+ minEntropy: 3
1270
1271
  },
1271
1272
  {
1272
1273
  name: "GitHub Fine-Grained PAT",
@@ -1317,7 +1318,8 @@ var init_dlp = __esm({
1317
1318
  name: "GCP API Key",
1318
1319
  regex: /\bAIza[0-9A-Za-z_-]{35}\b/,
1319
1320
  severity: "block",
1320
- keywords: ["aiza"]
1321
+ keywords: ["aiza"],
1322
+ minEntropy: 3
1321
1323
  },
1322
1324
  {
1323
1325
  name: "GCP Service Account",
@@ -1564,7 +1566,8 @@ var init_dlp = __esm({
1564
1566
  name: "Mapbox Access Token",
1565
1567
  regex: /\bpk\.eyJ1[a-zA-Z0-9._-]{20,}\b/,
1566
1568
  severity: "block",
1567
- keywords: ["pk.eyj1"]
1569
+ keywords: ["pk.eyj1"],
1570
+ minEntropy: 3
1568
1571
  },
1569
1572
  // ── Notion ────────────────────────────────────────────────────────────────
1570
1573
  {
@@ -9929,6 +9932,7 @@ function scanClaudeHistory(startDate, onProgress, onLine) {
9929
9932
  continue;
9930
9933
  }
9931
9934
  const sessionCalls = [];
9935
+ const toolUseFilePaths = /* @__PURE__ */ new Map();
9932
9936
  for (const line of raw.split("\n")) {
9933
9937
  if (!line.trim()) continue;
9934
9938
  onLine?.();
@@ -9971,6 +9975,33 @@ function scanClaudeHistory(startDate, onProgress, onLine) {
9971
9975
  }
9972
9976
  }
9973
9977
  }
9978
+ for (const block of content2) {
9979
+ if (block.type !== "tool_result") continue;
9980
+ const filePath = block.tool_use_id ? toolUseFilePaths.get(block.tool_use_id) : void 0;
9981
+ if (filePath) {
9982
+ const ext = import_path17.default.extname(filePath).toLowerCase();
9983
+ if (CODE_EXTENSIONS.has(ext)) continue;
9984
+ }
9985
+ const resultText = typeof block.content === "string" ? block.content : Array.isArray(block.content) ? block.content.map((c) => c.text ?? "").join("\n") : null;
9986
+ if (!resultText) continue;
9987
+ const dlpMatch = scanArgs({ text: resultText });
9988
+ if (dlpMatch) {
9989
+ const isDupe = result.dlpFindings.some(
9990
+ (f) => f.patternName === dlpMatch.patternName && f.redactedSample === dlpMatch.redactedSample && f.project === projLabel
9991
+ );
9992
+ if (!isDupe) {
9993
+ result.dlpFindings.push({
9994
+ patternName: dlpMatch.patternName,
9995
+ redactedSample: dlpMatch.redactedSample,
9996
+ toolName: "tool-result",
9997
+ timestamp: entry.timestamp ?? "",
9998
+ project: projLabel,
9999
+ sessionId,
10000
+ agent: "claude"
10001
+ });
10002
+ }
10003
+ }
10004
+ }
9974
10005
  }
9975
10006
  continue;
9976
10007
  }
@@ -9990,6 +10021,9 @@ function scanClaudeHistory(startDate, onProgress, onLine) {
9990
10021
  const toolName = block.name ?? "";
9991
10022
  const toolNameLower = toolName.toLowerCase();
9992
10023
  const input = block.input ?? {};
10024
+ if (block.id && typeof input.file_path === "string") {
10025
+ toolUseFilePaths.set(block.id, input.file_path);
10026
+ }
9993
10027
  sessionCalls.push({ toolName, input, timestamp: entry.timestamp ?? "" });
9994
10028
  if (toolNameLower === "bash" || toolNameLower === "execute_bash") {
9995
10029
  result.bashCalls++;
@@ -9997,6 +10031,9 @@ function scanClaudeHistory(startDate, onProgress, onLine) {
9997
10031
  const rawCmd = String(input.command ?? "").trimStart();
9998
10032
  if (/^node9\s+(scan|explain|report|tail|dlp|status|sessions|audit)\b/.test(rawCmd))
9999
10033
  continue;
10034
+ const inputFilePath = typeof input.file_path === "string" ? input.file_path : "";
10035
+ const inputFileExt = inputFilePath ? import_path17.default.extname(inputFilePath).toLowerCase() : "";
10036
+ if (CODE_EXTENSIONS.has(inputFileExt)) continue;
10000
10037
  const dlpMatch = scanArgs(input);
10001
10038
  if (dlpMatch) {
10002
10039
  const isDupe = result.dlpFindings.some(
@@ -10493,6 +10530,44 @@ function scanCodexHistory(startDate, onProgress, onLine) {
10493
10530
  }
10494
10531
  return result;
10495
10532
  }
10533
+ function scanShellConfig() {
10534
+ const home = import_os12.default.homedir();
10535
+ const configFiles = [".zshrc", ".bashrc", ".bash_profile", ".profile"].map(
10536
+ (f) => import_path17.default.join(home, f)
10537
+ );
10538
+ const findings = [];
10539
+ for (const filePath of configFiles) {
10540
+ if (!import_fs14.default.existsSync(filePath)) continue;
10541
+ let lines;
10542
+ try {
10543
+ lines = import_fs14.default.readFileSync(filePath, "utf-8").split("\n");
10544
+ } catch {
10545
+ continue;
10546
+ }
10547
+ const shortPath = filePath.replace(home, "~");
10548
+ for (const line of lines) {
10549
+ const trimmed = line.trim();
10550
+ if (!trimmed || trimmed.startsWith("#")) continue;
10551
+ const dlpMatch = scanArgs({ text: trimmed });
10552
+ if (!dlpMatch) continue;
10553
+ const isDupe = findings.some(
10554
+ (f) => f.patternName === dlpMatch.patternName && f.redactedSample === dlpMatch.redactedSample && f.project === shortPath
10555
+ );
10556
+ if (!isDupe) {
10557
+ findings.push({
10558
+ patternName: dlpMatch.patternName,
10559
+ redactedSample: dlpMatch.redactedSample,
10560
+ toolName: "shell-config",
10561
+ timestamp: "",
10562
+ project: shortPath,
10563
+ sessionId: "",
10564
+ agent: "shell"
10565
+ });
10566
+ }
10567
+ }
10568
+ }
10569
+ return findings;
10570
+ }
10496
10571
  function mergeScans(a, b) {
10497
10572
  const dates = [a.firstDate, b.firstDate].filter(Boolean);
10498
10573
  const lastDates = [a.lastDate, b.lastDate].filter(Boolean);
@@ -10607,6 +10682,7 @@ function registerScanCommand(program2) {
10607
10682
  onLine
10608
10683
  );
10609
10684
  const scan = mergeScans(mergeScans(claudeScan, geminiScan), codexScan);
10685
+ scan.dlpFindings.push(...scanShellConfig());
10610
10686
  const summary = buildScanSummary([
10611
10687
  { id: "claude", label: "Claude", icon: "\u{1F916}", scan: claudeScan },
10612
10688
  { id: "gemini", label: "Gemini", icon: "\u264A", scan: geminiScan },
@@ -10660,7 +10736,7 @@ function registerScanCommand(program2) {
10660
10736
  }
10661
10737
  if (scan.dlpFindings.length > 0) {
10662
10738
  console.log(
10663
- " " + import_chalk2.default.red("\u{1F511} Credential leak") + " " + import_chalk2.default.red.bold(String(scan.dlpFindings.length).padStart(5)) + import_chalk2.default.dim(" secret detected in tool call")
10739
+ " " + import_chalk2.default.red("\u{1F511} Credential leak") + " " + import_chalk2.default.red.bold(String(scan.dlpFindings.length).padStart(5)) + import_chalk2.default.dim(" secret detected in history or shell config")
10664
10740
  );
10665
10741
  }
10666
10742
  if (blockedCount > 0) {
@@ -10669,8 +10745,9 @@ function registerScanCommand(program2) {
10669
10745
  );
10670
10746
  }
10671
10747
  if (scan.loopFindings.length > 0) {
10748
+ const loopCost = summary.loopWastedUSD > 0 ? import_chalk2.default.dim(" \xB7 ") + import_chalk2.default.yellow("~" + fmtCost(summary.loopWastedUSD) + " wasted") : "";
10672
10749
  console.log(
10673
- " " + import_chalk2.default.yellow("\u{1F501} Loop detected") + " " + import_chalk2.default.yellow.bold(String(scan.loopFindings.length).padStart(5)) + import_chalk2.default.dim(" repeated tool call patterns found")
10750
+ " " + import_chalk2.default.yellow("\u{1F501} Loop detected") + " " + import_chalk2.default.yellow.bold(String(scan.loopFindings.length).padStart(5)) + import_chalk2.default.dim(" repeated tool call patterns found") + loopCost
10674
10751
  );
10675
10752
  }
10676
10753
  if (reviewCount > 0) {
@@ -10690,7 +10767,7 @@ function registerScanCommand(program2) {
10690
10767
  for (const f of shownDlp) {
10691
10768
  const ts = f.timestamp ? import_chalk2.default.dim(fmtTs(f.timestamp) + " ") : "";
10692
10769
  const proj = import_chalk2.default.dim(f.project.slice(0, 22).padEnd(22) + " ");
10693
- const agentBadge = f.agent === "gemini" ? import_chalk2.default.blue("[Gemini] ") : f.agent === "codex" ? import_chalk2.default.magenta("[Codex] ") : import_chalk2.default.cyan("[Claude] ");
10770
+ const agentBadge = f.agent === "gemini" ? import_chalk2.default.blue("[Gemini] ") : f.agent === "codex" ? import_chalk2.default.magenta("[Codex] ") : f.agent === "shell" ? import_chalk2.default.yellow("[Shell] ") : import_chalk2.default.cyan("[Claude] ");
10694
10771
  const sessionSuffix = f.sessionId ? import_chalk2.default.dim(` \u2192 ${f.sessionId.slice(0, 8)}`) : "";
10695
10772
  console.log(
10696
10773
  ` \u{1F6A8} ${ts}${proj}${agentBadge}` + import_chalk2.default.yellow(f.patternName) + import_chalk2.default.dim(" ") + import_chalk2.default.gray(f.redactedSample) + sessionSuffix
@@ -10722,10 +10799,11 @@ function registerScanCommand(program2) {
10722
10799
  }
10723
10800
  if (scan.loopFindings.length > 0) {
10724
10801
  console.log(" " + import_chalk2.default.dim("\u2500".repeat(70)));
10802
+ const loopCostLabel = summary.loopWastedUSD > 0 ? import_chalk2.default.dim(" \xB7 ") + import_chalk2.default.yellow("~" + fmtCost(summary.loopWastedUSD) + " wasted") : "";
10725
10803
  console.log(
10726
10804
  " " + import_chalk2.default.yellow.bold("\u{1F501} Agent Loops") + import_chalk2.default.dim(" \xB7 ") + import_chalk2.default.yellow(
10727
10805
  `${num(scan.loopFindings.length)} repeated pattern${scan.loopFindings.length !== 1 ? "s" : ""} found`
10728
- )
10806
+ ) + loopCostLabel
10729
10807
  );
10730
10808
  const shownLoops = drillDown ? scan.loopFindings : scan.loopFindings.slice(0, topN);
10731
10809
  for (const f of shownLoops) {
@@ -10848,7 +10926,7 @@ function registerScanCommand(program2) {
10848
10926
  }
10849
10927
  });
10850
10928
  }
10851
- var import_chalk2, import_fs14, import_path17, import_os12, CLAUDE_PRICING, GEMINI_PRICING, LOOP_TOOLS, LOOP_THRESHOLD, DEFAULT_RULE_NAMES;
10929
+ var import_chalk2, import_fs14, import_path17, import_os12, CLAUDE_PRICING, GEMINI_PRICING, CODE_EXTENSIONS, LOOP_TOOLS, LOOP_THRESHOLD, DEFAULT_RULE_NAMES;
10852
10930
  var init_scan = __esm({
10853
10931
  "src/cli/commands/scan.ts"() {
10854
10932
  "use strict";
@@ -10884,6 +10962,33 @@ var init_scan = __esm({
10884
10962
  "gemini-1.5-flash": { i: 75e-9, o: 3e-7, cr: 1875e-11 },
10885
10963
  "gemini-3-flash": { i: 1e-7, o: 4e-7, cr: 25e-9 }
10886
10964
  };
10965
+ CODE_EXTENSIONS = /* @__PURE__ */ new Set([
10966
+ ".ts",
10967
+ ".tsx",
10968
+ ".js",
10969
+ ".jsx",
10970
+ ".mjs",
10971
+ ".cjs",
10972
+ ".py",
10973
+ ".rb",
10974
+ ".go",
10975
+ ".rs",
10976
+ ".java",
10977
+ ".kt",
10978
+ ".swift",
10979
+ ".c",
10980
+ ".cpp",
10981
+ ".h",
10982
+ ".cs",
10983
+ ".php",
10984
+ ".sh",
10985
+ ".bash",
10986
+ ".html",
10987
+ ".css",
10988
+ ".scss",
10989
+ ".vue",
10990
+ ".svelte"
10991
+ ]);
10887
10992
  LOOP_TOOLS = /* @__PURE__ */ new Set([
10888
10993
  "bash",
10889
10994
  "execute_bash",
@@ -17566,6 +17671,7 @@ init_core();
17566
17671
  init_setup();
17567
17672
  init_shields();
17568
17673
  init_service();
17674
+ init_daemon_starter();
17569
17675
  var DEFAULT_SHIELDS = ["bash-safe", "filesystem", "postgres"];
17570
17676
  function fireTelemetryPing(agents) {
17571
17677
  try {
@@ -17704,6 +17810,19 @@ function registerInitCommand(program2) {
17704
17810
  } else {
17705
17811
  console.log(import_chalk13.default.green(" \u2713 Daemon login service already installed"));
17706
17812
  }
17813
+ if (!isTestingMode()) {
17814
+ process.stdout.write(import_chalk13.default.dim(" Starting daemon..."));
17815
+ const started = await autoStartDaemonAndWait(false);
17816
+ if (started) {
17817
+ process.stdout.write(
17818
+ "\r" + import_chalk13.default.green(" \u2713 Daemon started \u2014 protection is active") + "\n"
17819
+ );
17820
+ } else {
17821
+ process.stdout.write(
17822
+ "\r" + import_chalk13.default.dim(" Daemon will start on next login ") + "\n"
17823
+ );
17824
+ }
17825
+ }
17707
17826
  console.log("");
17708
17827
  }
17709
17828
  {
package/dist/cli.mjs CHANGED
@@ -1244,7 +1244,8 @@ var init_dlp = __esm({
1244
1244
  name: "GitHub Token",
1245
1245
  regex: /\bgh[pous]_[A-Za-z0-9]{36}\b/,
1246
1246
  severity: "block",
1247
- keywords: ["ghp_", "gho_", "ghu_", "ghs_"]
1247
+ keywords: ["ghp_", "gho_", "ghu_", "ghs_"],
1248
+ minEntropy: 3
1248
1249
  },
1249
1250
  {
1250
1251
  name: "GitHub Fine-Grained PAT",
@@ -1295,7 +1296,8 @@ var init_dlp = __esm({
1295
1296
  name: "GCP API Key",
1296
1297
  regex: /\bAIza[0-9A-Za-z_-]{35}\b/,
1297
1298
  severity: "block",
1298
- keywords: ["aiza"]
1299
+ keywords: ["aiza"],
1300
+ minEntropy: 3
1299
1301
  },
1300
1302
  {
1301
1303
  name: "GCP Service Account",
@@ -1542,7 +1544,8 @@ var init_dlp = __esm({
1542
1544
  name: "Mapbox Access Token",
1543
1545
  regex: /\bpk\.eyJ1[a-zA-Z0-9._-]{20,}\b/,
1544
1546
  severity: "block",
1545
- keywords: ["pk.eyj1"]
1547
+ keywords: ["pk.eyj1"],
1548
+ minEntropy: 3
1546
1549
  },
1547
1550
  // ── Notion ────────────────────────────────────────────────────────────────
1548
1551
  {
@@ -9909,6 +9912,7 @@ function scanClaudeHistory(startDate, onProgress, onLine) {
9909
9912
  continue;
9910
9913
  }
9911
9914
  const sessionCalls = [];
9915
+ const toolUseFilePaths = /* @__PURE__ */ new Map();
9912
9916
  for (const line of raw.split("\n")) {
9913
9917
  if (!line.trim()) continue;
9914
9918
  onLine?.();
@@ -9951,6 +9955,33 @@ function scanClaudeHistory(startDate, onProgress, onLine) {
9951
9955
  }
9952
9956
  }
9953
9957
  }
9958
+ for (const block of content2) {
9959
+ if (block.type !== "tool_result") continue;
9960
+ const filePath = block.tool_use_id ? toolUseFilePaths.get(block.tool_use_id) : void 0;
9961
+ if (filePath) {
9962
+ const ext = path17.extname(filePath).toLowerCase();
9963
+ if (CODE_EXTENSIONS.has(ext)) continue;
9964
+ }
9965
+ const resultText = typeof block.content === "string" ? block.content : Array.isArray(block.content) ? block.content.map((c) => c.text ?? "").join("\n") : null;
9966
+ if (!resultText) continue;
9967
+ const dlpMatch = scanArgs({ text: resultText });
9968
+ if (dlpMatch) {
9969
+ const isDupe = result.dlpFindings.some(
9970
+ (f) => f.patternName === dlpMatch.patternName && f.redactedSample === dlpMatch.redactedSample && f.project === projLabel
9971
+ );
9972
+ if (!isDupe) {
9973
+ result.dlpFindings.push({
9974
+ patternName: dlpMatch.patternName,
9975
+ redactedSample: dlpMatch.redactedSample,
9976
+ toolName: "tool-result",
9977
+ timestamp: entry.timestamp ?? "",
9978
+ project: projLabel,
9979
+ sessionId,
9980
+ agent: "claude"
9981
+ });
9982
+ }
9983
+ }
9984
+ }
9954
9985
  }
9955
9986
  continue;
9956
9987
  }
@@ -9970,6 +10001,9 @@ function scanClaudeHistory(startDate, onProgress, onLine) {
9970
10001
  const toolName = block.name ?? "";
9971
10002
  const toolNameLower = toolName.toLowerCase();
9972
10003
  const input = block.input ?? {};
10004
+ if (block.id && typeof input.file_path === "string") {
10005
+ toolUseFilePaths.set(block.id, input.file_path);
10006
+ }
9973
10007
  sessionCalls.push({ toolName, input, timestamp: entry.timestamp ?? "" });
9974
10008
  if (toolNameLower === "bash" || toolNameLower === "execute_bash") {
9975
10009
  result.bashCalls++;
@@ -9977,6 +10011,9 @@ function scanClaudeHistory(startDate, onProgress, onLine) {
9977
10011
  const rawCmd = String(input.command ?? "").trimStart();
9978
10012
  if (/^node9\s+(scan|explain|report|tail|dlp|status|sessions|audit)\b/.test(rawCmd))
9979
10013
  continue;
10014
+ const inputFilePath = typeof input.file_path === "string" ? input.file_path : "";
10015
+ const inputFileExt = inputFilePath ? path17.extname(inputFilePath).toLowerCase() : "";
10016
+ if (CODE_EXTENSIONS.has(inputFileExt)) continue;
9980
10017
  const dlpMatch = scanArgs(input);
9981
10018
  if (dlpMatch) {
9982
10019
  const isDupe = result.dlpFindings.some(
@@ -10473,6 +10510,44 @@ function scanCodexHistory(startDate, onProgress, onLine) {
10473
10510
  }
10474
10511
  return result;
10475
10512
  }
10513
+ function scanShellConfig() {
10514
+ const home = os12.homedir();
10515
+ const configFiles = [".zshrc", ".bashrc", ".bash_profile", ".profile"].map(
10516
+ (f) => path17.join(home, f)
10517
+ );
10518
+ const findings = [];
10519
+ for (const filePath of configFiles) {
10520
+ if (!fs14.existsSync(filePath)) continue;
10521
+ let lines;
10522
+ try {
10523
+ lines = fs14.readFileSync(filePath, "utf-8").split("\n");
10524
+ } catch {
10525
+ continue;
10526
+ }
10527
+ const shortPath = filePath.replace(home, "~");
10528
+ for (const line of lines) {
10529
+ const trimmed = line.trim();
10530
+ if (!trimmed || trimmed.startsWith("#")) continue;
10531
+ const dlpMatch = scanArgs({ text: trimmed });
10532
+ if (!dlpMatch) continue;
10533
+ const isDupe = findings.some(
10534
+ (f) => f.patternName === dlpMatch.patternName && f.redactedSample === dlpMatch.redactedSample && f.project === shortPath
10535
+ );
10536
+ if (!isDupe) {
10537
+ findings.push({
10538
+ patternName: dlpMatch.patternName,
10539
+ redactedSample: dlpMatch.redactedSample,
10540
+ toolName: "shell-config",
10541
+ timestamp: "",
10542
+ project: shortPath,
10543
+ sessionId: "",
10544
+ agent: "shell"
10545
+ });
10546
+ }
10547
+ }
10548
+ }
10549
+ return findings;
10550
+ }
10476
10551
  function mergeScans(a, b) {
10477
10552
  const dates = [a.firstDate, b.firstDate].filter(Boolean);
10478
10553
  const lastDates = [a.lastDate, b.lastDate].filter(Boolean);
@@ -10587,6 +10662,7 @@ function registerScanCommand(program2) {
10587
10662
  onLine
10588
10663
  );
10589
10664
  const scan = mergeScans(mergeScans(claudeScan, geminiScan), codexScan);
10665
+ scan.dlpFindings.push(...scanShellConfig());
10590
10666
  const summary = buildScanSummary([
10591
10667
  { id: "claude", label: "Claude", icon: "\u{1F916}", scan: claudeScan },
10592
10668
  { id: "gemini", label: "Gemini", icon: "\u264A", scan: geminiScan },
@@ -10640,7 +10716,7 @@ function registerScanCommand(program2) {
10640
10716
  }
10641
10717
  if (scan.dlpFindings.length > 0) {
10642
10718
  console.log(
10643
- " " + chalk2.red("\u{1F511} Credential leak") + " " + chalk2.red.bold(String(scan.dlpFindings.length).padStart(5)) + chalk2.dim(" secret detected in tool call")
10719
+ " " + chalk2.red("\u{1F511} Credential leak") + " " + chalk2.red.bold(String(scan.dlpFindings.length).padStart(5)) + chalk2.dim(" secret detected in history or shell config")
10644
10720
  );
10645
10721
  }
10646
10722
  if (blockedCount > 0) {
@@ -10649,8 +10725,9 @@ function registerScanCommand(program2) {
10649
10725
  );
10650
10726
  }
10651
10727
  if (scan.loopFindings.length > 0) {
10728
+ const loopCost = summary.loopWastedUSD > 0 ? chalk2.dim(" \xB7 ") + chalk2.yellow("~" + fmtCost(summary.loopWastedUSD) + " wasted") : "";
10652
10729
  console.log(
10653
- " " + chalk2.yellow("\u{1F501} Loop detected") + " " + chalk2.yellow.bold(String(scan.loopFindings.length).padStart(5)) + chalk2.dim(" repeated tool call patterns found")
10730
+ " " + chalk2.yellow("\u{1F501} Loop detected") + " " + chalk2.yellow.bold(String(scan.loopFindings.length).padStart(5)) + chalk2.dim(" repeated tool call patterns found") + loopCost
10654
10731
  );
10655
10732
  }
10656
10733
  if (reviewCount > 0) {
@@ -10670,7 +10747,7 @@ function registerScanCommand(program2) {
10670
10747
  for (const f of shownDlp) {
10671
10748
  const ts = f.timestamp ? chalk2.dim(fmtTs(f.timestamp) + " ") : "";
10672
10749
  const proj = chalk2.dim(f.project.slice(0, 22).padEnd(22) + " ");
10673
- const agentBadge = f.agent === "gemini" ? chalk2.blue("[Gemini] ") : f.agent === "codex" ? chalk2.magenta("[Codex] ") : chalk2.cyan("[Claude] ");
10750
+ const agentBadge = f.agent === "gemini" ? chalk2.blue("[Gemini] ") : f.agent === "codex" ? chalk2.magenta("[Codex] ") : f.agent === "shell" ? chalk2.yellow("[Shell] ") : chalk2.cyan("[Claude] ");
10674
10751
  const sessionSuffix = f.sessionId ? chalk2.dim(` \u2192 ${f.sessionId.slice(0, 8)}`) : "";
10675
10752
  console.log(
10676
10753
  ` \u{1F6A8} ${ts}${proj}${agentBadge}` + chalk2.yellow(f.patternName) + chalk2.dim(" ") + chalk2.gray(f.redactedSample) + sessionSuffix
@@ -10702,10 +10779,11 @@ function registerScanCommand(program2) {
10702
10779
  }
10703
10780
  if (scan.loopFindings.length > 0) {
10704
10781
  console.log(" " + chalk2.dim("\u2500".repeat(70)));
10782
+ const loopCostLabel = summary.loopWastedUSD > 0 ? chalk2.dim(" \xB7 ") + chalk2.yellow("~" + fmtCost(summary.loopWastedUSD) + " wasted") : "";
10705
10783
  console.log(
10706
10784
  " " + chalk2.yellow.bold("\u{1F501} Agent Loops") + chalk2.dim(" \xB7 ") + chalk2.yellow(
10707
10785
  `${num(scan.loopFindings.length)} repeated pattern${scan.loopFindings.length !== 1 ? "s" : ""} found`
10708
- )
10786
+ ) + loopCostLabel
10709
10787
  );
10710
10788
  const shownLoops = drillDown ? scan.loopFindings : scan.loopFindings.slice(0, topN);
10711
10789
  for (const f of shownLoops) {
@@ -10828,7 +10906,7 @@ function registerScanCommand(program2) {
10828
10906
  }
10829
10907
  });
10830
10908
  }
10831
- var CLAUDE_PRICING, GEMINI_PRICING, LOOP_TOOLS, LOOP_THRESHOLD, DEFAULT_RULE_NAMES;
10909
+ var CLAUDE_PRICING, GEMINI_PRICING, CODE_EXTENSIONS, LOOP_TOOLS, LOOP_THRESHOLD, DEFAULT_RULE_NAMES;
10832
10910
  var init_scan = __esm({
10833
10911
  "src/cli/commands/scan.ts"() {
10834
10912
  "use strict";
@@ -10860,6 +10938,33 @@ var init_scan = __esm({
10860
10938
  "gemini-1.5-flash": { i: 75e-9, o: 3e-7, cr: 1875e-11 },
10861
10939
  "gemini-3-flash": { i: 1e-7, o: 4e-7, cr: 25e-9 }
10862
10940
  };
10941
+ CODE_EXTENSIONS = /* @__PURE__ */ new Set([
10942
+ ".ts",
10943
+ ".tsx",
10944
+ ".js",
10945
+ ".jsx",
10946
+ ".mjs",
10947
+ ".cjs",
10948
+ ".py",
10949
+ ".rb",
10950
+ ".go",
10951
+ ".rs",
10952
+ ".java",
10953
+ ".kt",
10954
+ ".swift",
10955
+ ".c",
10956
+ ".cpp",
10957
+ ".h",
10958
+ ".cs",
10959
+ ".php",
10960
+ ".sh",
10961
+ ".bash",
10962
+ ".html",
10963
+ ".css",
10964
+ ".scss",
10965
+ ".vue",
10966
+ ".svelte"
10967
+ ]);
10863
10968
  LOOP_TOOLS = /* @__PURE__ */ new Set([
10864
10969
  "bash",
10865
10970
  "execute_bash",
@@ -17535,6 +17640,7 @@ init_core();
17535
17640
  init_setup();
17536
17641
  init_shields();
17537
17642
  init_service();
17643
+ init_daemon_starter();
17538
17644
  import chalk13 from "chalk";
17539
17645
  import fs33 from "fs";
17540
17646
  import path35 from "path";
@@ -17678,6 +17784,19 @@ function registerInitCommand(program2) {
17678
17784
  } else {
17679
17785
  console.log(chalk13.green(" \u2713 Daemon login service already installed"));
17680
17786
  }
17787
+ if (!isTestingMode()) {
17788
+ process.stdout.write(chalk13.dim(" Starting daemon..."));
17789
+ const started = await autoStartDaemonAndWait(false);
17790
+ if (started) {
17791
+ process.stdout.write(
17792
+ "\r" + chalk13.green(" \u2713 Daemon started \u2014 protection is active") + "\n"
17793
+ );
17794
+ } else {
17795
+ process.stdout.write(
17796
+ "\r" + chalk13.dim(" Daemon will start on next login ") + "\n"
17797
+ );
17798
+ }
17799
+ }
17681
17800
  console.log("");
17682
17801
  }
17683
17802
  {
package/dist/index.js CHANGED
@@ -1045,7 +1045,8 @@ var DLP_PATTERNS = [
1045
1045
  name: "GitHub Token",
1046
1046
  regex: /\bgh[pous]_[A-Za-z0-9]{36}\b/,
1047
1047
  severity: "block",
1048
- keywords: ["ghp_", "gho_", "ghu_", "ghs_"]
1048
+ keywords: ["ghp_", "gho_", "ghu_", "ghs_"],
1049
+ minEntropy: 3
1049
1050
  },
1050
1051
  {
1051
1052
  name: "GitHub Fine-Grained PAT",
@@ -1096,7 +1097,8 @@ var DLP_PATTERNS = [
1096
1097
  name: "GCP API Key",
1097
1098
  regex: /\bAIza[0-9A-Za-z_-]{35}\b/,
1098
1099
  severity: "block",
1099
- keywords: ["aiza"]
1100
+ keywords: ["aiza"],
1101
+ minEntropy: 3
1100
1102
  },
1101
1103
  {
1102
1104
  name: "GCP Service Account",
@@ -1343,7 +1345,8 @@ var DLP_PATTERNS = [
1343
1345
  name: "Mapbox Access Token",
1344
1346
  regex: /\bpk\.eyJ1[a-zA-Z0-9._-]{20,}\b/,
1345
1347
  severity: "block",
1346
- keywords: ["pk.eyj1"]
1348
+ keywords: ["pk.eyj1"],
1349
+ minEntropy: 3
1347
1350
  },
1348
1351
  // ── Notion ────────────────────────────────────────────────────────────────
1349
1352
  {
package/dist/index.mjs CHANGED
@@ -1015,7 +1015,8 @@ var DLP_PATTERNS = [
1015
1015
  name: "GitHub Token",
1016
1016
  regex: /\bgh[pous]_[A-Za-z0-9]{36}\b/,
1017
1017
  severity: "block",
1018
- keywords: ["ghp_", "gho_", "ghu_", "ghs_"]
1018
+ keywords: ["ghp_", "gho_", "ghu_", "ghs_"],
1019
+ minEntropy: 3
1019
1020
  },
1020
1021
  {
1021
1022
  name: "GitHub Fine-Grained PAT",
@@ -1066,7 +1067,8 @@ var DLP_PATTERNS = [
1066
1067
  name: "GCP API Key",
1067
1068
  regex: /\bAIza[0-9A-Za-z_-]{35}\b/,
1068
1069
  severity: "block",
1069
- keywords: ["aiza"]
1070
+ keywords: ["aiza"],
1071
+ minEntropy: 3
1070
1072
  },
1071
1073
  {
1072
1074
  name: "GCP Service Account",
@@ -1313,7 +1315,8 @@ var DLP_PATTERNS = [
1313
1315
  name: "Mapbox Access Token",
1314
1316
  regex: /\bpk\.eyJ1[a-zA-Z0-9._-]{20,}\b/,
1315
1317
  severity: "block",
1316
- keywords: ["pk.eyj1"]
1318
+ keywords: ["pk.eyj1"],
1319
+ minEntropy: 3
1317
1320
  },
1318
1321
  // ── Notion ────────────────────────────────────────────────────────────────
1319
1322
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node9/proxy",
3
- "version": "1.12.10",
3
+ "version": "1.13.0",
4
4
  "description": "The Sudo Command for AI Agents. Execution Security for Claude Code & MCP.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",