@node9/proxy 2.5.0 → 2.6.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.
- package/README.md +14 -1
- package/dist/cli.js +1373 -1146
- package/dist/cli.mjs +1366 -1139
- package/dist/dashboard.mjs +1031 -127
- package/dist/index.js +111 -48
- package/dist/index.mjs +111 -48
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -4027,6 +4027,10 @@ var COMMAND_CHECK_KEYS = [
|
|
|
4027
4027
|
"evalDynamic",
|
|
4028
4028
|
"pipeChainHigh"
|
|
4029
4029
|
];
|
|
4030
|
+
var CLASS_B_COMMAND_CHECKS = /* @__PURE__ */ new Set([
|
|
4031
|
+
"evalDynamic",
|
|
4032
|
+
"pipeChainHigh"
|
|
4033
|
+
]);
|
|
4030
4034
|
function applyManagedCommandChecks(local, managed, locked) {
|
|
4031
4035
|
const next = { ...local };
|
|
4032
4036
|
for (const key of COMMAND_CHECK_KEYS) {
|
|
@@ -4036,7 +4040,7 @@ function applyManagedCommandChecks(local, managed, locked) {
|
|
|
4036
4040
|
const resolved = floorValue(COMMAND_CHECK_ORDER, local[key], m, {
|
|
4037
4041
|
locked: locked.includes(lockKey)
|
|
4038
4042
|
});
|
|
4039
|
-
if ((key
|
|
4043
|
+
if (CLASS_B_COMMAND_CHECKS.has(key) && resolved === "off") continue;
|
|
4040
4044
|
next[key] = resolved;
|
|
4041
4045
|
}
|
|
4042
4046
|
return next;
|
|
@@ -4177,6 +4181,7 @@ var DANGEROUS_WORDS = [
|
|
|
4177
4181
|
];
|
|
4178
4182
|
var DEFAULT_CONFIG = {
|
|
4179
4183
|
version: "1.0",
|
|
4184
|
+
policySource: "local",
|
|
4180
4185
|
settings: {
|
|
4181
4186
|
mode: "standard",
|
|
4182
4187
|
autoStartDaemon: true,
|
|
@@ -4440,13 +4445,15 @@ function getCredentials() {
|
|
|
4440
4445
|
if (profile?.apiKey) {
|
|
4441
4446
|
return {
|
|
4442
4447
|
apiKey: profile.apiKey,
|
|
4443
|
-
apiUrl: profile.apiUrl || DEFAULT_API_URL
|
|
4448
|
+
apiUrl: profile.apiUrl || DEFAULT_API_URL,
|
|
4449
|
+
localOnly: profile.localOnly === true || profileName !== "default"
|
|
4444
4450
|
};
|
|
4445
4451
|
}
|
|
4446
4452
|
if (creds.apiKey) {
|
|
4447
4453
|
return {
|
|
4448
4454
|
apiKey: creds.apiKey,
|
|
4449
|
-
apiUrl: creds.apiUrl || DEFAULT_API_URL
|
|
4455
|
+
apiUrl: creds.apiUrl || DEFAULT_API_URL,
|
|
4456
|
+
localOnly: creds.localOnly === true
|
|
4450
4457
|
};
|
|
4451
4458
|
}
|
|
4452
4459
|
}
|
|
@@ -4558,22 +4565,16 @@ function getConfig(cwd) {
|
|
|
4558
4565
|
const i = COMMAND_CHECK_ORDER.indexOf(v ?? "");
|
|
4559
4566
|
return i === -1 ? 1 : i;
|
|
4560
4567
|
};
|
|
4561
|
-
const
|
|
4568
|
+
const pr2Creds = getCredentials();
|
|
4569
|
+
const keyed = !!pr2Creds?.apiKey && pr2Creds.localOnly !== true;
|
|
4570
|
+
const applyLayer = (source, isProject = false, isCloud = false) => {
|
|
4562
4571
|
if (!source) return;
|
|
4563
4572
|
const s = source.settings || {};
|
|
4564
4573
|
const p = source.policy || {};
|
|
4565
|
-
if (s.mode !== void 0) mergedSettings.mode = s.mode;
|
|
4566
4574
|
if (s.autoStartDaemon !== void 0) mergedSettings.autoStartDaemon = s.autoStartDaemon;
|
|
4567
4575
|
if (s.enableHookLogDebug !== void 0)
|
|
4568
4576
|
mergedSettings.enableHookLogDebug = s.enableHookLogDebug;
|
|
4569
|
-
if (s.approvers) mergedSettings.approvers = { ...mergedSettings.approvers, ...s.approvers };
|
|
4570
4577
|
if (s.shipper) mergedSettings.shipper = { ...mergedSettings.shipper, ...s.shipper };
|
|
4571
|
-
if (s.approvalTimeoutMs !== void 0) mergedSettings.approvalTimeoutMs = s.approvalTimeoutMs;
|
|
4572
|
-
if (s.approvalTimeoutSeconds !== void 0 && s.approvalTimeoutMs === void 0)
|
|
4573
|
-
mergedSettings.approvalTimeoutMs = s.approvalTimeoutSeconds * 1e3;
|
|
4574
|
-
if (s.environment !== void 0) mergedSettings.environment = s.environment;
|
|
4575
|
-
if (s.reviewChannel !== void 0) mergedSettings.reviewChannel = s.reviewChannel;
|
|
4576
|
-
if (s.mcpAllowWeakening !== void 0) mergedSettings.mcpAllowWeakening = s.mcpAllowWeakening;
|
|
4577
4578
|
if (s.cloudSyncIntervalHours !== void 0)
|
|
4578
4579
|
mergedSettings.cloudSyncIntervalHours = s.cloudSyncIntervalHours;
|
|
4579
4580
|
if (s.mcpAutoWrap !== void 0) mergedSettings.mcpAutoWrap = s.mcpAutoWrap === true;
|
|
@@ -4581,6 +4582,15 @@ function getConfig(cwd) {
|
|
|
4581
4582
|
mergedSettings.mcpReconcileIntervalMinutes = s.mcpReconcileIntervalMinutes;
|
|
4582
4583
|
if (s.mcpStaleAfterDays !== void 0) mergedSettings.mcpStaleAfterDays = s.mcpStaleAfterDays;
|
|
4583
4584
|
if (s.hud !== void 0) mergedSettings.hud = { ...mergedSettings.hud, ...s.hud };
|
|
4585
|
+
if (keyed && !isCloud) return;
|
|
4586
|
+
if (s.mode !== void 0) mergedSettings.mode = s.mode;
|
|
4587
|
+
if (s.approvers) mergedSettings.approvers = { ...mergedSettings.approvers, ...s.approvers };
|
|
4588
|
+
if (s.approvalTimeoutMs !== void 0) mergedSettings.approvalTimeoutMs = s.approvalTimeoutMs;
|
|
4589
|
+
if (s.approvalTimeoutSeconds !== void 0 && s.approvalTimeoutMs === void 0)
|
|
4590
|
+
mergedSettings.approvalTimeoutMs = s.approvalTimeoutSeconds * 1e3;
|
|
4591
|
+
if (s.environment !== void 0) mergedSettings.environment = s.environment;
|
|
4592
|
+
if (s.reviewChannel !== void 0) mergedSettings.reviewChannel = s.reviewChannel;
|
|
4593
|
+
if (s.mcpAllowWeakening !== void 0) mergedSettings.mcpAllowWeakening = s.mcpAllowWeakening;
|
|
4584
4594
|
if (p.sandboxPaths) mergedPolicy.sandboxPaths.push(...p.sandboxPaths);
|
|
4585
4595
|
if (p.ignoredTools) mergedPolicy.ignoredTools.push(...p.ignoredTools);
|
|
4586
4596
|
if (p.dangerousWords) mergedPolicy.dangerousWords = [...p.dangerousWords];
|
|
@@ -4688,6 +4698,9 @@ function getConfig(cwd) {
|
|
|
4688
4698
|
/* isProject */
|
|
4689
4699
|
true
|
|
4690
4700
|
);
|
|
4701
|
+
if (keyed) {
|
|
4702
|
+
mergedSettings.approvers = { ...mergedSettings.approvers, cloud: true };
|
|
4703
|
+
}
|
|
4691
4704
|
let cloudManagedShields = [];
|
|
4692
4705
|
const managedCommandCheckKeys = /* @__PURE__ */ new Set();
|
|
4693
4706
|
const lockedCommandCheckKeys = /* @__PURE__ */ new Set();
|
|
@@ -4700,7 +4713,12 @@ function getConfig(cwd) {
|
|
|
4700
4713
|
try {
|
|
4701
4714
|
const raw = readRulesCacheResilient(cacheFile);
|
|
4702
4715
|
if (Array.isArray(raw.rules) && raw.rules.length > 0) {
|
|
4703
|
-
applyLayer(
|
|
4716
|
+
applyLayer(
|
|
4717
|
+
{ policy: { smartRules: raw.rules } },
|
|
4718
|
+
false,
|
|
4719
|
+
/* isCloud */
|
|
4720
|
+
true
|
|
4721
|
+
);
|
|
4704
4722
|
}
|
|
4705
4723
|
if (Array.isArray(raw.shields)) {
|
|
4706
4724
|
cloudManagedShields = raw.shields.filter((s) => typeof s === "string");
|
|
@@ -4709,47 +4727,85 @@ function getConfig(cwd) {
|
|
|
4709
4727
|
const mc = raw.managedConfig;
|
|
4710
4728
|
const locked = Array.isArray(mc.locked) ? mc.locked.filter((f) => typeof f === "string") : [];
|
|
4711
4729
|
if (typeof mc.mode === "string") {
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4730
|
+
if (keyed) {
|
|
4731
|
+
if (["observe", "audit", "standard", "strict"].includes(mc.mode)) {
|
|
4732
|
+
mergedSettings.mode = mc.mode;
|
|
4733
|
+
}
|
|
4734
|
+
} else {
|
|
4735
|
+
mergedSettings.mode = resolveManagedMode(
|
|
4736
|
+
mergedSettings.mode,
|
|
4737
|
+
mc.mode,
|
|
4738
|
+
locked.includes("mode")
|
|
4739
|
+
);
|
|
4740
|
+
}
|
|
4717
4741
|
}
|
|
4718
4742
|
if (typeof mc.mode === "string" || locked.includes("mode")) {
|
|
4719
4743
|
modeCloudControlled = true;
|
|
4720
4744
|
}
|
|
4721
4745
|
if (mc.egress && typeof mc.egress === "object") {
|
|
4722
4746
|
const hosts = (v) => Array.isArray(v) ? v.filter((h) => typeof h === "string") : void 0;
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4747
|
+
if (keyed) {
|
|
4748
|
+
const e = mc.egress;
|
|
4749
|
+
if (typeof e.enabled === "boolean") mergedPolicy.egress.enabled = e.enabled;
|
|
4750
|
+
if (e.mode === "off" || e.mode === "review" || e.mode === "block")
|
|
4751
|
+
mergedPolicy.egress.mode = e.mode;
|
|
4752
|
+
const allow = hosts(e.allow);
|
|
4753
|
+
if (allow) mergedPolicy.egress.allow = allow;
|
|
4754
|
+
const deny = hosts(e.deny);
|
|
4755
|
+
if (deny) mergedPolicy.egress.deny = deny;
|
|
4756
|
+
if (typeof e.allowPrivate === "boolean")
|
|
4757
|
+
mergedPolicy.egress.allowPrivate = e.allowPrivate;
|
|
4758
|
+
} else {
|
|
4759
|
+
mergedPolicy.egress = applyManagedEgress(
|
|
4760
|
+
mergedPolicy.egress,
|
|
4761
|
+
{
|
|
4762
|
+
enabled: typeof mc.egress.enabled === "boolean" ? mc.egress.enabled : void 0,
|
|
4763
|
+
mode: typeof mc.egress.mode === "string" ? mc.egress.mode : void 0,
|
|
4764
|
+
allow: hosts(mc.egress.allow),
|
|
4765
|
+
deny: hosts(mc.egress.deny),
|
|
4766
|
+
allowPrivate: typeof mc.egress.allowPrivate === "boolean" ? mc.egress.allowPrivate : void 0
|
|
4767
|
+
},
|
|
4768
|
+
locked,
|
|
4769
|
+
egressModeUserSet
|
|
4770
|
+
);
|
|
4771
|
+
}
|
|
4735
4772
|
}
|
|
4736
4773
|
if (mc.dlp && typeof mc.dlp === "object") {
|
|
4737
|
-
|
|
4738
|
-
mergedPolicy.dlp
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4774
|
+
if (keyed) {
|
|
4775
|
+
if (typeof mc.dlp.enabled === "boolean") mergedPolicy.dlp.enabled = mc.dlp.enabled;
|
|
4776
|
+
if (mc.dlp.pii === "off" || mc.dlp.pii === "block") mergedPolicy.dlp.pii = mc.dlp.pii;
|
|
4777
|
+
if (mc.dlp.reviewAction === "review" || mc.dlp.reviewAction === "block")
|
|
4778
|
+
mergedPolicy.dlp.reviewAction = mc.dlp.reviewAction;
|
|
4779
|
+
} else {
|
|
4780
|
+
mergedPolicy.dlp = applyManagedDlp(
|
|
4781
|
+
mergedPolicy.dlp,
|
|
4782
|
+
{
|
|
4783
|
+
enabled: typeof mc.dlp.enabled === "boolean" ? mc.dlp.enabled : void 0,
|
|
4784
|
+
pii: typeof mc.dlp.pii === "string" ? mc.dlp.pii : void 0,
|
|
4785
|
+
reviewAction: mc.dlp.reviewAction === "review" || mc.dlp.reviewAction === "block" ? mc.dlp.reviewAction : void 0
|
|
4786
|
+
},
|
|
4787
|
+
locked
|
|
4788
|
+
);
|
|
4789
|
+
}
|
|
4746
4790
|
}
|
|
4747
4791
|
if (mc.commandChecks && typeof mc.commandChecks === "object") {
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4792
|
+
if (keyed) {
|
|
4793
|
+
const src = mc.commandChecks;
|
|
4794
|
+
const next = { ...mergedPolicy.commandChecks ?? {} };
|
|
4795
|
+
for (const key of COMMAND_CHECK_KEYS) {
|
|
4796
|
+
const val = src[key];
|
|
4797
|
+
if (val !== "off" && val !== "review" && val !== "block") continue;
|
|
4798
|
+
if (val === "off" && CLASS_B_COMMAND_CHECKS.has(key)) continue;
|
|
4799
|
+
next[key] = val;
|
|
4800
|
+
}
|
|
4801
|
+
mergedPolicy.commandChecks = next;
|
|
4802
|
+
} else {
|
|
4803
|
+
mergedPolicy.commandChecks = applyManagedCommandChecks(
|
|
4804
|
+
mergedPolicy.commandChecks ?? {},
|
|
4805
|
+
mc.commandChecks,
|
|
4806
|
+
locked
|
|
4807
|
+
);
|
|
4808
|
+
}
|
|
4753
4809
|
for (const [key, val] of Object.entries(mc.commandChecks)) {
|
|
4754
4810
|
if (typeof val !== "string") continue;
|
|
4755
4811
|
managedCommandCheckKeys.add(key);
|
|
@@ -4846,7 +4902,8 @@ function getConfig(cwd) {
|
|
|
4846
4902
|
}
|
|
4847
4903
|
}
|
|
4848
4904
|
const shieldOverrides = readShieldOverrides();
|
|
4849
|
-
|
|
4905
|
+
if (keyed) mergedPolicy.trustedHostsManaged = true;
|
|
4906
|
+
const activeShieldNames = keyed ? [...new Set(cloudManagedShields)] : [.../* @__PURE__ */ new Set([...readActiveShields(), ...cloudManagedShields])];
|
|
4850
4907
|
const appliedShields = [];
|
|
4851
4908
|
const cloudManagedSet = new Set(cloudManagedShields);
|
|
4852
4909
|
for (const shieldName of activeShieldNames) {
|
|
@@ -4910,7 +4967,9 @@ function getConfig(cwd) {
|
|
|
4910
4967
|
mergedPolicy.smartRules.push(injected);
|
|
4911
4968
|
}
|
|
4912
4969
|
const envMode = process.env.NODE9_MODE;
|
|
4913
|
-
if (envMode && !modeCloudControlled &&
|
|
4970
|
+
if (envMode && !modeCloudControlled && // PR-2: one listening point includes the env var — a keyed machine's
|
|
4971
|
+
// mode comes from the workspace (or the shipped default), never the shell.
|
|
4972
|
+
!keyed && ["observe", "audit", "standard", "strict"].includes(envMode)) {
|
|
4914
4973
|
mergedSettings.mode = envMode;
|
|
4915
4974
|
}
|
|
4916
4975
|
if ((cloudManagedShields.length > 0 || cloudMandatesEnforcement) && !modeCloudControlled && !modeCloudStaged && (mergedSettings.mode === "observe" || mergedSettings.mode === "audit")) {
|
|
@@ -4937,7 +4996,11 @@ function getConfig(cwd) {
|
|
|
4937
4996
|
const result = {
|
|
4938
4997
|
settings: mergedSettings,
|
|
4939
4998
|
policy: mergedPolicy,
|
|
4940
|
-
environments: mergedEnvironments
|
|
4999
|
+
environments: mergedEnvironments,
|
|
5000
|
+
// PR-2 — the one truth introspection reads: which of the two working
|
|
5001
|
+
// modes this machine is in. 'workspace' = keyed, policy from the cloud;
|
|
5002
|
+
// 'local' = the local stack (incl. --local / named-profile keys).
|
|
5003
|
+
policySource: keyed ? "workspace" : "local"
|
|
4941
5004
|
};
|
|
4942
5005
|
if (!cwd) cachedConfig = result;
|
|
4943
5006
|
return result;
|
|
@@ -6483,7 +6546,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
|
|
|
6483
6546
|
} else if (!taintWarning && !appPermReview) {
|
|
6484
6547
|
const toolLower = toolName.toLowerCase();
|
|
6485
6548
|
const isFileTool = toolLower === "read" || toolLower === "grep" || toolLower === "glob" || toolLower === "read_file" || toolLower === "grep_search" || toolLower === "list_files";
|
|
6486
|
-
const activeShields = isFileTool ? readActiveShields() : [];
|
|
6549
|
+
const activeShields = isFileTool ? config.policy.appliedShields ?? readActiveShields() : [];
|
|
6487
6550
|
const managedJail = isFileTool ? config.policy.managedJailPaths ?? [] : [];
|
|
6488
6551
|
if (isFileTool && (activeShields.includes("project-jail") || activeShields.includes(USER_JAIL_SHIELD) || managedJail.length > 0)) {
|
|
6489
6552
|
const argsObj = args && typeof args === "object" && !Array.isArray(args) ? args : {};
|
package/dist/index.mjs
CHANGED
|
@@ -3997,6 +3997,10 @@ var COMMAND_CHECK_KEYS = [
|
|
|
3997
3997
|
"evalDynamic",
|
|
3998
3998
|
"pipeChainHigh"
|
|
3999
3999
|
];
|
|
4000
|
+
var CLASS_B_COMMAND_CHECKS = /* @__PURE__ */ new Set([
|
|
4001
|
+
"evalDynamic",
|
|
4002
|
+
"pipeChainHigh"
|
|
4003
|
+
]);
|
|
4000
4004
|
function applyManagedCommandChecks(local, managed, locked) {
|
|
4001
4005
|
const next = { ...local };
|
|
4002
4006
|
for (const key of COMMAND_CHECK_KEYS) {
|
|
@@ -4006,7 +4010,7 @@ function applyManagedCommandChecks(local, managed, locked) {
|
|
|
4006
4010
|
const resolved = floorValue(COMMAND_CHECK_ORDER, local[key], m, {
|
|
4007
4011
|
locked: locked.includes(lockKey)
|
|
4008
4012
|
});
|
|
4009
|
-
if ((key
|
|
4013
|
+
if (CLASS_B_COMMAND_CHECKS.has(key) && resolved === "off") continue;
|
|
4010
4014
|
next[key] = resolved;
|
|
4011
4015
|
}
|
|
4012
4016
|
return next;
|
|
@@ -4147,6 +4151,7 @@ var DANGEROUS_WORDS = [
|
|
|
4147
4151
|
];
|
|
4148
4152
|
var DEFAULT_CONFIG = {
|
|
4149
4153
|
version: "1.0",
|
|
4154
|
+
policySource: "local",
|
|
4150
4155
|
settings: {
|
|
4151
4156
|
mode: "standard",
|
|
4152
4157
|
autoStartDaemon: true,
|
|
@@ -4410,13 +4415,15 @@ function getCredentials() {
|
|
|
4410
4415
|
if (profile?.apiKey) {
|
|
4411
4416
|
return {
|
|
4412
4417
|
apiKey: profile.apiKey,
|
|
4413
|
-
apiUrl: profile.apiUrl || DEFAULT_API_URL
|
|
4418
|
+
apiUrl: profile.apiUrl || DEFAULT_API_URL,
|
|
4419
|
+
localOnly: profile.localOnly === true || profileName !== "default"
|
|
4414
4420
|
};
|
|
4415
4421
|
}
|
|
4416
4422
|
if (creds.apiKey) {
|
|
4417
4423
|
return {
|
|
4418
4424
|
apiKey: creds.apiKey,
|
|
4419
|
-
apiUrl: creds.apiUrl || DEFAULT_API_URL
|
|
4425
|
+
apiUrl: creds.apiUrl || DEFAULT_API_URL,
|
|
4426
|
+
localOnly: creds.localOnly === true
|
|
4420
4427
|
};
|
|
4421
4428
|
}
|
|
4422
4429
|
}
|
|
@@ -4528,22 +4535,16 @@ function getConfig(cwd) {
|
|
|
4528
4535
|
const i = COMMAND_CHECK_ORDER.indexOf(v ?? "");
|
|
4529
4536
|
return i === -1 ? 1 : i;
|
|
4530
4537
|
};
|
|
4531
|
-
const
|
|
4538
|
+
const pr2Creds = getCredentials();
|
|
4539
|
+
const keyed = !!pr2Creds?.apiKey && pr2Creds.localOnly !== true;
|
|
4540
|
+
const applyLayer = (source, isProject = false, isCloud = false) => {
|
|
4532
4541
|
if (!source) return;
|
|
4533
4542
|
const s = source.settings || {};
|
|
4534
4543
|
const p = source.policy || {};
|
|
4535
|
-
if (s.mode !== void 0) mergedSettings.mode = s.mode;
|
|
4536
4544
|
if (s.autoStartDaemon !== void 0) mergedSettings.autoStartDaemon = s.autoStartDaemon;
|
|
4537
4545
|
if (s.enableHookLogDebug !== void 0)
|
|
4538
4546
|
mergedSettings.enableHookLogDebug = s.enableHookLogDebug;
|
|
4539
|
-
if (s.approvers) mergedSettings.approvers = { ...mergedSettings.approvers, ...s.approvers };
|
|
4540
4547
|
if (s.shipper) mergedSettings.shipper = { ...mergedSettings.shipper, ...s.shipper };
|
|
4541
|
-
if (s.approvalTimeoutMs !== void 0) mergedSettings.approvalTimeoutMs = s.approvalTimeoutMs;
|
|
4542
|
-
if (s.approvalTimeoutSeconds !== void 0 && s.approvalTimeoutMs === void 0)
|
|
4543
|
-
mergedSettings.approvalTimeoutMs = s.approvalTimeoutSeconds * 1e3;
|
|
4544
|
-
if (s.environment !== void 0) mergedSettings.environment = s.environment;
|
|
4545
|
-
if (s.reviewChannel !== void 0) mergedSettings.reviewChannel = s.reviewChannel;
|
|
4546
|
-
if (s.mcpAllowWeakening !== void 0) mergedSettings.mcpAllowWeakening = s.mcpAllowWeakening;
|
|
4547
4548
|
if (s.cloudSyncIntervalHours !== void 0)
|
|
4548
4549
|
mergedSettings.cloudSyncIntervalHours = s.cloudSyncIntervalHours;
|
|
4549
4550
|
if (s.mcpAutoWrap !== void 0) mergedSettings.mcpAutoWrap = s.mcpAutoWrap === true;
|
|
@@ -4551,6 +4552,15 @@ function getConfig(cwd) {
|
|
|
4551
4552
|
mergedSettings.mcpReconcileIntervalMinutes = s.mcpReconcileIntervalMinutes;
|
|
4552
4553
|
if (s.mcpStaleAfterDays !== void 0) mergedSettings.mcpStaleAfterDays = s.mcpStaleAfterDays;
|
|
4553
4554
|
if (s.hud !== void 0) mergedSettings.hud = { ...mergedSettings.hud, ...s.hud };
|
|
4555
|
+
if (keyed && !isCloud) return;
|
|
4556
|
+
if (s.mode !== void 0) mergedSettings.mode = s.mode;
|
|
4557
|
+
if (s.approvers) mergedSettings.approvers = { ...mergedSettings.approvers, ...s.approvers };
|
|
4558
|
+
if (s.approvalTimeoutMs !== void 0) mergedSettings.approvalTimeoutMs = s.approvalTimeoutMs;
|
|
4559
|
+
if (s.approvalTimeoutSeconds !== void 0 && s.approvalTimeoutMs === void 0)
|
|
4560
|
+
mergedSettings.approvalTimeoutMs = s.approvalTimeoutSeconds * 1e3;
|
|
4561
|
+
if (s.environment !== void 0) mergedSettings.environment = s.environment;
|
|
4562
|
+
if (s.reviewChannel !== void 0) mergedSettings.reviewChannel = s.reviewChannel;
|
|
4563
|
+
if (s.mcpAllowWeakening !== void 0) mergedSettings.mcpAllowWeakening = s.mcpAllowWeakening;
|
|
4554
4564
|
if (p.sandboxPaths) mergedPolicy.sandboxPaths.push(...p.sandboxPaths);
|
|
4555
4565
|
if (p.ignoredTools) mergedPolicy.ignoredTools.push(...p.ignoredTools);
|
|
4556
4566
|
if (p.dangerousWords) mergedPolicy.dangerousWords = [...p.dangerousWords];
|
|
@@ -4658,6 +4668,9 @@ function getConfig(cwd) {
|
|
|
4658
4668
|
/* isProject */
|
|
4659
4669
|
true
|
|
4660
4670
|
);
|
|
4671
|
+
if (keyed) {
|
|
4672
|
+
mergedSettings.approvers = { ...mergedSettings.approvers, cloud: true };
|
|
4673
|
+
}
|
|
4661
4674
|
let cloudManagedShields = [];
|
|
4662
4675
|
const managedCommandCheckKeys = /* @__PURE__ */ new Set();
|
|
4663
4676
|
const lockedCommandCheckKeys = /* @__PURE__ */ new Set();
|
|
@@ -4670,7 +4683,12 @@ function getConfig(cwd) {
|
|
|
4670
4683
|
try {
|
|
4671
4684
|
const raw = readRulesCacheResilient(cacheFile);
|
|
4672
4685
|
if (Array.isArray(raw.rules) && raw.rules.length > 0) {
|
|
4673
|
-
applyLayer(
|
|
4686
|
+
applyLayer(
|
|
4687
|
+
{ policy: { smartRules: raw.rules } },
|
|
4688
|
+
false,
|
|
4689
|
+
/* isCloud */
|
|
4690
|
+
true
|
|
4691
|
+
);
|
|
4674
4692
|
}
|
|
4675
4693
|
if (Array.isArray(raw.shields)) {
|
|
4676
4694
|
cloudManagedShields = raw.shields.filter((s) => typeof s === "string");
|
|
@@ -4679,47 +4697,85 @@ function getConfig(cwd) {
|
|
|
4679
4697
|
const mc = raw.managedConfig;
|
|
4680
4698
|
const locked = Array.isArray(mc.locked) ? mc.locked.filter((f) => typeof f === "string") : [];
|
|
4681
4699
|
if (typeof mc.mode === "string") {
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4700
|
+
if (keyed) {
|
|
4701
|
+
if (["observe", "audit", "standard", "strict"].includes(mc.mode)) {
|
|
4702
|
+
mergedSettings.mode = mc.mode;
|
|
4703
|
+
}
|
|
4704
|
+
} else {
|
|
4705
|
+
mergedSettings.mode = resolveManagedMode(
|
|
4706
|
+
mergedSettings.mode,
|
|
4707
|
+
mc.mode,
|
|
4708
|
+
locked.includes("mode")
|
|
4709
|
+
);
|
|
4710
|
+
}
|
|
4687
4711
|
}
|
|
4688
4712
|
if (typeof mc.mode === "string" || locked.includes("mode")) {
|
|
4689
4713
|
modeCloudControlled = true;
|
|
4690
4714
|
}
|
|
4691
4715
|
if (mc.egress && typeof mc.egress === "object") {
|
|
4692
4716
|
const hosts = (v) => Array.isArray(v) ? v.filter((h) => typeof h === "string") : void 0;
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4717
|
+
if (keyed) {
|
|
4718
|
+
const e = mc.egress;
|
|
4719
|
+
if (typeof e.enabled === "boolean") mergedPolicy.egress.enabled = e.enabled;
|
|
4720
|
+
if (e.mode === "off" || e.mode === "review" || e.mode === "block")
|
|
4721
|
+
mergedPolicy.egress.mode = e.mode;
|
|
4722
|
+
const allow = hosts(e.allow);
|
|
4723
|
+
if (allow) mergedPolicy.egress.allow = allow;
|
|
4724
|
+
const deny = hosts(e.deny);
|
|
4725
|
+
if (deny) mergedPolicy.egress.deny = deny;
|
|
4726
|
+
if (typeof e.allowPrivate === "boolean")
|
|
4727
|
+
mergedPolicy.egress.allowPrivate = e.allowPrivate;
|
|
4728
|
+
} else {
|
|
4729
|
+
mergedPolicy.egress = applyManagedEgress(
|
|
4730
|
+
mergedPolicy.egress,
|
|
4731
|
+
{
|
|
4732
|
+
enabled: typeof mc.egress.enabled === "boolean" ? mc.egress.enabled : void 0,
|
|
4733
|
+
mode: typeof mc.egress.mode === "string" ? mc.egress.mode : void 0,
|
|
4734
|
+
allow: hosts(mc.egress.allow),
|
|
4735
|
+
deny: hosts(mc.egress.deny),
|
|
4736
|
+
allowPrivate: typeof mc.egress.allowPrivate === "boolean" ? mc.egress.allowPrivate : void 0
|
|
4737
|
+
},
|
|
4738
|
+
locked,
|
|
4739
|
+
egressModeUserSet
|
|
4740
|
+
);
|
|
4741
|
+
}
|
|
4705
4742
|
}
|
|
4706
4743
|
if (mc.dlp && typeof mc.dlp === "object") {
|
|
4707
|
-
|
|
4708
|
-
mergedPolicy.dlp
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4744
|
+
if (keyed) {
|
|
4745
|
+
if (typeof mc.dlp.enabled === "boolean") mergedPolicy.dlp.enabled = mc.dlp.enabled;
|
|
4746
|
+
if (mc.dlp.pii === "off" || mc.dlp.pii === "block") mergedPolicy.dlp.pii = mc.dlp.pii;
|
|
4747
|
+
if (mc.dlp.reviewAction === "review" || mc.dlp.reviewAction === "block")
|
|
4748
|
+
mergedPolicy.dlp.reviewAction = mc.dlp.reviewAction;
|
|
4749
|
+
} else {
|
|
4750
|
+
mergedPolicy.dlp = applyManagedDlp(
|
|
4751
|
+
mergedPolicy.dlp,
|
|
4752
|
+
{
|
|
4753
|
+
enabled: typeof mc.dlp.enabled === "boolean" ? mc.dlp.enabled : void 0,
|
|
4754
|
+
pii: typeof mc.dlp.pii === "string" ? mc.dlp.pii : void 0,
|
|
4755
|
+
reviewAction: mc.dlp.reviewAction === "review" || mc.dlp.reviewAction === "block" ? mc.dlp.reviewAction : void 0
|
|
4756
|
+
},
|
|
4757
|
+
locked
|
|
4758
|
+
);
|
|
4759
|
+
}
|
|
4716
4760
|
}
|
|
4717
4761
|
if (mc.commandChecks && typeof mc.commandChecks === "object") {
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4762
|
+
if (keyed) {
|
|
4763
|
+
const src = mc.commandChecks;
|
|
4764
|
+
const next = { ...mergedPolicy.commandChecks ?? {} };
|
|
4765
|
+
for (const key of COMMAND_CHECK_KEYS) {
|
|
4766
|
+
const val = src[key];
|
|
4767
|
+
if (val !== "off" && val !== "review" && val !== "block") continue;
|
|
4768
|
+
if (val === "off" && CLASS_B_COMMAND_CHECKS.has(key)) continue;
|
|
4769
|
+
next[key] = val;
|
|
4770
|
+
}
|
|
4771
|
+
mergedPolicy.commandChecks = next;
|
|
4772
|
+
} else {
|
|
4773
|
+
mergedPolicy.commandChecks = applyManagedCommandChecks(
|
|
4774
|
+
mergedPolicy.commandChecks ?? {},
|
|
4775
|
+
mc.commandChecks,
|
|
4776
|
+
locked
|
|
4777
|
+
);
|
|
4778
|
+
}
|
|
4723
4779
|
for (const [key, val] of Object.entries(mc.commandChecks)) {
|
|
4724
4780
|
if (typeof val !== "string") continue;
|
|
4725
4781
|
managedCommandCheckKeys.add(key);
|
|
@@ -4816,7 +4872,8 @@ function getConfig(cwd) {
|
|
|
4816
4872
|
}
|
|
4817
4873
|
}
|
|
4818
4874
|
const shieldOverrides = readShieldOverrides();
|
|
4819
|
-
|
|
4875
|
+
if (keyed) mergedPolicy.trustedHostsManaged = true;
|
|
4876
|
+
const activeShieldNames = keyed ? [...new Set(cloudManagedShields)] : [.../* @__PURE__ */ new Set([...readActiveShields(), ...cloudManagedShields])];
|
|
4820
4877
|
const appliedShields = [];
|
|
4821
4878
|
const cloudManagedSet = new Set(cloudManagedShields);
|
|
4822
4879
|
for (const shieldName of activeShieldNames) {
|
|
@@ -4880,7 +4937,9 @@ function getConfig(cwd) {
|
|
|
4880
4937
|
mergedPolicy.smartRules.push(injected);
|
|
4881
4938
|
}
|
|
4882
4939
|
const envMode = process.env.NODE9_MODE;
|
|
4883
|
-
if (envMode && !modeCloudControlled &&
|
|
4940
|
+
if (envMode && !modeCloudControlled && // PR-2: one listening point includes the env var — a keyed machine's
|
|
4941
|
+
// mode comes from the workspace (or the shipped default), never the shell.
|
|
4942
|
+
!keyed && ["observe", "audit", "standard", "strict"].includes(envMode)) {
|
|
4884
4943
|
mergedSettings.mode = envMode;
|
|
4885
4944
|
}
|
|
4886
4945
|
if ((cloudManagedShields.length > 0 || cloudMandatesEnforcement) && !modeCloudControlled && !modeCloudStaged && (mergedSettings.mode === "observe" || mergedSettings.mode === "audit")) {
|
|
@@ -4907,7 +4966,11 @@ function getConfig(cwd) {
|
|
|
4907
4966
|
const result = {
|
|
4908
4967
|
settings: mergedSettings,
|
|
4909
4968
|
policy: mergedPolicy,
|
|
4910
|
-
environments: mergedEnvironments
|
|
4969
|
+
environments: mergedEnvironments,
|
|
4970
|
+
// PR-2 — the one truth introspection reads: which of the two working
|
|
4971
|
+
// modes this machine is in. 'workspace' = keyed, policy from the cloud;
|
|
4972
|
+
// 'local' = the local stack (incl. --local / named-profile keys).
|
|
4973
|
+
policySource: keyed ? "workspace" : "local"
|
|
4911
4974
|
};
|
|
4912
4975
|
if (!cwd) cachedConfig = result;
|
|
4913
4976
|
return result;
|
|
@@ -6453,7 +6516,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
|
|
|
6453
6516
|
} else if (!taintWarning && !appPermReview) {
|
|
6454
6517
|
const toolLower = toolName.toLowerCase();
|
|
6455
6518
|
const isFileTool = toolLower === "read" || toolLower === "grep" || toolLower === "glob" || toolLower === "read_file" || toolLower === "grep_search" || toolLower === "list_files";
|
|
6456
|
-
const activeShields = isFileTool ? readActiveShields() : [];
|
|
6519
|
+
const activeShields = isFileTool ? config.policy.appliedShields ?? readActiveShields() : [];
|
|
6457
6520
|
const managedJail = isFileTool ? config.policy.managedJailPaths ?? [] : [];
|
|
6458
6521
|
if (isFileTool && (activeShields.includes("project-jail") || activeShields.includes(USER_JAIL_SHIELD) || managedJail.length > 0)) {
|
|
6459
6522
|
const argsObj = args && typeof args === "object" && !Array.isArray(args) ? args : {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@node9/proxy",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.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",
|
|
@@ -70,7 +70,9 @@
|
|
|
70
70
|
"bump-extractor-version": "node scripts/check-extractor-version.mjs --bump",
|
|
71
71
|
"fix": "npm run format && npm run lint:fix",
|
|
72
72
|
"validate": "npm run format && npm run lint && npm run typecheck && npm run test && npm run test:e2e && npm run build",
|
|
73
|
+
"pretest:e2e": "npm run build",
|
|
73
74
|
"test:e2e": "cross-env NODE9_TESTING=1 bash scripts/e2e.sh",
|
|
75
|
+
"pretest": "npm run build",
|
|
74
76
|
"test": "cross-env NODE9_TESTING=1 vitest --run",
|
|
75
77
|
"test:coverage": "cross-env NODE9_TESTING=1 vitest --run --coverage",
|
|
76
78
|
"test:watch": "cross-env NODE9_TESTING=1 vitest",
|