@node9/proxy 1.64.0 → 1.65.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.
@@ -2459,7 +2459,7 @@ var init_trusted_hosts = __esm({
2459
2459
  });
2460
2460
 
2461
2461
  // src/config/index.ts
2462
- var DANGEROUS_WORDS, DEFAULT_CONFIG;
2462
+ var DANGEROUS_WORDS, DEFAULT_CONFIG, CACHE_LOG_REARM_MS;
2463
2463
  var init_config = __esm({
2464
2464
  "src/config/index.ts"() {
2465
2465
  "use strict";
@@ -2684,6 +2684,7 @@ var init_config = __esm({
2684
2684
  },
2685
2685
  environments: {}
2686
2686
  };
2687
+ CACHE_LOG_REARM_MS = 5 * 60 * 1e3;
2687
2688
  }
2688
2689
  });
2689
2690
 
package/dist/index.js CHANGED
@@ -4070,9 +4070,9 @@ function getActiveEnvironment(config) {
4070
4070
  const env = config.settings.environment || process.env.NODE_ENV || "development";
4071
4071
  return config.environments[env] ?? null;
4072
4072
  }
4073
- var cacheReadFailureLogged = false;
4074
4073
  function readRulesCacheResilient(cacheFile) {
4075
4074
  let existed = false;
4075
+ let sawReadError = false;
4076
4076
  for (let attempt = 0; attempt < 3; attempt++) {
4077
4077
  let content;
4078
4078
  try {
@@ -4080,30 +4080,42 @@ function readRulesCacheResilient(cacheFile) {
4080
4080
  existed = true;
4081
4081
  } catch (err) {
4082
4082
  if (err.code === "ENOENT") return {};
4083
+ sawReadError = true;
4083
4084
  continue;
4084
4085
  }
4085
4086
  try {
4086
- return JSON.parse(content);
4087
+ const parsed = JSON.parse(content);
4088
+ lastParsedRulesCache = parsed;
4089
+ return parsed;
4087
4090
  } catch {
4088
4091
  }
4089
4092
  }
4090
- if (existed) {
4093
+ if (existed || sawReadError) {
4091
4094
  const backup = import_path4.default.join(import_path4.default.dirname(cacheFile), "rules-cache.last-good.json");
4092
4095
  if (backup !== cacheFile) {
4093
4096
  try {
4094
4097
  const raw = JSON.parse(import_fs4.default.readFileSync(backup, "utf-8"));
4095
4098
  logCacheReadIssue(cacheFile, "RULES_CACHE_CORRUPT_USED_BACKUP");
4099
+ lastParsedRulesCache = raw;
4096
4100
  return raw;
4097
4101
  } catch {
4098
4102
  }
4099
4103
  }
4104
+ if (lastParsedRulesCache) {
4105
+ logCacheReadIssue(cacheFile, "RULES_CACHE_USED_MEMORY");
4106
+ return lastParsedRulesCache;
4107
+ }
4100
4108
  logCacheReadIssue(cacheFile, "RULES_CACHE_UNREADABLE");
4101
4109
  }
4102
4110
  return {};
4103
4111
  }
4112
+ var lastParsedRulesCache = null;
4113
+ var CACHE_LOG_REARM_MS = 5 * 60 * 1e3;
4114
+ var cacheReadLastLoggedAt = 0;
4104
4115
  function logCacheReadIssue(cacheFile, kind) {
4105
- if (cacheReadFailureLogged) return;
4106
- cacheReadFailureLogged = true;
4116
+ const now = Date.now();
4117
+ if (now - cacheReadLastLoggedAt < CACHE_LOG_REARM_MS) return;
4118
+ cacheReadLastLoggedAt = now;
4107
4119
  try {
4108
4120
  import_fs4.default.appendFileSync(
4109
4121
  import_path4.default.join(import_os4.default.homedir(), ".node9", "hook-debug.log"),
@@ -5616,6 +5628,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
5616
5628
  let riskMetadata;
5617
5629
  let statefulRecoveryCommand;
5618
5630
  let localSmartRuleMatched = false;
5631
+ let hardBlockDowngraded = false;
5619
5632
  let taintWarning = null;
5620
5633
  if (isNetworkTool(toolName, args)) {
5621
5634
  const filePaths = extractFilePaths(toolName, args);
@@ -5857,6 +5870,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
5857
5870
  return { approved: true, checkedBy: "local-policy" };
5858
5871
  }
5859
5872
  if (policyResult.decision === "block") {
5873
+ hardBlockDowngraded = true;
5860
5874
  const daemonUp = isDaemonRunning();
5861
5875
  let humanApproverReachable = false;
5862
5876
  if (!policyResult.dependsOnStatePredicates?.length && daemonUp && !isTestEnv2) {
@@ -5930,7 +5944,8 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
5930
5944
  explainableLabel = policyResult.blockedByLabel || "Local Config";
5931
5945
  policyMatchedField = policyResult.matchedField;
5932
5946
  policyMatchedWord = policyResult.matchedWord;
5933
- if (policyResult.ruleName || policyResult.tier === 7) localSmartRuleMatched = true;
5947
+ if (policyResult.ruleName || policyResult.tier === 7 || hardBlockDowngraded)
5948
+ localSmartRuleMatched = true;
5934
5949
  if (policyResult.ruleDescription) policyRuleDescription = policyResult.ruleDescription;
5935
5950
  else if (policyResult.reason) policyRuleDescription = policyResult.reason;
5936
5951
  riskMetadata = computeRiskMetadata(
@@ -5942,7 +5957,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
5942
5957
  policyResult.ruleName
5943
5958
  );
5944
5959
  if (policyRuleDescription) riskMetadata.ruleDescription = policyRuleDescription.slice(0, 200);
5945
- const persistent = policyResult.ruleName || policyResult.tier === 7 ? null : getPersistentDecision(toolName);
5960
+ const persistent = policyResult.ruleName || policyResult.tier === 7 || hardBlockDowngraded ? null : getPersistentDecision(toolName);
5946
5961
  if (persistent === "allow" && !appPermReview) {
5947
5962
  if (!isManual) appendLocalAudit(toolName, args, "allow", "persistent", meta, hashAuditArgs);
5948
5963
  return { approved: true, checkedBy: "persistent" };
@@ -5975,7 +5990,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
5975
5990
  return { approved: true };
5976
5991
  }
5977
5992
  }
5978
- if (!taintWarning && !appPermReview && getActiveTrustSession(toolName, args)) {
5993
+ if (!taintWarning && !appPermReview && !hardBlockDowngraded && getActiveTrustSession(toolName, args)) {
5979
5994
  if (!isManual) appendLocalAudit(toolName, args, "allow", "trust", meta, hashAuditArgs);
5980
5995
  return { approved: true, checkedBy: "trust" };
5981
5996
  }
@@ -6015,7 +6030,7 @@ ${appPermReview}`
6015
6030
  }
6016
6031
  }
6017
6032
  const cloudEnforcedForDefer = approvers.cloud && !!creds?.apiKey;
6018
- if (options?.deferReview && !taintWarning && !appPermReview && !cloudEnforcedForDefer) {
6033
+ if (options?.deferReview && !hardBlockDowngraded && !taintWarning && !appPermReview && !cloudEnforcedForDefer) {
6019
6034
  return {
6020
6035
  approved: false,
6021
6036
  review: true,
@@ -6039,7 +6054,7 @@ ${appPermReview}`
6039
6054
  forceReview
6040
6055
  );
6041
6056
  if (!initResult.pending) {
6042
- if (initResult.shadowMode && !appPermReview) {
6057
+ if (initResult.shadowMode && !localSmartRuleMatched && !options?.localSmartRuleMatched && !appPermReview) {
6043
6058
  return { approved: true, checkedBy: "cloud" };
6044
6059
  }
6045
6060
  if (!localSmartRuleMatched && !options?.localSmartRuleMatched && !appPermReview) {
package/dist/index.mjs CHANGED
@@ -4040,9 +4040,9 @@ function getActiveEnvironment(config) {
4040
4040
  const env = config.settings.environment || process.env.NODE_ENV || "development";
4041
4041
  return config.environments[env] ?? null;
4042
4042
  }
4043
- var cacheReadFailureLogged = false;
4044
4043
  function readRulesCacheResilient(cacheFile) {
4045
4044
  let existed = false;
4045
+ let sawReadError = false;
4046
4046
  for (let attempt = 0; attempt < 3; attempt++) {
4047
4047
  let content;
4048
4048
  try {
@@ -4050,30 +4050,42 @@ function readRulesCacheResilient(cacheFile) {
4050
4050
  existed = true;
4051
4051
  } catch (err) {
4052
4052
  if (err.code === "ENOENT") return {};
4053
+ sawReadError = true;
4053
4054
  continue;
4054
4055
  }
4055
4056
  try {
4056
- return JSON.parse(content);
4057
+ const parsed = JSON.parse(content);
4058
+ lastParsedRulesCache = parsed;
4059
+ return parsed;
4057
4060
  } catch {
4058
4061
  }
4059
4062
  }
4060
- if (existed) {
4063
+ if (existed || sawReadError) {
4061
4064
  const backup = path4.join(path4.dirname(cacheFile), "rules-cache.last-good.json");
4062
4065
  if (backup !== cacheFile) {
4063
4066
  try {
4064
4067
  const raw = JSON.parse(fs4.readFileSync(backup, "utf-8"));
4065
4068
  logCacheReadIssue(cacheFile, "RULES_CACHE_CORRUPT_USED_BACKUP");
4069
+ lastParsedRulesCache = raw;
4066
4070
  return raw;
4067
4071
  } catch {
4068
4072
  }
4069
4073
  }
4074
+ if (lastParsedRulesCache) {
4075
+ logCacheReadIssue(cacheFile, "RULES_CACHE_USED_MEMORY");
4076
+ return lastParsedRulesCache;
4077
+ }
4070
4078
  logCacheReadIssue(cacheFile, "RULES_CACHE_UNREADABLE");
4071
4079
  }
4072
4080
  return {};
4073
4081
  }
4082
+ var lastParsedRulesCache = null;
4083
+ var CACHE_LOG_REARM_MS = 5 * 60 * 1e3;
4084
+ var cacheReadLastLoggedAt = 0;
4074
4085
  function logCacheReadIssue(cacheFile, kind) {
4075
- if (cacheReadFailureLogged) return;
4076
- cacheReadFailureLogged = true;
4086
+ const now = Date.now();
4087
+ if (now - cacheReadLastLoggedAt < CACHE_LOG_REARM_MS) return;
4088
+ cacheReadLastLoggedAt = now;
4077
4089
  try {
4078
4090
  fs4.appendFileSync(
4079
4091
  path4.join(os4.homedir(), ".node9", "hook-debug.log"),
@@ -5586,6 +5598,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
5586
5598
  let riskMetadata;
5587
5599
  let statefulRecoveryCommand;
5588
5600
  let localSmartRuleMatched = false;
5601
+ let hardBlockDowngraded = false;
5589
5602
  let taintWarning = null;
5590
5603
  if (isNetworkTool(toolName, args)) {
5591
5604
  const filePaths = extractFilePaths(toolName, args);
@@ -5827,6 +5840,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
5827
5840
  return { approved: true, checkedBy: "local-policy" };
5828
5841
  }
5829
5842
  if (policyResult.decision === "block") {
5843
+ hardBlockDowngraded = true;
5830
5844
  const daemonUp = isDaemonRunning();
5831
5845
  let humanApproverReachable = false;
5832
5846
  if (!policyResult.dependsOnStatePredicates?.length && daemonUp && !isTestEnv2) {
@@ -5900,7 +5914,8 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
5900
5914
  explainableLabel = policyResult.blockedByLabel || "Local Config";
5901
5915
  policyMatchedField = policyResult.matchedField;
5902
5916
  policyMatchedWord = policyResult.matchedWord;
5903
- if (policyResult.ruleName || policyResult.tier === 7) localSmartRuleMatched = true;
5917
+ if (policyResult.ruleName || policyResult.tier === 7 || hardBlockDowngraded)
5918
+ localSmartRuleMatched = true;
5904
5919
  if (policyResult.ruleDescription) policyRuleDescription = policyResult.ruleDescription;
5905
5920
  else if (policyResult.reason) policyRuleDescription = policyResult.reason;
5906
5921
  riskMetadata = computeRiskMetadata(
@@ -5912,7 +5927,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
5912
5927
  policyResult.ruleName
5913
5928
  );
5914
5929
  if (policyRuleDescription) riskMetadata.ruleDescription = policyRuleDescription.slice(0, 200);
5915
- const persistent = policyResult.ruleName || policyResult.tier === 7 ? null : getPersistentDecision(toolName);
5930
+ const persistent = policyResult.ruleName || policyResult.tier === 7 || hardBlockDowngraded ? null : getPersistentDecision(toolName);
5916
5931
  if (persistent === "allow" && !appPermReview) {
5917
5932
  if (!isManual) appendLocalAudit(toolName, args, "allow", "persistent", meta, hashAuditArgs);
5918
5933
  return { approved: true, checkedBy: "persistent" };
@@ -5945,7 +5960,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
5945
5960
  return { approved: true };
5946
5961
  }
5947
5962
  }
5948
- if (!taintWarning && !appPermReview && getActiveTrustSession(toolName, args)) {
5963
+ if (!taintWarning && !appPermReview && !hardBlockDowngraded && getActiveTrustSession(toolName, args)) {
5949
5964
  if (!isManual) appendLocalAudit(toolName, args, "allow", "trust", meta, hashAuditArgs);
5950
5965
  return { approved: true, checkedBy: "trust" };
5951
5966
  }
@@ -5985,7 +6000,7 @@ ${appPermReview}`
5985
6000
  }
5986
6001
  }
5987
6002
  const cloudEnforcedForDefer = approvers.cloud && !!creds?.apiKey;
5988
- if (options?.deferReview && !taintWarning && !appPermReview && !cloudEnforcedForDefer) {
6003
+ if (options?.deferReview && !hardBlockDowngraded && !taintWarning && !appPermReview && !cloudEnforcedForDefer) {
5989
6004
  return {
5990
6005
  approved: false,
5991
6006
  review: true,
@@ -6009,7 +6024,7 @@ ${appPermReview}`
6009
6024
  forceReview
6010
6025
  );
6011
6026
  if (!initResult.pending) {
6012
- if (initResult.shadowMode && !appPermReview) {
6027
+ if (initResult.shadowMode && !localSmartRuleMatched && !options?.localSmartRuleMatched && !appPermReview) {
6013
6028
  return { approved: true, checkedBy: "cloud" };
6014
6029
  }
6015
6030
  if (!localSmartRuleMatched && !options?.localSmartRuleMatched && !appPermReview) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node9/proxy",
3
- "version": "1.64.0",
3
+ "version": "1.65.1",
4
4
  "description": "The Sudo Command for AI Agents. Execution Security for Claude Code, Codex, Gemini, Cursor, Opencode, Pi, and any MCP server.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",