@node9/proxy 2.45.0 → 2.46.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/dist/cli.js +8644 -8729
- package/dist/cli.mjs +8629 -8714
- package/dist/dashboard.mjs +395 -314
- package/package.json +1 -1
package/dist/dashboard.mjs
CHANGED
|
@@ -18747,79 +18747,6 @@ var init_credential_files = __esm({
|
|
|
18747
18747
|
}
|
|
18748
18748
|
});
|
|
18749
18749
|
|
|
18750
|
-
// src/cli/commands/blast.ts
|
|
18751
|
-
import chalk from "chalk";
|
|
18752
|
-
import fs5 from "fs";
|
|
18753
|
-
import path6 from "path";
|
|
18754
|
-
import os4 from "os";
|
|
18755
|
-
function buildSensitivePaths(home, cwd) {
|
|
18756
|
-
const homeFiles = homeCredentialFiles(home).map(({ full, label: label2, description, score }) => ({
|
|
18757
|
-
full,
|
|
18758
|
-
label: label2,
|
|
18759
|
-
description,
|
|
18760
|
-
score
|
|
18761
|
-
}));
|
|
18762
|
-
return [
|
|
18763
|
-
...homeFiles,
|
|
18764
|
-
{
|
|
18765
|
-
full: path6.join(cwd, ".env"),
|
|
18766
|
-
label: ".env (current folder)",
|
|
18767
|
-
description: "App secrets: database passwords, API keys",
|
|
18768
|
-
score: 20
|
|
18769
|
-
},
|
|
18770
|
-
{
|
|
18771
|
-
full: path6.join(cwd, ".env.local"),
|
|
18772
|
-
label: ".env.local (current folder)",
|
|
18773
|
-
description: "Local overrides: often contains real credentials",
|
|
18774
|
-
score: 15
|
|
18775
|
-
},
|
|
18776
|
-
{
|
|
18777
|
-
full: path6.join(cwd, ".env.production"),
|
|
18778
|
-
label: ".env.production (current folder)",
|
|
18779
|
-
description: "Production secrets",
|
|
18780
|
-
score: 20
|
|
18781
|
-
}
|
|
18782
|
-
];
|
|
18783
|
-
}
|
|
18784
|
-
function isReadable(filePath) {
|
|
18785
|
-
try {
|
|
18786
|
-
fs5.accessSync(filePath, fs5.constants.R_OK);
|
|
18787
|
-
return true;
|
|
18788
|
-
} catch {
|
|
18789
|
-
return false;
|
|
18790
|
-
}
|
|
18791
|
-
}
|
|
18792
|
-
function runBlast() {
|
|
18793
|
-
const home = os4.homedir();
|
|
18794
|
-
const cwd = process.cwd();
|
|
18795
|
-
const paths = buildSensitivePaths(home, cwd);
|
|
18796
|
-
let scoreDeduction = 0;
|
|
18797
|
-
const reachable = [];
|
|
18798
|
-
for (const p of paths) {
|
|
18799
|
-
if (fs5.existsSync(p.full) && isReadable(p.full)) {
|
|
18800
|
-
reachable.push(p);
|
|
18801
|
-
scoreDeduction += p.score;
|
|
18802
|
-
}
|
|
18803
|
-
}
|
|
18804
|
-
const envFindings = [];
|
|
18805
|
-
for (const [key, value] of Object.entries(process.env)) {
|
|
18806
|
-
if (!value) continue;
|
|
18807
|
-
const match = scanArgs({ [key]: value });
|
|
18808
|
-
if (match) {
|
|
18809
|
-
envFindings.push({ key, patternName: match.patternName });
|
|
18810
|
-
scoreDeduction += 10;
|
|
18811
|
-
}
|
|
18812
|
-
}
|
|
18813
|
-
return { reachable, envFindings, score: Math.max(0, 100 - scoreDeduction) };
|
|
18814
|
-
}
|
|
18815
|
-
var init_blast = __esm({
|
|
18816
|
-
"src/cli/commands/blast.ts"() {
|
|
18817
|
-
"use strict";
|
|
18818
|
-
init_dlp();
|
|
18819
|
-
init_credential_files();
|
|
18820
|
-
}
|
|
18821
|
-
});
|
|
18822
|
-
|
|
18823
18750
|
// src/mcp-cmd.ts
|
|
18824
18751
|
var init_mcp_cmd = __esm({
|
|
18825
18752
|
"src/mcp-cmd.ts"() {
|
|
@@ -18872,14 +18799,14 @@ var init_codex_trust = __esm({
|
|
|
18872
18799
|
});
|
|
18873
18800
|
|
|
18874
18801
|
// src/daemon/hook-baseline.ts
|
|
18875
|
-
import
|
|
18876
|
-
import
|
|
18802
|
+
import path6 from "path";
|
|
18803
|
+
import os4 from "os";
|
|
18877
18804
|
var BASELINE_FILE, NOTIFIED_FILE;
|
|
18878
18805
|
var init_hook_baseline = __esm({
|
|
18879
18806
|
"src/daemon/hook-baseline.ts"() {
|
|
18880
18807
|
"use strict";
|
|
18881
|
-
BASELINE_FILE =
|
|
18882
|
-
NOTIFIED_FILE =
|
|
18808
|
+
BASELINE_FILE = path6.join(os4.homedir(), ".node9", "hooks-baseline.json");
|
|
18809
|
+
NOTIFIED_FILE = path6.join(os4.homedir(), ".node9", "hook-heal-notified.json");
|
|
18883
18810
|
}
|
|
18884
18811
|
});
|
|
18885
18812
|
|
|
@@ -18898,27 +18825,27 @@ var init_setup_pi_shim = __esm({
|
|
|
18898
18825
|
});
|
|
18899
18826
|
|
|
18900
18827
|
// src/utils/atomic-write.ts
|
|
18901
|
-
import
|
|
18902
|
-
import
|
|
18828
|
+
import fs5 from "fs";
|
|
18829
|
+
import path7 from "path";
|
|
18903
18830
|
import { randomUUID } from "crypto";
|
|
18904
18831
|
function atomicWriteSync(filePath, data, options) {
|
|
18905
|
-
const dir2 =
|
|
18906
|
-
if (!
|
|
18832
|
+
const dir2 = path7.dirname(filePath);
|
|
18833
|
+
if (!fs5.existsSync(dir2)) fs5.mkdirSync(dir2, { recursive: true });
|
|
18907
18834
|
const tmpPath = `${filePath}.${randomUUID()}.tmp`;
|
|
18908
18835
|
try {
|
|
18909
|
-
|
|
18836
|
+
fs5.writeFileSync(tmpPath, data, options);
|
|
18910
18837
|
} catch (err) {
|
|
18911
18838
|
try {
|
|
18912
|
-
|
|
18839
|
+
fs5.unlinkSync(tmpPath);
|
|
18913
18840
|
} catch {
|
|
18914
18841
|
}
|
|
18915
18842
|
throw err;
|
|
18916
18843
|
}
|
|
18917
18844
|
try {
|
|
18918
|
-
|
|
18845
|
+
fs5.renameSync(tmpPath, filePath);
|
|
18919
18846
|
} catch (err) {
|
|
18920
18847
|
try {
|
|
18921
|
-
|
|
18848
|
+
fs5.unlinkSync(tmpPath);
|
|
18922
18849
|
} catch {
|
|
18923
18850
|
}
|
|
18924
18851
|
throw err;
|
|
@@ -18931,10 +18858,10 @@ var init_atomic_write = __esm({
|
|
|
18931
18858
|
});
|
|
18932
18859
|
|
|
18933
18860
|
// src/setup.ts
|
|
18934
|
-
import
|
|
18935
|
-
import
|
|
18936
|
-
import
|
|
18937
|
-
import
|
|
18861
|
+
import fs6 from "fs";
|
|
18862
|
+
import path8 from "path";
|
|
18863
|
+
import os5 from "os";
|
|
18864
|
+
import chalk from "chalk";
|
|
18938
18865
|
import { confirm as rawConfirm } from "@inquirer/prompts";
|
|
18939
18866
|
import { parse as parseToml4, stringify as stringifyToml2 } from "smol-toml";
|
|
18940
18867
|
import * as yaml from "yaml";
|
|
@@ -18946,9 +18873,9 @@ function isNode9Hook(cmd) {
|
|
|
18946
18873
|
// fell into after #185.
|
|
18947
18874
|
/[/\\]\.node9[/\\]bin[/\\]hook"? (?:check|log)/.test(cmd);
|
|
18948
18875
|
}
|
|
18949
|
-
function claudeDesktopConfigPath(homeDir =
|
|
18876
|
+
function claudeDesktopConfigPath(homeDir = os5.homedir()) {
|
|
18950
18877
|
if (process.platform === "darwin") {
|
|
18951
|
-
return
|
|
18878
|
+
return path8.join(
|
|
18952
18879
|
homeDir,
|
|
18953
18880
|
"Library",
|
|
18954
18881
|
"Application Support",
|
|
@@ -18957,47 +18884,47 @@ function claudeDesktopConfigPath(homeDir = os6.homedir()) {
|
|
|
18957
18884
|
);
|
|
18958
18885
|
}
|
|
18959
18886
|
if (process.platform === "linux") {
|
|
18960
|
-
return
|
|
18887
|
+
return path8.join(homeDir, ".config", "Claude", "claude_desktop_config.json");
|
|
18961
18888
|
}
|
|
18962
18889
|
if (process.platform === "win32") {
|
|
18963
|
-
const appData = process.env.APPDATA ||
|
|
18964
|
-
return
|
|
18890
|
+
const appData = process.env.APPDATA || path8.join(homeDir, "AppData", "Roaming");
|
|
18891
|
+
return path8.join(appData, "Claude", "claude_desktop_config.json");
|
|
18965
18892
|
}
|
|
18966
18893
|
return null;
|
|
18967
18894
|
}
|
|
18968
|
-
function opencodeConfigDir(home =
|
|
18895
|
+
function opencodeConfigDir(home = os5.homedir()) {
|
|
18969
18896
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
18970
|
-
const base2 = xdg &&
|
|
18971
|
-
return
|
|
18897
|
+
const base2 = xdg && path8.isAbsolute(xdg) ? xdg : path8.join(home, ".config");
|
|
18898
|
+
return path8.join(base2, "opencode");
|
|
18972
18899
|
}
|
|
18973
18900
|
function commonBinDirs(home) {
|
|
18974
18901
|
return [
|
|
18975
|
-
|
|
18976
|
-
|
|
18977
|
-
|
|
18902
|
+
path8.join(home, ".local", "bin"),
|
|
18903
|
+
path8.join(home, ".bun", "bin"),
|
|
18904
|
+
path8.join(home, ".npm-global", "bin"),
|
|
18978
18905
|
"/usr/local/bin",
|
|
18979
18906
|
"/opt/homebrew/bin"
|
|
18980
18907
|
];
|
|
18981
18908
|
}
|
|
18982
|
-
function binaryInPath(binary, home =
|
|
18909
|
+
function binaryInPath(binary, home = os5.homedir()) {
|
|
18983
18910
|
const pathEnv = process.env.PATH ?? "";
|
|
18984
|
-
const dirs = [...pathEnv.split(
|
|
18911
|
+
const dirs = [...pathEnv.split(path8.delimiter), ...commonBinDirs(home)];
|
|
18985
18912
|
const seen = /* @__PURE__ */ new Set();
|
|
18986
18913
|
for (const dir2 of dirs) {
|
|
18987
18914
|
if (!dir2 || seen.has(dir2)) continue;
|
|
18988
18915
|
seen.add(dir2);
|
|
18989
18916
|
try {
|
|
18990
|
-
|
|
18917
|
+
fs6.accessSync(path8.join(dir2, binary), fs6.constants.X_OK);
|
|
18991
18918
|
return true;
|
|
18992
18919
|
} catch {
|
|
18993
18920
|
}
|
|
18994
18921
|
}
|
|
18995
18922
|
return false;
|
|
18996
18923
|
}
|
|
18997
|
-
function detectAgents(homeDir =
|
|
18924
|
+
function detectAgents(homeDir = os5.homedir()) {
|
|
18998
18925
|
const exists2 = (p) => {
|
|
18999
18926
|
try {
|
|
19000
|
-
return
|
|
18927
|
+
return fs6.existsSync(p);
|
|
19001
18928
|
} catch (err) {
|
|
19002
18929
|
const code = err.code;
|
|
19003
18930
|
if (code !== "ENOENT") {
|
|
@@ -19009,7 +18936,7 @@ function detectAgents(homeDir = os6.homedir()) {
|
|
|
19009
18936
|
};
|
|
19010
18937
|
const desktopPath = claudeDesktopConfigPath(homeDir);
|
|
19011
18938
|
return {
|
|
19012
|
-
claude: exists2(
|
|
18939
|
+
claude: exists2(path8.join(homeDir, ".claude")) || exists2(path8.join(homeDir, ".claude.json")),
|
|
19013
18940
|
// Antigravity (agy) shares the ~/.gemini root, so a bare
|
|
19014
18941
|
// `exists(~/.gemini)` would report the (EOL'd) Gemini CLI as
|
|
19015
18942
|
// installed on every agy machine — and `node9 init` would then
|
|
@@ -19019,19 +18946,19 @@ function detectAgents(homeDir = os6.homedir()) {
|
|
|
19019
18946
|
// creates ~/.gemini/settings.json on first run; agy does not touch
|
|
19020
18947
|
// it (it uses antigravity-cli/settings.json) — that file is the
|
|
19021
18948
|
// legacy-CLI discriminator.
|
|
19022
|
-
gemini: exists2(
|
|
18949
|
+
gemini: exists2(path8.join(homeDir, ".gemini", "settings.json")) || binaryInPath("gemini", homeDir),
|
|
19023
18950
|
// agy creates ~/.gemini/antigravity-cli/ on first launch; the IDE
|
|
19024
18951
|
// creates antigravity-ide/. PATH fallback covers installed-but-
|
|
19025
18952
|
// never-launched (same class as opencode #186).
|
|
19026
|
-
antigravity: exists2(
|
|
18953
|
+
antigravity: exists2(path8.join(homeDir, ".gemini", "antigravity-cli")) || exists2(path8.join(homeDir, ".gemini", "antigravity-ide")) || binaryInPath("agy", homeDir),
|
|
19027
18954
|
// GitHub Copilot CLI creates ~/.copilot on first launch; PATH
|
|
19028
18955
|
// fallback covers installed-but-never-launched (same as opencode #186).
|
|
19029
|
-
copilot: exists2(
|
|
19030
|
-
cursor: exists2(
|
|
19031
|
-
codex: exists2(
|
|
19032
|
-
windsurf: exists2(
|
|
19033
|
-
vscode: exists2(
|
|
19034
|
-
claudeDesktop: desktopPath !== null && exists2(
|
|
18956
|
+
copilot: exists2(path8.join(homeDir, ".copilot")) || binaryInPath("copilot", homeDir),
|
|
18957
|
+
cursor: exists2(path8.join(homeDir, ".cursor")),
|
|
18958
|
+
codex: exists2(path8.join(homeDir, ".codex")),
|
|
18959
|
+
windsurf: exists2(path8.join(homeDir, ".codeium", "windsurf")),
|
|
18960
|
+
vscode: exists2(path8.join(homeDir, ".vscode")),
|
|
18961
|
+
claudeDesktop: desktopPath !== null && exists2(path8.dirname(desktopPath)),
|
|
19035
18962
|
// Opencode creates its config dir lazily on first launch — fall back to a
|
|
19036
18963
|
// PATH lookup so installed-but-never-launched CLIs are still wired. Config
|
|
19037
18964
|
// dir honors $XDG_CONFIG_HOME via opencodeConfigDir (#186, custom-XDG).
|
|
@@ -19042,7 +18969,7 @@ function detectAgents(homeDir = os6.homedir()) {
|
|
|
19042
18969
|
// dir lazily on first launch — same class of bug as opencode's #186
|
|
19043
18970
|
// (design R6) — so fall back to PATH lookup for installed-but-never-
|
|
19044
18971
|
// launched pi.
|
|
19045
|
-
pi: exists2(
|
|
18972
|
+
pi: exists2(path8.join(homeDir, ".pi", "agent")) || binaryInPath("pi", homeDir),
|
|
19046
18973
|
// Hermes Agent (https://github.com/NousResearch/hermes-agent): home dir
|
|
19047
18974
|
// is $HERMES_HOME (default ~/.hermes) per hermes_constants.py:30. config.yaml
|
|
19048
18975
|
// appears after `hermes setup` has run; the directory alone exists from
|
|
@@ -19051,13 +18978,13 @@ function detectAgents(homeDir = os6.homedir()) {
|
|
|
19051
18978
|
hermes: exists2(hermesHomeDir(homeDir)) || binaryInPath("hermes", homeDir)
|
|
19052
18979
|
};
|
|
19053
18980
|
}
|
|
19054
|
-
function hermesHomeDir(homeDir =
|
|
18981
|
+
function hermesHomeDir(homeDir = os5.homedir()) {
|
|
19055
18982
|
const env = process.env.HERMES_HOME?.trim();
|
|
19056
|
-
if (env &&
|
|
19057
|
-
return
|
|
18983
|
+
if (env && path8.isAbsolute(env)) return env;
|
|
18984
|
+
return path8.join(homeDir, ".hermes");
|
|
19058
18985
|
}
|
|
19059
|
-
function hermesConfigPath(homeDir =
|
|
19060
|
-
return
|
|
18986
|
+
function hermesConfigPath(homeDir = os5.homedir()) {
|
|
18987
|
+
return path8.join(hermesHomeDir(homeDir), HERMES_CONFIG_FILENAME);
|
|
19061
18988
|
}
|
|
19062
18989
|
var HERMES_CONFIG_FILENAME;
|
|
19063
18990
|
var init_setup = __esm({
|
|
@@ -19076,15 +19003,15 @@ var init_setup = __esm({
|
|
|
19076
19003
|
});
|
|
19077
19004
|
|
|
19078
19005
|
// src/agent-wiring.ts
|
|
19079
|
-
import
|
|
19080
|
-
import
|
|
19081
|
-
import
|
|
19006
|
+
import fs7 from "fs";
|
|
19007
|
+
import path9 from "path";
|
|
19008
|
+
import os6 from "os";
|
|
19082
19009
|
import * as yaml2 from "yaml";
|
|
19083
19010
|
import { parse as parseToml5 } from "smol-toml";
|
|
19084
19011
|
function readJson(filePath) {
|
|
19085
|
-
if (!
|
|
19012
|
+
if (!fs7.existsSync(filePath)) return null;
|
|
19086
19013
|
try {
|
|
19087
|
-
return JSON.parse(
|
|
19014
|
+
return JSON.parse(fs7.readFileSync(filePath, "utf-8"));
|
|
19088
19015
|
} catch {
|
|
19089
19016
|
return "invalid";
|
|
19090
19017
|
}
|
|
@@ -19096,10 +19023,10 @@ function flatHaveNode9Hook(entries) {
|
|
|
19096
19023
|
return (Array.isArray(entries) ? entries : []).some((h) => isNode9Hook(h.command));
|
|
19097
19024
|
}
|
|
19098
19025
|
function readHookRoot(filePath, format) {
|
|
19099
|
-
if (!
|
|
19026
|
+
if (!fs7.existsSync(filePath)) return "absent";
|
|
19100
19027
|
let raw;
|
|
19101
19028
|
try {
|
|
19102
|
-
raw =
|
|
19029
|
+
raw = fs7.readFileSync(filePath, "utf-8");
|
|
19103
19030
|
} catch {
|
|
19104
19031
|
return "absent";
|
|
19105
19032
|
}
|
|
@@ -19122,20 +19049,20 @@ function detectMcp(servers) {
|
|
|
19122
19049
|
return { wrapped, present };
|
|
19123
19050
|
}
|
|
19124
19051
|
function readMcp(filePath, format) {
|
|
19125
|
-
if (!
|
|
19052
|
+
if (!fs7.existsSync(filePath)) return { wrapped: [], present: false };
|
|
19126
19053
|
try {
|
|
19127
19054
|
if (format === "toml") {
|
|
19128
|
-
const parsed2 = parseToml5(
|
|
19055
|
+
const parsed2 = parseToml5(fs7.readFileSync(filePath, "utf-8"));
|
|
19129
19056
|
return detectMcp(parsed2?.mcp_servers);
|
|
19130
19057
|
}
|
|
19131
19058
|
const parsed = readJson(filePath);
|
|
19132
19059
|
if (parsed === null || parsed === "invalid") return { wrapped: [], present: false };
|
|
19133
|
-
return detectMcp(parsed.mcpServers);
|
|
19060
|
+
return detectMcp(format === "vscode" ? parsed.servers : parsed.mcpServers);
|
|
19134
19061
|
} catch {
|
|
19135
19062
|
return { wrapped: [], present: false };
|
|
19136
19063
|
}
|
|
19137
19064
|
}
|
|
19138
|
-
function getAgentWiring(home =
|
|
19065
|
+
function getAgentWiring(home = os6.homedir()) {
|
|
19139
19066
|
const detected = detectAgents(home);
|
|
19140
19067
|
return AGENT_SPECS.map((spec) => {
|
|
19141
19068
|
const present = spec.present(home);
|
|
@@ -19179,7 +19106,8 @@ function getAgentWiring(home = os7.homedir()) {
|
|
|
19179
19106
|
configFormat: spec.hookFormat === "yaml" ? "YAML" : "JSON",
|
|
19180
19107
|
mcpServers: mcp ? mcp.wrapped : null,
|
|
19181
19108
|
mcpProtected: mcp ? mcp.present : false,
|
|
19182
|
-
isProtected: anyHookWired || (mcp?.present ?? false)
|
|
19109
|
+
isProtected: anyHookWired || (mcp?.present ?? false),
|
|
19110
|
+
protection: spec.hookEvents.length > 0 || spec.shimFile ? "hooks" : "mcp"
|
|
19183
19111
|
};
|
|
19184
19112
|
});
|
|
19185
19113
|
}
|
|
@@ -19190,7 +19118,7 @@ var init_agent_wiring = __esm({
|
|
|
19190
19118
|
init_setup();
|
|
19191
19119
|
exists = (p) => {
|
|
19192
19120
|
try {
|
|
19193
|
-
return
|
|
19121
|
+
return fs7.existsSync(p);
|
|
19194
19122
|
} catch {
|
|
19195
19123
|
return false;
|
|
19196
19124
|
}
|
|
@@ -19204,55 +19132,55 @@ var init_agent_wiring = __esm({
|
|
|
19204
19132
|
id: "claude",
|
|
19205
19133
|
label: "Claude Code",
|
|
19206
19134
|
setupCommand: "node9 agents add claude",
|
|
19207
|
-
hookFile: (h) =>
|
|
19135
|
+
hookFile: (h) => path9.join(h, ".claude", "settings.json"),
|
|
19208
19136
|
hookFormat: "matcher",
|
|
19209
19137
|
// UserPromptSubmit is prompt DLP. setup.ts has written it for Claude since
|
|
19210
19138
|
// that shipped; the spec must name it too, or status/doctor never show the
|
|
19211
19139
|
// row and heal (which repairs via setupAgent) has no signal it is missing.
|
|
19212
19140
|
hookEvents: [ck("PreToolUse"), lg("PostToolUse"), ck("UserPromptSubmit")],
|
|
19213
|
-
mcpFile: (h) =>
|
|
19214
|
-
present: (h) => exists(
|
|
19141
|
+
mcpFile: (h) => path9.join(h, ".claude.json"),
|
|
19142
|
+
present: (h) => exists(path9.join(h, ".claude", "settings.json")) || exists(path9.join(h, ".claude.json"))
|
|
19215
19143
|
},
|
|
19216
19144
|
{
|
|
19217
19145
|
id: "gemini",
|
|
19218
19146
|
label: "Gemini CLI",
|
|
19219
19147
|
setupCommand: "node9 agents add gemini",
|
|
19220
|
-
hookFile: (h) =>
|
|
19148
|
+
hookFile: (h) => path9.join(h, ".gemini", "settings.json"),
|
|
19221
19149
|
hookFormat: "matcher",
|
|
19222
19150
|
hookEvents: [ck("BeforeTool"), lg("AfterTool")],
|
|
19223
|
-
mcpFile: (h) =>
|
|
19224
|
-
present: (h) => exists(
|
|
19151
|
+
mcpFile: (h) => path9.join(h, ".gemini", "settings.json"),
|
|
19152
|
+
present: (h) => exists(path9.join(h, ".gemini", "settings.json"))
|
|
19225
19153
|
},
|
|
19226
19154
|
{
|
|
19227
19155
|
id: "codex",
|
|
19228
19156
|
label: "Codex",
|
|
19229
19157
|
setupCommand: "node9 agents add codex",
|
|
19230
|
-
hookFile: (h) =>
|
|
19158
|
+
hookFile: (h) => path9.join(h, ".codex", "hooks.json"),
|
|
19231
19159
|
hookFormat: "matcher",
|
|
19232
19160
|
hookEvents: [ck("PreToolUse"), ck("UserPromptSubmit")],
|
|
19233
|
-
mcpFile: (h) =>
|
|
19161
|
+
mcpFile: (h) => path9.join(h, ".codex", "config.toml"),
|
|
19234
19162
|
mcpFormat: "toml",
|
|
19235
|
-
present: (h) => exists(
|
|
19163
|
+
present: (h) => exists(path9.join(h, ".codex"))
|
|
19236
19164
|
},
|
|
19237
19165
|
{
|
|
19238
19166
|
id: "antigravity",
|
|
19239
19167
|
label: "Antigravity",
|
|
19240
19168
|
setupCommand: "node9 agents add antigravity",
|
|
19241
|
-
hookFile: (h) =>
|
|
19169
|
+
hookFile: (h) => path9.join(h, ".gemini", "config", "hooks.json"),
|
|
19242
19170
|
hookFormat: "matcher",
|
|
19243
19171
|
hookEvents: [ck("PreToolUse"), lg("PostToolUse")],
|
|
19244
|
-
mcpFile: (h) =>
|
|
19245
|
-
present: (h) => exists(
|
|
19172
|
+
mcpFile: (h) => path9.join(h, ".gemini", "config", "mcp_config.json"),
|
|
19173
|
+
present: (h) => exists(path9.join(h, ".gemini", "config", "hooks.json")) || exists(path9.join(h, ".gemini", "antigravity-cli")) || exists(path9.join(h, ".gemini", "antigravity-ide"))
|
|
19246
19174
|
},
|
|
19247
19175
|
{
|
|
19248
19176
|
id: "copilot",
|
|
19249
19177
|
label: "GitHub Copilot",
|
|
19250
19178
|
setupCommand: "node9 agents add copilot",
|
|
19251
|
-
hookFile: (h) =>
|
|
19179
|
+
hookFile: (h) => path9.join(h, ".copilot", "hooks", "node9.json"),
|
|
19252
19180
|
hookFormat: "flat",
|
|
19253
19181
|
hookEvents: [ck("PreToolUse"), lg("PostToolUse"), ck("UserPromptSubmit")],
|
|
19254
|
-
mcpFile: (h) =>
|
|
19255
|
-
present: (h) => exists(
|
|
19182
|
+
mcpFile: (h) => path9.join(h, ".copilot", "mcp-config.json"),
|
|
19183
|
+
present: (h) => exists(path9.join(h, ".copilot"))
|
|
19256
19184
|
},
|
|
19257
19185
|
{
|
|
19258
19186
|
id: "cursor",
|
|
@@ -19261,8 +19189,45 @@ var init_agent_wiring = __esm({
|
|
|
19261
19189
|
// MCP-only — no hook file (see note above).
|
|
19262
19190
|
hookFormat: "flat",
|
|
19263
19191
|
hookEvents: [],
|
|
19264
|
-
mcpFile: (h) =>
|
|
19265
|
-
present: (h) => exists(
|
|
19192
|
+
mcpFile: (h) => path9.join(h, ".cursor", "mcp.json"),
|
|
19193
|
+
present: (h) => exists(path9.join(h, ".cursor", "mcp.json"))
|
|
19194
|
+
},
|
|
19195
|
+
// The three MCP-only agents below came over from `getAgentsStatus` (fw#421
|
|
19196
|
+
// P3), so one registry answers every "is it wired" question.
|
|
19197
|
+
{
|
|
19198
|
+
id: "windsurf",
|
|
19199
|
+
label: "Windsurf",
|
|
19200
|
+
setupCommand: "node9 agents add windsurf",
|
|
19201
|
+
hookFormat: "flat",
|
|
19202
|
+
hookEvents: [],
|
|
19203
|
+
mcpFile: (h) => path9.join(h, ".codeium", "windsurf", "mcp_config.json"),
|
|
19204
|
+
mcpInventory: false,
|
|
19205
|
+
present: (h) => exists(path9.join(h, ".codeium", "windsurf"))
|
|
19206
|
+
},
|
|
19207
|
+
{
|
|
19208
|
+
id: "vscode",
|
|
19209
|
+
label: "VSCode",
|
|
19210
|
+
setupCommand: "node9 agents add vscode",
|
|
19211
|
+
hookFormat: "flat",
|
|
19212
|
+
hookEvents: [],
|
|
19213
|
+
mcpFile: (h) => path9.join(h, ".vscode", "mcp.json"),
|
|
19214
|
+
mcpFormat: "vscode",
|
|
19215
|
+
mcpInventory: false,
|
|
19216
|
+
present: (h) => exists(path9.join(h, ".vscode"))
|
|
19217
|
+
},
|
|
19218
|
+
{
|
|
19219
|
+
id: "claudeDesktop",
|
|
19220
|
+
label: "Claude Desktop",
|
|
19221
|
+
setupCommand: "node9 agents add claudeDesktop",
|
|
19222
|
+
hookFormat: "flat",
|
|
19223
|
+
hookEvents: [],
|
|
19224
|
+
// The per-platform config path; its parent directory is the footprint.
|
|
19225
|
+
mcpFile: (h) => claudeDesktopConfigPath(h) ?? path9.join(h, ".config", "Claude", "claude_desktop_config.json"),
|
|
19226
|
+
mcpInventory: false,
|
|
19227
|
+
present: (h) => {
|
|
19228
|
+
const p = claudeDesktopConfigPath(h);
|
|
19229
|
+
return p !== null && exists(path9.dirname(p));
|
|
19230
|
+
}
|
|
19266
19231
|
},
|
|
19267
19232
|
{
|
|
19268
19233
|
id: "hermes",
|
|
@@ -19283,8 +19248,8 @@ var init_agent_wiring = __esm({
|
|
|
19283
19248
|
setupCommand: "node9 agents add opencode",
|
|
19284
19249
|
hookFormat: "flat",
|
|
19285
19250
|
hookEvents: [],
|
|
19286
|
-
shimFile: (h) =>
|
|
19287
|
-
present: (h) => exists(opencodeConfigDir(h)) || exists(
|
|
19251
|
+
shimFile: (h) => path9.join(opencodeConfigDir(h), "plugins", "node9.js"),
|
|
19252
|
+
present: (h) => exists(opencodeConfigDir(h)) || exists(path9.join(opencodeConfigDir(h), "plugins", "node9.js"))
|
|
19288
19253
|
},
|
|
19289
19254
|
{
|
|
19290
19255
|
id: "pi",
|
|
@@ -19292,8 +19257,8 @@ var init_agent_wiring = __esm({
|
|
|
19292
19257
|
setupCommand: "node9 agents add pi",
|
|
19293
19258
|
hookFormat: "flat",
|
|
19294
19259
|
hookEvents: [],
|
|
19295
|
-
shimFile: (h) =>
|
|
19296
|
-
present: (h) => exists(
|
|
19260
|
+
shimFile: (h) => path9.join(h, ".pi", "agent", "extensions", "node9.js"),
|
|
19261
|
+
present: (h) => exists(path9.join(h, ".pi", "agent")) || exists(path9.join(h, ".pi", "agent", "extensions", "node9.js"))
|
|
19297
19262
|
}
|
|
19298
19263
|
];
|
|
19299
19264
|
}
|
|
@@ -19383,14 +19348,14 @@ var init_build = __esm({
|
|
|
19383
19348
|
});
|
|
19384
19349
|
|
|
19385
19350
|
// src/shields.ts
|
|
19386
|
-
import
|
|
19387
|
-
import
|
|
19388
|
-
import
|
|
19351
|
+
import fs8 from "fs";
|
|
19352
|
+
import path10 from "path";
|
|
19353
|
+
import os7 from "os";
|
|
19389
19354
|
function loadUserShields() {
|
|
19390
19355
|
const result = {};
|
|
19391
19356
|
let entries;
|
|
19392
19357
|
try {
|
|
19393
|
-
entries =
|
|
19358
|
+
entries = fs8.readdirSync(USER_SHIELDS_DIR).filter((f) => f.endsWith(".json"));
|
|
19394
19359
|
} catch (err) {
|
|
19395
19360
|
if (err.code !== "ENOENT") {
|
|
19396
19361
|
process.stderr.write(
|
|
@@ -19401,9 +19366,9 @@ function loadUserShields() {
|
|
|
19401
19366
|
return result;
|
|
19402
19367
|
}
|
|
19403
19368
|
for (const file2 of entries) {
|
|
19404
|
-
const filePath =
|
|
19369
|
+
const filePath = path10.join(USER_SHIELDS_DIR, file2);
|
|
19405
19370
|
try {
|
|
19406
|
-
const raw = JSON.parse(
|
|
19371
|
+
const raw = JSON.parse(fs8.readFileSync(filePath, "utf-8"));
|
|
19407
19372
|
const v = validateShieldDefinition(raw);
|
|
19408
19373
|
if ("error" in v) {
|
|
19409
19374
|
process.stderr.write(`[node9] ${v.error}: ${filePath}
|
|
@@ -19435,7 +19400,7 @@ function getShield(name) {
|
|
|
19435
19400
|
}
|
|
19436
19401
|
function readShieldsFile() {
|
|
19437
19402
|
try {
|
|
19438
|
-
const raw =
|
|
19403
|
+
const raw = fs8.readFileSync(SHIELDS_STATE_FILE, "utf-8");
|
|
19439
19404
|
if (!raw.trim()) return { active: [] };
|
|
19440
19405
|
const parsed = JSON.parse(raw);
|
|
19441
19406
|
const active = Array.isArray(parsed.active) ? parsed.active.filter(
|
|
@@ -19468,23 +19433,23 @@ var init_shields = __esm({
|
|
|
19468
19433
|
init_dist();
|
|
19469
19434
|
init_build();
|
|
19470
19435
|
init_dist();
|
|
19471
|
-
USER_SHIELDS_DIR =
|
|
19436
|
+
USER_SHIELDS_DIR = path10.join(os7.homedir(), ".node9", "shields");
|
|
19472
19437
|
SHIELDS = buildSHIELDS();
|
|
19473
|
-
SHIELDS_STATE_FILE =
|
|
19438
|
+
SHIELDS_STATE_FILE = path10.join(os7.homedir(), ".node9", "shields.json");
|
|
19474
19439
|
}
|
|
19475
19440
|
});
|
|
19476
19441
|
|
|
19477
19442
|
// src/shields/jail.ts
|
|
19478
|
-
import
|
|
19479
|
-
import
|
|
19480
|
-
import
|
|
19443
|
+
import fs9 from "fs";
|
|
19444
|
+
import os8 from "os";
|
|
19445
|
+
import path11 from "path";
|
|
19481
19446
|
function jailStorePath() {
|
|
19482
|
-
return
|
|
19447
|
+
return path11.join(os8.homedir(), ".node9", "jail-paths.json");
|
|
19483
19448
|
}
|
|
19484
19449
|
function readJailPaths() {
|
|
19485
19450
|
let text;
|
|
19486
19451
|
try {
|
|
19487
|
-
text =
|
|
19452
|
+
text = fs9.readFileSync(jailStorePath(), "utf8");
|
|
19488
19453
|
} catch (err) {
|
|
19489
19454
|
if (err.code === "ENOENT") return [];
|
|
19490
19455
|
throw err;
|
|
@@ -19522,11 +19487,11 @@ var init_jail = __esm({
|
|
|
19522
19487
|
});
|
|
19523
19488
|
|
|
19524
19489
|
// src/canary/registry.ts
|
|
19525
|
-
import
|
|
19526
|
-
import
|
|
19527
|
-
import
|
|
19490
|
+
import fs10 from "fs";
|
|
19491
|
+
import os9 from "os";
|
|
19492
|
+
import path12 from "path";
|
|
19528
19493
|
function canaryStorePath() {
|
|
19529
|
-
return
|
|
19494
|
+
return path12.join(os9.homedir(), ".node9", "canaries.json");
|
|
19530
19495
|
}
|
|
19531
19496
|
function isRecord(x) {
|
|
19532
19497
|
if (!x || typeof x !== "object") return false;
|
|
@@ -19537,7 +19502,7 @@ function loadCanaries(opts) {
|
|
|
19537
19502
|
const p = canaryStorePath();
|
|
19538
19503
|
let raw;
|
|
19539
19504
|
try {
|
|
19540
|
-
raw =
|
|
19505
|
+
raw = fs10.readFileSync(p, "utf-8");
|
|
19541
19506
|
} catch (e) {
|
|
19542
19507
|
if (e.code === "ENOENT") return [];
|
|
19543
19508
|
throw e;
|
|
@@ -19576,23 +19541,23 @@ var init_registry = __esm({
|
|
|
19576
19541
|
});
|
|
19577
19542
|
|
|
19578
19543
|
// src/utils/read-capped.ts
|
|
19579
|
-
import
|
|
19544
|
+
import fs11 from "fs";
|
|
19580
19545
|
function readCapped(file2, maxBytes, openFlags = "r") {
|
|
19581
19546
|
if (maxBytes < 0) return null;
|
|
19582
19547
|
let fd;
|
|
19583
19548
|
try {
|
|
19584
|
-
fd =
|
|
19549
|
+
fd = fs11.openSync(file2, openFlags);
|
|
19585
19550
|
} catch {
|
|
19586
19551
|
return null;
|
|
19587
19552
|
}
|
|
19588
19553
|
try {
|
|
19589
|
-
const st =
|
|
19554
|
+
const st = fs11.fstatSync(fd);
|
|
19590
19555
|
if (!st.isFile()) return null;
|
|
19591
19556
|
const want = Math.min(st.size, maxBytes + 1);
|
|
19592
19557
|
const buf = Buffer.alloc(want);
|
|
19593
19558
|
let read2 = 0;
|
|
19594
19559
|
while (read2 < want) {
|
|
19595
|
-
const n =
|
|
19560
|
+
const n = fs11.readSync(fd, buf, read2, want - read2, read2);
|
|
19596
19561
|
if (n <= 0) break;
|
|
19597
19562
|
read2 += n;
|
|
19598
19563
|
}
|
|
@@ -19604,7 +19569,7 @@ function readCapped(file2, maxBytes, openFlags = "r") {
|
|
|
19604
19569
|
return null;
|
|
19605
19570
|
} finally {
|
|
19606
19571
|
try {
|
|
19607
|
-
|
|
19572
|
+
fs11.closeSync(fd);
|
|
19608
19573
|
} catch {
|
|
19609
19574
|
}
|
|
19610
19575
|
}
|
|
@@ -19620,13 +19585,13 @@ var init_read_capped = __esm({
|
|
|
19620
19585
|
});
|
|
19621
19586
|
|
|
19622
19587
|
// src/posture/secrets.ts
|
|
19623
|
-
import
|
|
19624
|
-
import
|
|
19625
|
-
import
|
|
19588
|
+
import fs12 from "fs";
|
|
19589
|
+
import path13 from "path";
|
|
19590
|
+
import os10 from "os";
|
|
19626
19591
|
function displayPath(p, home) {
|
|
19627
19592
|
if (p === home) return "~";
|
|
19628
|
-
const prefix = home.endsWith(
|
|
19629
|
-
if (p.startsWith(prefix)) return "~" +
|
|
19593
|
+
const prefix = home.endsWith(path13.sep) ? home : home + path13.sep;
|
|
19594
|
+
if (p.startsWith(prefix)) return "~" + path13.sep + p.slice(prefix.length);
|
|
19630
19595
|
return p;
|
|
19631
19596
|
}
|
|
19632
19597
|
function safeRead(file2) {
|
|
@@ -19637,8 +19602,8 @@ function safeRead(file2) {
|
|
|
19637
19602
|
function candidateFiles(home, cwd) {
|
|
19638
19603
|
const files = /* @__PURE__ */ new Set();
|
|
19639
19604
|
try {
|
|
19640
|
-
for (const name of
|
|
19641
|
-
if (name === ".env" || name.startsWith(".env.")) files.add(
|
|
19605
|
+
for (const name of fs12.readdirSync(cwd)) {
|
|
19606
|
+
if (name === ".env" || name.startsWith(".env.")) files.add(path13.join(cwd, name));
|
|
19642
19607
|
}
|
|
19643
19608
|
} catch {
|
|
19644
19609
|
}
|
|
@@ -19646,7 +19611,7 @@ function candidateFiles(home, cwd) {
|
|
|
19646
19611
|
if (spec.hookFile) files.add(spec.hookFile(home));
|
|
19647
19612
|
if (spec.mcpFile) files.add(spec.mcpFile(home));
|
|
19648
19613
|
}
|
|
19649
|
-
files.add(
|
|
19614
|
+
files.add(path13.join(home, ".env"));
|
|
19650
19615
|
return [...files];
|
|
19651
19616
|
}
|
|
19652
19617
|
function credentialMaterial(home) {
|
|
@@ -19660,7 +19625,7 @@ function plantedDecoyPaths() {
|
|
|
19660
19625
|
}
|
|
19661
19626
|
}
|
|
19662
19627
|
function checkSecrets(ctx) {
|
|
19663
|
-
const home = ctx.home ||
|
|
19628
|
+
const home = ctx.home || os10.homedir();
|
|
19664
19629
|
const findings = [];
|
|
19665
19630
|
const planted = plantedDecoyPaths();
|
|
19666
19631
|
const plaintext = [];
|
|
@@ -19696,7 +19661,7 @@ function checkSecrets(ctx) {
|
|
|
19696
19661
|
for (const file2 of credentialMaterial(home)) {
|
|
19697
19662
|
if (planted.has(file2)) continue;
|
|
19698
19663
|
try {
|
|
19699
|
-
if (
|
|
19664
|
+
if (fs12.statSync(file2).isFile()) {
|
|
19700
19665
|
creds.push(displayPath(file2, home));
|
|
19701
19666
|
credPaths.push(file2);
|
|
19702
19667
|
}
|
|
@@ -19717,6 +19682,25 @@ function checkSecrets(ctx) {
|
|
|
19717
19682
|
coverageProbe: { kind: "fileRead", paths: credPaths }
|
|
19718
19683
|
});
|
|
19719
19684
|
}
|
|
19685
|
+
const envSecrets = [];
|
|
19686
|
+
for (const [key, value] of Object.entries(ctx.env ?? process.env)) {
|
|
19687
|
+
if (!value) continue;
|
|
19688
|
+
const match = scanArgs({ [key]: value });
|
|
19689
|
+
if (match) envSecrets.push(`${key} (${match.patternName})`);
|
|
19690
|
+
}
|
|
19691
|
+
if (envSecrets.length > 0) {
|
|
19692
|
+
findings.push({
|
|
19693
|
+
category: "Secrets",
|
|
19694
|
+
severity: "high",
|
|
19695
|
+
title: `${envSecrets.length} secret environment variable${envSecrets.length === 1 ? "" : "s"} visible to the agent`,
|
|
19696
|
+
what: "A key or token is exported in the shell the agent runs from.",
|
|
19697
|
+
why: "Every program the agent starts inherits the environment, so the value is one `env` away.",
|
|
19698
|
+
who: "A tricked agent can read it and send it anywhere a command can reach.",
|
|
19699
|
+
detail: envSecrets,
|
|
19700
|
+
fix: "Unset it in the shell that starts the agent, or pass it to the one command that needs it (`env KEY=... cmd`) or a secrets manager.",
|
|
19701
|
+
owner: "os"
|
|
19702
|
+
});
|
|
19703
|
+
}
|
|
19720
19704
|
if (planted.size > 0) {
|
|
19721
19705
|
findings.push({
|
|
19722
19706
|
category: "Secrets",
|
|
@@ -19739,6 +19723,7 @@ var init_secrets = __esm({
|
|
|
19739
19723
|
init_registry();
|
|
19740
19724
|
init_read_capped();
|
|
19741
19725
|
init_credential_files();
|
|
19726
|
+
init_dlp();
|
|
19742
19727
|
MAX_FILE_BYTES = 256 * 1024;
|
|
19743
19728
|
}
|
|
19744
19729
|
});
|
|
@@ -20149,15 +20134,15 @@ var init_managed = __esm({
|
|
|
20149
20134
|
});
|
|
20150
20135
|
|
|
20151
20136
|
// src/auth/trusted-hosts.ts
|
|
20152
|
-
import
|
|
20153
|
-
import
|
|
20154
|
-
import
|
|
20137
|
+
import fs13 from "fs";
|
|
20138
|
+
import path14 from "path";
|
|
20139
|
+
import os11 from "os";
|
|
20155
20140
|
function getTrustedHostsPath() {
|
|
20156
|
-
return
|
|
20141
|
+
return path14.join(os11.homedir(), ".node9", "trusted-hosts.json");
|
|
20157
20142
|
}
|
|
20158
20143
|
function readTrustedHosts() {
|
|
20159
20144
|
try {
|
|
20160
|
-
const raw =
|
|
20145
|
+
const raw = fs13.readFileSync(getTrustedHostsPath(), "utf8");
|
|
20161
20146
|
const parsed = JSON.parse(raw);
|
|
20162
20147
|
return Array.isArray(parsed.hosts) ? parsed.hosts : [];
|
|
20163
20148
|
} catch {
|
|
@@ -20166,7 +20151,7 @@ function readTrustedHosts() {
|
|
|
20166
20151
|
}
|
|
20167
20152
|
function getFileMtime() {
|
|
20168
20153
|
try {
|
|
20169
|
-
return
|
|
20154
|
+
return fs13.statSync(getTrustedHostsPath()).mtimeMs;
|
|
20170
20155
|
} catch {
|
|
20171
20156
|
return 0;
|
|
20172
20157
|
}
|
|
@@ -20385,9 +20370,9 @@ var init_api_url = __esm({
|
|
|
20385
20370
|
});
|
|
20386
20371
|
|
|
20387
20372
|
// src/config/index.ts
|
|
20388
|
-
import
|
|
20389
|
-
import
|
|
20390
|
-
import
|
|
20373
|
+
import fs14 from "fs";
|
|
20374
|
+
import path15 from "path";
|
|
20375
|
+
import os12 from "os";
|
|
20391
20376
|
function sanitizeSsrfAllow(entries, source) {
|
|
20392
20377
|
const kept = [];
|
|
20393
20378
|
for (const entry of entries) {
|
|
@@ -20409,8 +20394,8 @@ function noteRejectedApiUrl(raw) {
|
|
|
20409
20394
|
if (rejectedApiUrlsSeen.has(key)) return;
|
|
20410
20395
|
rejectedApiUrlsSeen.add(key);
|
|
20411
20396
|
try {
|
|
20412
|
-
|
|
20413
|
-
|
|
20397
|
+
fs14.appendFileSync(
|
|
20398
|
+
path15.join(os12.homedir(), ".node9", "hook-debug.log"),
|
|
20414
20399
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] REFUSED apiUrl, using the default instead: ${String(raw).slice(0, 200).replace(/[\r\n]+/g, " ")}
|
|
20415
20400
|
`
|
|
20416
20401
|
);
|
|
@@ -20427,9 +20412,9 @@ function getCredentials() {
|
|
|
20427
20412
|
};
|
|
20428
20413
|
}
|
|
20429
20414
|
try {
|
|
20430
|
-
const credPath =
|
|
20431
|
-
if (
|
|
20432
|
-
const creds = JSON.parse(
|
|
20415
|
+
const credPath = path15.join(os12.homedir(), ".node9", "credentials.json");
|
|
20416
|
+
if (fs14.existsSync(credPath)) {
|
|
20417
|
+
const creds = JSON.parse(fs14.readFileSync(credPath, "utf-8"));
|
|
20433
20418
|
const profileName = process.env.NODE9_PROFILE || "default";
|
|
20434
20419
|
const profile = creds[profileName];
|
|
20435
20420
|
if (typeof profile?.apiKey === "string" && profile.apiKey.length > 0) {
|
|
@@ -20461,7 +20446,7 @@ function readRulesCacheResilient(cacheFile) {
|
|
|
20461
20446
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
20462
20447
|
let content;
|
|
20463
20448
|
try {
|
|
20464
|
-
content =
|
|
20449
|
+
content = fs14.readFileSync(cacheFile, "utf-8");
|
|
20465
20450
|
existed = true;
|
|
20466
20451
|
} catch (err) {
|
|
20467
20452
|
if (err.code === "ENOENT") return {};
|
|
@@ -20476,10 +20461,10 @@ function readRulesCacheResilient(cacheFile) {
|
|
|
20476
20461
|
}
|
|
20477
20462
|
}
|
|
20478
20463
|
if (existed || sawReadError) {
|
|
20479
|
-
const backup =
|
|
20464
|
+
const backup = path15.join(path15.dirname(cacheFile), "rules-cache.last-good.json");
|
|
20480
20465
|
if (backup !== cacheFile) {
|
|
20481
20466
|
try {
|
|
20482
|
-
const raw = JSON.parse(
|
|
20467
|
+
const raw = JSON.parse(fs14.readFileSync(backup, "utf-8"));
|
|
20483
20468
|
logCacheReadIssue(cacheFile, "RULES_CACHE_CORRUPT_USED_BACKUP");
|
|
20484
20469
|
lastParsedRulesCache = raw;
|
|
20485
20470
|
return raw;
|
|
@@ -20499,8 +20484,8 @@ function logCacheReadIssue(cacheFile, kind) {
|
|
|
20499
20484
|
if (now - cacheReadLastLoggedAt < CACHE_LOG_REARM_MS) return;
|
|
20500
20485
|
cacheReadLastLoggedAt = now;
|
|
20501
20486
|
try {
|
|
20502
|
-
|
|
20503
|
-
|
|
20487
|
+
fs14.appendFileSync(
|
|
20488
|
+
path15.join(os12.homedir(), ".node9", "hook-debug.log"),
|
|
20504
20489
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] ${kind} ${cacheFile}
|
|
20505
20490
|
`
|
|
20506
20491
|
);
|
|
@@ -20517,8 +20502,8 @@ function catalogSettingsFrom(settings, policy) {
|
|
|
20517
20502
|
}
|
|
20518
20503
|
function getConfig(cwd) {
|
|
20519
20504
|
if (!cwd && cachedConfig) return cachedConfig;
|
|
20520
|
-
const globalPath =
|
|
20521
|
-
const projectPath =
|
|
20505
|
+
const globalPath = path15.join(os12.homedir(), ".node9", "config.json");
|
|
20506
|
+
const projectPath = path15.join(cwd ?? process.cwd(), "node9.config.json");
|
|
20522
20507
|
const globalConfig = tryLoadConfig(globalPath);
|
|
20523
20508
|
const projectConfig = tryLoadConfig(projectPath, { project: true });
|
|
20524
20509
|
const mergedSettings = {
|
|
@@ -20763,7 +20748,7 @@ function getConfig(cwd) {
|
|
|
20763
20748
|
let cloudMandatesEnforcement = false;
|
|
20764
20749
|
let cloudMandatesAppPerm = false;
|
|
20765
20750
|
{
|
|
20766
|
-
const cacheFile =
|
|
20751
|
+
const cacheFile = path15.join(os12.homedir(), ".node9", "rules-cache.json");
|
|
20767
20752
|
try {
|
|
20768
20753
|
const raw = readRulesCacheResilient(cacheFile);
|
|
20769
20754
|
if (Array.isArray(raw.rules) && raw.rules.length > 0) {
|
|
@@ -21195,10 +21180,10 @@ function getConfig(cwd) {
|
|
|
21195
21180
|
}
|
|
21196
21181
|
function tryLoadConfig(filePath, options = {}) {
|
|
21197
21182
|
v2ChecksByPath.delete(filePath);
|
|
21198
|
-
if (!
|
|
21183
|
+
if (!fs14.existsSync(filePath)) return null;
|
|
21199
21184
|
let raw;
|
|
21200
21185
|
try {
|
|
21201
|
-
raw = JSON.parse(
|
|
21186
|
+
raw = JSON.parse(fs14.readFileSync(filePath, "utf-8"));
|
|
21202
21187
|
} catch (err) {
|
|
21203
21188
|
const msg = err instanceof Error ? err.message : String(err);
|
|
21204
21189
|
process.stderr.write(
|
|
@@ -21661,10 +21646,10 @@ var init_templates = __esm({
|
|
|
21661
21646
|
});
|
|
21662
21647
|
|
|
21663
21648
|
// src/posture/egress.ts
|
|
21664
|
-
import
|
|
21649
|
+
import fs15 from "fs";
|
|
21665
21650
|
function sandboxEgressWallActive() {
|
|
21666
21651
|
try {
|
|
21667
|
-
return
|
|
21652
|
+
return fs15.existsSync(ALLOWED_DOMAINS_PATH);
|
|
21668
21653
|
} catch {
|
|
21669
21654
|
return false;
|
|
21670
21655
|
}
|
|
@@ -22011,29 +21996,29 @@ var init_gate_order = __esm({
|
|
|
22011
21996
|
});
|
|
22012
21997
|
|
|
22013
21998
|
// src/policy/file-access.ts
|
|
22014
|
-
import
|
|
22015
|
-
import
|
|
22016
|
-
import
|
|
21999
|
+
import fs16 from "fs";
|
|
22000
|
+
import os13 from "os";
|
|
22001
|
+
import path16 from "path";
|
|
22017
22002
|
function absoluteSpelling(p, cwd, home) {
|
|
22018
22003
|
if (p === "~" || p.startsWith("~/")) p = home + p.slice(1);
|
|
22019
|
-
return
|
|
22004
|
+
return path16.isAbsolute(p) ? p : `${cwd}/${p}`;
|
|
22020
22005
|
}
|
|
22021
22006
|
function physical(p, followFinal, links = 0) {
|
|
22022
22007
|
if (links > 40) throw new Error("Too many symbolic links");
|
|
22023
22008
|
if (!followFinal) {
|
|
22024
|
-
const parent = physical(
|
|
22025
|
-
return { path: `${parent.path}/${
|
|
22009
|
+
const parent = physical(path16.dirname(p), true, links);
|
|
22010
|
+
return { path: `${parent.path}/${path16.basename(p)}`, missing: parent.missing };
|
|
22026
22011
|
}
|
|
22027
22012
|
try {
|
|
22028
|
-
return { path:
|
|
22013
|
+
return { path: fs16.realpathSync.native(p), missing: false };
|
|
22029
22014
|
} catch (error) {
|
|
22030
22015
|
const code = error.code;
|
|
22031
22016
|
if (!["ENOENT", "ENOTDIR"].includes(code ?? "")) throw error;
|
|
22032
22017
|
try {
|
|
22033
|
-
if (
|
|
22034
|
-
const target =
|
|
22018
|
+
if (fs16.lstatSync(p).isSymbolicLink()) {
|
|
22019
|
+
const target = fs16.readlinkSync(p);
|
|
22035
22020
|
return physical(
|
|
22036
|
-
|
|
22021
|
+
path16.isAbsolute(target) ? target : `${path16.dirname(p)}/${target}`,
|
|
22037
22022
|
true,
|
|
22038
22023
|
links + 1
|
|
22039
22024
|
);
|
|
@@ -22042,13 +22027,13 @@ function physical(p, followFinal, links = 0) {
|
|
|
22042
22027
|
if (!["ENOENT", "ENOTDIR"].includes(linkError.code ?? ""))
|
|
22043
22028
|
throw linkError;
|
|
22044
22029
|
}
|
|
22045
|
-
const parent =
|
|
22030
|
+
const parent = path16.dirname(p);
|
|
22046
22031
|
if (parent === p) return { path: p, missing: true };
|
|
22047
22032
|
const resolved = physical(parent, true, links);
|
|
22048
|
-
return { path: `${resolved.path}/${
|
|
22033
|
+
return { path: `${resolved.path}/${path16.basename(p)}`, missing: true };
|
|
22049
22034
|
}
|
|
22050
22035
|
}
|
|
22051
|
-
function prepareFileAccesses(tool, args, cwd = process.cwd(), inspection = {}, home =
|
|
22036
|
+
function prepareFileAccesses(tool, args, cwd = process.cwd(), inspection = {}, home = os13.homedir()) {
|
|
22052
22037
|
const context = { cwd, homeDirs: [home, "/root"] };
|
|
22053
22038
|
const accesses = collectFileAccesses(tool, args, context, inspection);
|
|
22054
22039
|
const handledPaths = /* @__PURE__ */ new Set();
|
|
@@ -22071,14 +22056,14 @@ function prepareFileAccesses(tool, args, cwd = process.cwd(), inspection = {}, h
|
|
|
22071
22056
|
const raw = absoluteSpelling(access.path, access.cwd ?? cwd, home);
|
|
22072
22057
|
if (access.directoryTarget) {
|
|
22073
22058
|
try {
|
|
22074
|
-
if (!
|
|
22059
|
+
if (!fs16.statSync(absoluteSpelling(access.directoryTarget, access.cwd ?? cwd, home)).isDirectory())
|
|
22075
22060
|
continue;
|
|
22076
22061
|
} catch {
|
|
22077
22062
|
}
|
|
22078
22063
|
}
|
|
22079
22064
|
if (access.operation === "create") {
|
|
22080
22065
|
try {
|
|
22081
|
-
|
|
22066
|
+
fs16.statSync(raw);
|
|
22082
22067
|
continue;
|
|
22083
22068
|
} catch {
|
|
22084
22069
|
}
|
|
@@ -22133,15 +22118,15 @@ var init_file_access = __esm({
|
|
|
22133
22118
|
});
|
|
22134
22119
|
|
|
22135
22120
|
// src/supply-chain/osv-index.ts
|
|
22136
|
-
import
|
|
22137
|
-
import
|
|
22138
|
-
import
|
|
22121
|
+
import fs17 from "fs";
|
|
22122
|
+
import os14 from "os";
|
|
22123
|
+
import path17 from "path";
|
|
22139
22124
|
import { createHash as createHash4 } from "crypto";
|
|
22140
22125
|
function osvRoot() {
|
|
22141
|
-
return
|
|
22126
|
+
return path17.join(os14.homedir(), ".node9", "osv");
|
|
22142
22127
|
}
|
|
22143
22128
|
function ecoDir(eco) {
|
|
22144
|
-
return
|
|
22129
|
+
return path17.join(osvRoot(), eco);
|
|
22145
22130
|
}
|
|
22146
22131
|
function indexKey(eco, name) {
|
|
22147
22132
|
switch (eco) {
|
|
@@ -22160,11 +22145,11 @@ function shardOf(key) {
|
|
|
22160
22145
|
return createHash4("sha1").update(key).digest("hex").slice(0, 2);
|
|
22161
22146
|
}
|
|
22162
22147
|
function shardPath(eco, shard) {
|
|
22163
|
-
return
|
|
22148
|
+
return path17.join(ecoDir(eco), "shards", `${shard}.json`);
|
|
22164
22149
|
}
|
|
22165
22150
|
function readMeta(eco) {
|
|
22166
22151
|
try {
|
|
22167
|
-
const m = JSON.parse(
|
|
22152
|
+
const m = JSON.parse(fs17.readFileSync(path17.join(ecoDir(eco), "meta.json"), "utf8"));
|
|
22168
22153
|
if (typeof m?.syncedAt !== "string" || typeof m?.lastModifiedMs !== "number") return null;
|
|
22169
22154
|
return m;
|
|
22170
22155
|
} catch {
|
|
@@ -22173,7 +22158,7 @@ function readMeta(eco) {
|
|
|
22173
22158
|
}
|
|
22174
22159
|
function readShard(eco, shard) {
|
|
22175
22160
|
try {
|
|
22176
|
-
const s = JSON.parse(
|
|
22161
|
+
const s = JSON.parse(fs17.readFileSync(shardPath(eco, shard), "utf8"));
|
|
22177
22162
|
return s && typeof s === "object" && !Array.isArray(s) ? s : {};
|
|
22178
22163
|
} catch {
|
|
22179
22164
|
return {};
|
|
@@ -22555,17 +22540,17 @@ var init_registry2 = __esm({
|
|
|
22555
22540
|
});
|
|
22556
22541
|
|
|
22557
22542
|
// src/supply-chain/local-resolve.ts
|
|
22558
|
-
import
|
|
22559
|
-
import
|
|
22543
|
+
import fs18 from "fs";
|
|
22544
|
+
import path18 from "path";
|
|
22560
22545
|
function resolveInstalled(name, cwd) {
|
|
22561
|
-
if (!cwd || !
|
|
22546
|
+
if (!cwd || !path18.isAbsolute(cwd)) return null;
|
|
22562
22547
|
if (!/^(?:@[^/\\]+\/)?[^/\\]+$/.test(name)) return null;
|
|
22563
|
-
let dir2 =
|
|
22548
|
+
let dir2 = path18.resolve(cwd);
|
|
22564
22549
|
for (let i = 0; i < MAX_LEVELS; i++) {
|
|
22565
|
-
const pkgDir =
|
|
22566
|
-
const manifest =
|
|
22550
|
+
const pkgDir = path18.join(dir2, "node_modules", ...name.split("/"));
|
|
22551
|
+
const manifest = path18.join(pkgDir, "package.json");
|
|
22567
22552
|
try {
|
|
22568
|
-
const raw =
|
|
22553
|
+
const raw = fs18.readFileSync(manifest, "utf8");
|
|
22569
22554
|
const parsed = JSON.parse(raw);
|
|
22570
22555
|
if (typeof parsed.version === "string" && parsed.version.length > 0) {
|
|
22571
22556
|
return { version: parsed.version, dir: pkgDir };
|
|
@@ -22573,7 +22558,7 @@ function resolveInstalled(name, cwd) {
|
|
|
22573
22558
|
return null;
|
|
22574
22559
|
} catch {
|
|
22575
22560
|
}
|
|
22576
|
-
const parent =
|
|
22561
|
+
const parent = path18.dirname(dir2);
|
|
22577
22562
|
if (parent === dir2) break;
|
|
22578
22563
|
dir2 = parent;
|
|
22579
22564
|
}
|
|
@@ -22590,7 +22575,7 @@ var init_local_resolve = __esm({
|
|
|
22590
22575
|
|
|
22591
22576
|
// src/supply-chain/check.ts
|
|
22592
22577
|
import picomatch2 from "picomatch";
|
|
22593
|
-
import
|
|
22578
|
+
import path19 from "path";
|
|
22594
22579
|
function commandOf(toolName, args) {
|
|
22595
22580
|
if (!isBashTool(toolName) || !args || typeof args !== "object") return null;
|
|
22596
22581
|
const a = args;
|
|
@@ -22692,7 +22677,7 @@ function checkInstalled(p, version, misses) {
|
|
|
22692
22677
|
}
|
|
22693
22678
|
async function checkOne(p, cfg, misses, networkCapped, cwd) {
|
|
22694
22679
|
if (p.ecosystem === "npm" && LOCAL_FIRST_MANAGERS.has(p.manager) && p.localCwd !== null && (p.raw === p.name || p.version)) {
|
|
22695
|
-
const localCwd = cwd &&
|
|
22680
|
+
const localCwd = cwd && path19.isAbsolute(cwd) ? (p.localCwd ?? []).reduce((dir2, step) => path19.resolve(dir2, step), cwd) : void 0;
|
|
22696
22681
|
const installed = resolveInstalled(p.name, localCwd);
|
|
22697
22682
|
if (installed && (!p.version || p.version === installed.version))
|
|
22698
22683
|
return checkInstalled(p, installed.version, misses);
|
|
@@ -22861,33 +22846,33 @@ var init_check = __esm({
|
|
|
22861
22846
|
});
|
|
22862
22847
|
|
|
22863
22848
|
// src/supply-chain/registries.ts
|
|
22864
|
-
import
|
|
22865
|
-
import
|
|
22866
|
-
import
|
|
22849
|
+
import os15 from "os";
|
|
22850
|
+
import path20 from "path";
|
|
22851
|
+
import fs19 from "fs";
|
|
22867
22852
|
function userFiles(home, env) {
|
|
22868
|
-
const xdg = env.XDG_CONFIG_HOME ||
|
|
22853
|
+
const xdg = env.XDG_CONFIG_HOME || path20.join(home, ".config");
|
|
22869
22854
|
return [
|
|
22870
|
-
env.NPM_CONFIG_USERCONFIG || env.npm_config_userconfig ||
|
|
22871
|
-
|
|
22872
|
-
|
|
22873
|
-
|
|
22855
|
+
env.NPM_CONFIG_USERCONFIG || env.npm_config_userconfig || path20.join(home, ".npmrc"),
|
|
22856
|
+
path20.join(home, ".yarnrc"),
|
|
22857
|
+
path20.join(home, ".yarnrc.yml"),
|
|
22858
|
+
path20.join(home, ".bunfig.toml"),
|
|
22874
22859
|
env.PIP_CONFIG_FILE || "",
|
|
22875
|
-
|
|
22876
|
-
|
|
22860
|
+
path20.join(xdg, "pip", "pip.conf"),
|
|
22861
|
+
path20.join(home, ".pip", "pip.conf"),
|
|
22877
22862
|
"/etc/pip.conf",
|
|
22878
|
-
env.VIRTUAL_ENV ?
|
|
22863
|
+
env.VIRTUAL_ENV ? path20.join(env.VIRTUAL_ENV, "pip.conf") : "",
|
|
22879
22864
|
env.UV_CONFIG_FILE || "",
|
|
22880
|
-
|
|
22865
|
+
path20.join(xdg, "uv", "uv.toml"),
|
|
22881
22866
|
"/etc/uv/uv.toml"
|
|
22882
22867
|
].filter(Boolean);
|
|
22883
22868
|
}
|
|
22884
22869
|
function projectFiles(cwd) {
|
|
22885
|
-
if (!cwd || !
|
|
22870
|
+
if (!cwd || !path20.isAbsolute(cwd)) return [];
|
|
22886
22871
|
const out = [];
|
|
22887
22872
|
let dir2 = cwd;
|
|
22888
22873
|
for (let i = 0; i < MAX_PARENT_DIRS; i++) {
|
|
22889
|
-
for (const f of PROJECT_FILES) out.push(
|
|
22890
|
-
const parent =
|
|
22874
|
+
for (const f of PROJECT_FILES) out.push(path20.join(dir2, f));
|
|
22875
|
+
const parent = path20.dirname(dir2);
|
|
22891
22876
|
if (parent === dir2) break;
|
|
22892
22877
|
dir2 = parent;
|
|
22893
22878
|
}
|
|
@@ -22926,7 +22911,7 @@ function hostsInText(text, out) {
|
|
|
22926
22911
|
}
|
|
22927
22912
|
}
|
|
22928
22913
|
}
|
|
22929
|
-
function configuredRegistryHosts(cwd, env = process.env, home =
|
|
22914
|
+
function configuredRegistryHosts(cwd, env = process.env, home = os15.homedir()) {
|
|
22930
22915
|
const key = [
|
|
22931
22916
|
cwd ?? "",
|
|
22932
22917
|
home,
|
|
@@ -22948,7 +22933,7 @@ function configuredRegistryHosts(cwd, env = process.env, home = os16.homedir())
|
|
|
22948
22933
|
const r = readCappedText(
|
|
22949
22934
|
file2,
|
|
22950
22935
|
MAX_CONFIG_BYTES,
|
|
22951
|
-
|
|
22936
|
+
fs19.constants.O_RDONLY | (fs19.constants.O_NONBLOCK ?? 0)
|
|
22952
22937
|
);
|
|
22953
22938
|
if (r) hostsInText(r.text, hosts);
|
|
22954
22939
|
}
|
|
@@ -23005,17 +22990,17 @@ var init_registries = __esm({
|
|
|
23005
22990
|
});
|
|
23006
22991
|
|
|
23007
22992
|
// src/utils/provenance.ts
|
|
23008
|
-
import
|
|
23009
|
-
import
|
|
23010
|
-
import
|
|
22993
|
+
import fs20 from "fs";
|
|
22994
|
+
import path21 from "path";
|
|
22995
|
+
import os16 from "os";
|
|
23011
22996
|
function findInPath(cmd) {
|
|
23012
|
-
if (
|
|
22997
|
+
if (path21.posix.isAbsolute(cmd)) return cmd;
|
|
23013
22998
|
const pathEnv = process.env.PATH ?? "";
|
|
23014
|
-
for (const dir2 of pathEnv.split(
|
|
22999
|
+
for (const dir2 of pathEnv.split(path21.delimiter)) {
|
|
23015
23000
|
if (!dir2) continue;
|
|
23016
|
-
const full =
|
|
23001
|
+
const full = path21.join(dir2, cmd);
|
|
23017
23002
|
try {
|
|
23018
|
-
|
|
23003
|
+
fs20.accessSync(full, fs20.constants.X_OK);
|
|
23019
23004
|
return full;
|
|
23020
23005
|
} catch {
|
|
23021
23006
|
}
|
|
@@ -23026,7 +23011,7 @@ function _classifyPath(resolved, cwd) {
|
|
|
23026
23011
|
if (cwd && resolved.startsWith(cwd + "/")) {
|
|
23027
23012
|
return { trustLevel: "user", reason: "binary in project directory" };
|
|
23028
23013
|
}
|
|
23029
|
-
const osTmp =
|
|
23014
|
+
const osTmp = os16.tmpdir();
|
|
23030
23015
|
const allSuspect = osTmp ? [...SUSPECT_PREFIXES, osTmp] : SUSPECT_PREFIXES;
|
|
23031
23016
|
if (allSuspect.some((p) => resolved === p || resolved.startsWith(p + "/"))) {
|
|
23032
23017
|
return { trustLevel: "suspect", reason: `binary in temp directory: ${resolved}` };
|
|
@@ -23044,7 +23029,7 @@ function _classifyPath(resolved, cwd) {
|
|
|
23044
23029
|
}
|
|
23045
23030
|
function checkProvenance(cmd, cwd) {
|
|
23046
23031
|
const bare = cmd.startsWith("./") ? cmd.slice(2) : cmd;
|
|
23047
|
-
if (
|
|
23032
|
+
if (path21.posix.isAbsolute(bare)) {
|
|
23048
23033
|
const early = _classifyPath(bare, cwd);
|
|
23049
23034
|
if (early.trustLevel === "suspect") {
|
|
23050
23035
|
return { resolvedPath: bare, ...early };
|
|
@@ -23060,7 +23045,7 @@ function checkProvenance(cmd, cwd) {
|
|
|
23060
23045
|
reason: "binary not found in PATH"
|
|
23061
23046
|
};
|
|
23062
23047
|
}
|
|
23063
|
-
resolved =
|
|
23048
|
+
resolved = fs20.realpathSync(found);
|
|
23064
23049
|
} catch {
|
|
23065
23050
|
return {
|
|
23066
23051
|
resolvedPath: cmd,
|
|
@@ -23069,7 +23054,7 @@ function checkProvenance(cmd, cwd) {
|
|
|
23069
23054
|
};
|
|
23070
23055
|
}
|
|
23071
23056
|
try {
|
|
23072
|
-
const stat =
|
|
23057
|
+
const stat = fs20.statSync(resolved);
|
|
23073
23058
|
if (stat.mode & 2) {
|
|
23074
23059
|
return {
|
|
23075
23060
|
resolvedPath: resolved,
|
|
@@ -23094,19 +23079,19 @@ var init_provenance2 = __esm({
|
|
|
23094
23079
|
SYSTEM_PREFIXES = ["/usr/bin", "/usr/sbin", "/bin", "/sbin"];
|
|
23095
23080
|
MANAGED_PREFIXES = ["/usr/local/bin", "/opt/homebrew", "/home/linuxbrew", "/nix/store"];
|
|
23096
23081
|
USER_PREFIXES = [
|
|
23097
|
-
|
|
23098
|
-
|
|
23099
|
-
|
|
23100
|
-
|
|
23101
|
-
|
|
23082
|
+
path21.join(os16.homedir(), "bin"),
|
|
23083
|
+
path21.join(os16.homedir(), ".local", "bin"),
|
|
23084
|
+
path21.join(os16.homedir(), ".cargo", "bin"),
|
|
23085
|
+
path21.join(os16.homedir(), ".npm-global", "bin"),
|
|
23086
|
+
path21.join(os16.homedir(), ".volta", "bin")
|
|
23102
23087
|
];
|
|
23103
23088
|
SUSPECT_PREFIXES = ["/tmp", "/var/tmp", "/dev/shm"];
|
|
23104
23089
|
}
|
|
23105
23090
|
});
|
|
23106
23091
|
|
|
23107
23092
|
// src/policy/index.ts
|
|
23108
|
-
import
|
|
23109
|
-
import
|
|
23093
|
+
import fs21 from "fs";
|
|
23094
|
+
import path22 from "path";
|
|
23110
23095
|
async function evaluatePolicy2(toolName, args, agent, cwd, opts) {
|
|
23111
23096
|
const config = opts?.config ?? getConfig(cwd);
|
|
23112
23097
|
const prepared = opts?.fileAccess ?? prepareFileAccesses(toolName, args, cwd, inspectionLayers(config.policy));
|
|
@@ -23138,9 +23123,9 @@ async function evaluatePolicy2(toolName, args, agent, cwd, opts) {
|
|
|
23138
23123
|
);
|
|
23139
23124
|
}
|
|
23140
23125
|
function isGitWorkTreeTop(dir2, cwd) {
|
|
23141
|
-
if (!
|
|
23126
|
+
if (!path22.isAbsolute(cwd)) return true;
|
|
23142
23127
|
try {
|
|
23143
|
-
return
|
|
23128
|
+
return fs21.existsSync(path22.join(path22.resolve(cwd, dir2), ".git"));
|
|
23144
23129
|
} catch {
|
|
23145
23130
|
return true;
|
|
23146
23131
|
}
|
|
@@ -23149,7 +23134,7 @@ function readAgentSettings(absPath) {
|
|
|
23149
23134
|
const r = readCappedText(
|
|
23150
23135
|
absPath,
|
|
23151
23136
|
MAX_AGENT_SETTINGS_BYTES,
|
|
23152
|
-
|
|
23137
|
+
fs21.constants.O_RDONLY | (fs21.constants.O_NONBLOCK ?? 0)
|
|
23153
23138
|
);
|
|
23154
23139
|
return r && !r.truncated ? r.text : null;
|
|
23155
23140
|
}
|
|
@@ -23218,14 +23203,14 @@ var init_gate = __esm({
|
|
|
23218
23203
|
});
|
|
23219
23204
|
|
|
23220
23205
|
// src/posture/supply-chain.ts
|
|
23221
|
-
import
|
|
23222
|
-
import
|
|
23206
|
+
import os17 from "os";
|
|
23207
|
+
import path23 from "path";
|
|
23223
23208
|
import { parse as parseToml6 } from "smol-toml";
|
|
23224
23209
|
function isNode9Managed(command, args = []) {
|
|
23225
23210
|
if (!command) return false;
|
|
23226
|
-
if (
|
|
23227
|
-
if (PACKAGE_RUNNERS.has(
|
|
23228
|
-
return args.some((a) => a === "node9" ||
|
|
23211
|
+
if (path23.basename(command).toLowerCase() === "node9") return true;
|
|
23212
|
+
if (PACKAGE_RUNNERS.has(path23.basename(command).toLowerCase())) {
|
|
23213
|
+
return args.some((a) => a === "node9" || path23.basename(a).toLowerCase() === "node9");
|
|
23229
23214
|
}
|
|
23230
23215
|
return false;
|
|
23231
23216
|
}
|
|
@@ -23247,10 +23232,10 @@ function readServers(file2, format, agent) {
|
|
|
23247
23232
|
}
|
|
23248
23233
|
}
|
|
23249
23234
|
function checkSupplyChain(ctx) {
|
|
23250
|
-
const home = ctx.home ||
|
|
23235
|
+
const home = ctx.home || os17.homedir();
|
|
23251
23236
|
const servers = [];
|
|
23252
23237
|
for (const spec of AGENT_SPECS) {
|
|
23253
|
-
if (!spec.mcpFile) continue;
|
|
23238
|
+
if (!spec.mcpFile || spec.mcpInventory === false) continue;
|
|
23254
23239
|
servers.push(...readServers(spec.mcpFile(home), spec.mcpFormat ?? "json", spec.label));
|
|
23255
23240
|
}
|
|
23256
23241
|
if (servers.length === 0) return [];
|
|
@@ -23346,11 +23331,11 @@ var init_privilege = __esm({
|
|
|
23346
23331
|
});
|
|
23347
23332
|
|
|
23348
23333
|
// src/posture/containment.ts
|
|
23349
|
-
import
|
|
23334
|
+
import fs22 from "fs";
|
|
23350
23335
|
function inContainer() {
|
|
23351
|
-
if (
|
|
23336
|
+
if (fs22.existsSync("/.dockerenv") || fs22.existsSync("/run/.containerenv")) return true;
|
|
23352
23337
|
try {
|
|
23353
|
-
const cgroup =
|
|
23338
|
+
const cgroup = fs22.readFileSync("/proc/1/cgroup", "utf8");
|
|
23354
23339
|
if (/docker|kubepods|containerd|lxc|libpod/.test(cgroup)) return true;
|
|
23355
23340
|
} catch {
|
|
23356
23341
|
}
|
|
@@ -23396,7 +23381,7 @@ var init_containment = __esm({
|
|
|
23396
23381
|
});
|
|
23397
23382
|
|
|
23398
23383
|
// src/posture/inbound.ts
|
|
23399
|
-
import
|
|
23384
|
+
import fs23 from "fs";
|
|
23400
23385
|
function buildNetworkFix(labels) {
|
|
23401
23386
|
const shielded = [
|
|
23402
23387
|
...new Map(
|
|
@@ -23454,7 +23439,7 @@ function collectListeners() {
|
|
|
23454
23439
|
const byPort = /* @__PURE__ */ new Map();
|
|
23455
23440
|
for (const file2 of ["/proc/net/tcp", "/proc/net/tcp6"]) {
|
|
23456
23441
|
try {
|
|
23457
|
-
for (const l of parseListeners(
|
|
23442
|
+
for (const l of parseListeners(fs23.readFileSync(file2, "utf8"))) {
|
|
23458
23443
|
if (!byPort.has(l.port)) byPort.set(l.port, l);
|
|
23459
23444
|
}
|
|
23460
23445
|
} catch {
|
|
@@ -23466,11 +23451,11 @@ function readProc(pid) {
|
|
|
23466
23451
|
let comm = "unknown";
|
|
23467
23452
|
let cmdline = "";
|
|
23468
23453
|
try {
|
|
23469
|
-
comm =
|
|
23454
|
+
comm = fs23.readFileSync(`/proc/${pid}/comm`, "utf8").trim().replace(/-MainThread$/, "") || "unknown";
|
|
23470
23455
|
} catch {
|
|
23471
23456
|
}
|
|
23472
23457
|
try {
|
|
23473
|
-
cmdline =
|
|
23458
|
+
cmdline = fs23.readFileSync(`/proc/${pid}/cmdline`).toString().replace(/\0/g, " ").trim();
|
|
23474
23459
|
} catch {
|
|
23475
23460
|
}
|
|
23476
23461
|
return { comm, cmdline };
|
|
@@ -23480,21 +23465,21 @@ function resolveProcesses(inodes) {
|
|
|
23480
23465
|
if (inodes.size === 0) return map;
|
|
23481
23466
|
let pids;
|
|
23482
23467
|
try {
|
|
23483
|
-
pids =
|
|
23468
|
+
pids = fs23.readdirSync("/proc").filter((d) => /^\d+$/.test(d));
|
|
23484
23469
|
} catch {
|
|
23485
23470
|
return map;
|
|
23486
23471
|
}
|
|
23487
23472
|
for (const pid of pids) {
|
|
23488
23473
|
let fds;
|
|
23489
23474
|
try {
|
|
23490
|
-
fds =
|
|
23475
|
+
fds = fs23.readdirSync(`/proc/${pid}/fd`);
|
|
23491
23476
|
} catch {
|
|
23492
23477
|
continue;
|
|
23493
23478
|
}
|
|
23494
23479
|
for (const fd of fds) {
|
|
23495
23480
|
let link;
|
|
23496
23481
|
try {
|
|
23497
|
-
link =
|
|
23482
|
+
link = fs23.readlinkSync(`/proc/${pid}/fd/${fd}`);
|
|
23498
23483
|
} catch {
|
|
23499
23484
|
continue;
|
|
23500
23485
|
}
|
|
@@ -23599,9 +23584,9 @@ var init_inbound = __esm({
|
|
|
23599
23584
|
});
|
|
23600
23585
|
|
|
23601
23586
|
// src/posture/coverage.ts
|
|
23602
|
-
import
|
|
23587
|
+
import os18 from "os";
|
|
23603
23588
|
function checkCoverage(ctx) {
|
|
23604
|
-
const home = ctx.home ||
|
|
23589
|
+
const home = ctx.home || os18.homedir();
|
|
23605
23590
|
const findings = [];
|
|
23606
23591
|
const protectedAgents = getAgentWiring(home).filter((r) => r.isProtected);
|
|
23607
23592
|
if (protectedAgents.length === 0) {
|
|
@@ -23645,7 +23630,7 @@ var init_coverage = __esm({
|
|
|
23645
23630
|
});
|
|
23646
23631
|
|
|
23647
23632
|
// src/posture/governance.ts
|
|
23648
|
-
import
|
|
23633
|
+
import path24 from "path";
|
|
23649
23634
|
function checkData(ctx) {
|
|
23650
23635
|
const dlp = getConfig(ctx.cwd).policy.dlp;
|
|
23651
23636
|
if (!dlp?.enabled) {
|
|
@@ -23789,7 +23774,7 @@ var init_governance = __esm({
|
|
|
23789
23774
|
"src/posture/governance.ts"() {
|
|
23790
23775
|
"use strict";
|
|
23791
23776
|
init_config();
|
|
23792
|
-
jailProbePath = (home) =>
|
|
23777
|
+
jailProbePath = (home) => path24.join(home, ".aws", "credentials");
|
|
23793
23778
|
}
|
|
23794
23779
|
});
|
|
23795
23780
|
|
|
@@ -23968,7 +23953,7 @@ var init_enforcement = __esm({
|
|
|
23968
23953
|
});
|
|
23969
23954
|
|
|
23970
23955
|
// src/posture/index.ts
|
|
23971
|
-
import
|
|
23956
|
+
import os19 from "os";
|
|
23972
23957
|
function dropEnforcementRedundant(findings) {
|
|
23973
23958
|
const coveragePresent = findings.some((f) => f.category === "Coverage");
|
|
23974
23959
|
if (!coveragePresent) return findings;
|
|
@@ -23994,9 +23979,10 @@ async function runChecks(checks, ctx) {
|
|
|
23994
23979
|
}
|
|
23995
23980
|
async function runPosture(opts = {}) {
|
|
23996
23981
|
const ctx = {
|
|
23997
|
-
home: opts.home ??
|
|
23982
|
+
home: opts.home ?? os19.homedir(),
|
|
23998
23983
|
cwd: opts.cwd ?? process.cwd(),
|
|
23999
|
-
agent: opts.agent
|
|
23984
|
+
agent: opts.agent,
|
|
23985
|
+
env: opts.env
|
|
24000
23986
|
};
|
|
24001
23987
|
const {
|
|
24002
23988
|
findings: rawFindings,
|
|
@@ -24055,6 +24041,102 @@ var init_posture = __esm({
|
|
|
24055
24041
|
}
|
|
24056
24042
|
});
|
|
24057
24043
|
|
|
24044
|
+
// src/posture/render.ts
|
|
24045
|
+
import chalk2 from "chalk";
|
|
24046
|
+
var ICON, TIER_LABEL;
|
|
24047
|
+
var init_render = __esm({
|
|
24048
|
+
"src/posture/render.ts"() {
|
|
24049
|
+
"use strict";
|
|
24050
|
+
init_score();
|
|
24051
|
+
ICON = {
|
|
24052
|
+
critical: chalk2.red("\u274C"),
|
|
24053
|
+
high: chalk2.red("\u274C"),
|
|
24054
|
+
medium: chalk2.yellow("\u26A0\uFE0F "),
|
|
24055
|
+
advisory: chalk2.gray("\u26A0\uFE0F ")
|
|
24056
|
+
};
|
|
24057
|
+
TIER_LABEL = {
|
|
24058
|
+
good: chalk2.green("Good"),
|
|
24059
|
+
"at-risk": chalk2.yellow("At risk"),
|
|
24060
|
+
critical: chalk2.red("Critical")
|
|
24061
|
+
};
|
|
24062
|
+
}
|
|
24063
|
+
});
|
|
24064
|
+
|
|
24065
|
+
// src/cli/commands/blast.ts
|
|
24066
|
+
import chalk3 from "chalk";
|
|
24067
|
+
import fs24 from "fs";
|
|
24068
|
+
import path25 from "path";
|
|
24069
|
+
import os20 from "os";
|
|
24070
|
+
function buildSensitivePaths(home, cwd) {
|
|
24071
|
+
const homeFiles = homeCredentialFiles(home).map(({ full, label: label2, description, score }) => ({
|
|
24072
|
+
full,
|
|
24073
|
+
label: label2,
|
|
24074
|
+
description,
|
|
24075
|
+
score
|
|
24076
|
+
}));
|
|
24077
|
+
return [
|
|
24078
|
+
...homeFiles,
|
|
24079
|
+
{
|
|
24080
|
+
full: path25.join(cwd, ".env"),
|
|
24081
|
+
label: ".env (current folder)",
|
|
24082
|
+
description: "App secrets: database passwords, API keys",
|
|
24083
|
+
score: 20
|
|
24084
|
+
},
|
|
24085
|
+
{
|
|
24086
|
+
full: path25.join(cwd, ".env.local"),
|
|
24087
|
+
label: ".env.local (current folder)",
|
|
24088
|
+
description: "Local overrides: often contains real credentials",
|
|
24089
|
+
score: 15
|
|
24090
|
+
},
|
|
24091
|
+
{
|
|
24092
|
+
full: path25.join(cwd, ".env.production"),
|
|
24093
|
+
label: ".env.production (current folder)",
|
|
24094
|
+
description: "Production secrets",
|
|
24095
|
+
score: 20
|
|
24096
|
+
}
|
|
24097
|
+
];
|
|
24098
|
+
}
|
|
24099
|
+
function isReadable(filePath) {
|
|
24100
|
+
try {
|
|
24101
|
+
fs24.accessSync(filePath, fs24.constants.R_OK);
|
|
24102
|
+
return true;
|
|
24103
|
+
} catch {
|
|
24104
|
+
return false;
|
|
24105
|
+
}
|
|
24106
|
+
}
|
|
24107
|
+
function runBlast() {
|
|
24108
|
+
const home = os20.homedir();
|
|
24109
|
+
const cwd = process.cwd();
|
|
24110
|
+
const paths = buildSensitivePaths(home, cwd);
|
|
24111
|
+
let scoreDeduction = 0;
|
|
24112
|
+
const reachable = [];
|
|
24113
|
+
for (const p of paths) {
|
|
24114
|
+
if (fs24.existsSync(p.full) && isReadable(p.full)) {
|
|
24115
|
+
reachable.push(p);
|
|
24116
|
+
scoreDeduction += p.score;
|
|
24117
|
+
}
|
|
24118
|
+
}
|
|
24119
|
+
const envFindings = [];
|
|
24120
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
24121
|
+
if (!value) continue;
|
|
24122
|
+
const match = scanArgs({ [key]: value });
|
|
24123
|
+
if (match) {
|
|
24124
|
+
envFindings.push({ key, patternName: match.patternName });
|
|
24125
|
+
scoreDeduction += 10;
|
|
24126
|
+
}
|
|
24127
|
+
}
|
|
24128
|
+
return { reachable, envFindings, score: Math.max(0, 100 - scoreDeduction) };
|
|
24129
|
+
}
|
|
24130
|
+
var init_blast = __esm({
|
|
24131
|
+
"src/cli/commands/blast.ts"() {
|
|
24132
|
+
"use strict";
|
|
24133
|
+
init_dlp();
|
|
24134
|
+
init_credential_files();
|
|
24135
|
+
init_posture();
|
|
24136
|
+
init_render();
|
|
24137
|
+
}
|
|
24138
|
+
});
|
|
24139
|
+
|
|
24058
24140
|
// src/auth/decision-record.ts
|
|
24059
24141
|
function personRecord(channel, decision, extra = {}, now = Date.now()) {
|
|
24060
24142
|
return {
|
|
@@ -25535,7 +25617,7 @@ var init_report_audit = __esm({
|
|
|
25535
25617
|
});
|
|
25536
25618
|
|
|
25537
25619
|
// src/config/keyed-guard.ts
|
|
25538
|
-
import
|
|
25620
|
+
import chalk4 from "chalk";
|
|
25539
25621
|
function isKeyedForPolicy() {
|
|
25540
25622
|
try {
|
|
25541
25623
|
return getConfig().policySource === "workspace";
|
|
@@ -29344,7 +29426,7 @@ var init_scan_summary = __esm({
|
|
|
29344
29426
|
});
|
|
29345
29427
|
|
|
29346
29428
|
// src/cli/render/scan-derive.ts
|
|
29347
|
-
import
|
|
29429
|
+
import chalk5 from "chalk";
|
|
29348
29430
|
import stringWidth from "string-width";
|
|
29349
29431
|
var init_scan_derive = __esm({
|
|
29350
29432
|
"src/cli/render/scan-derive.ts"() {
|
|
@@ -29363,7 +29445,6 @@ var init_protection = __esm({
|
|
|
29363
29445
|
var init_scan_json = __esm({
|
|
29364
29446
|
"src/cli/render/scan-json.ts"() {
|
|
29365
29447
|
"use strict";
|
|
29366
|
-
init_scan_derive();
|
|
29367
29448
|
}
|
|
29368
29449
|
});
|
|
29369
29450
|
|
|
@@ -29376,7 +29457,7 @@ var init_scan_history = __esm({
|
|
|
29376
29457
|
});
|
|
29377
29458
|
|
|
29378
29459
|
// src/cli/commands/scan.ts
|
|
29379
|
-
import
|
|
29460
|
+
import chalk6 from "chalk";
|
|
29380
29461
|
import fs43 from "fs";
|
|
29381
29462
|
import path46 from "path";
|
|
29382
29463
|
import os35 from "os";
|
|
@@ -30721,7 +30802,7 @@ var init_scan = __esm({
|
|
|
30721
30802
|
init_hook_payload();
|
|
30722
30803
|
init_dist();
|
|
30723
30804
|
init_scan_summary();
|
|
30724
|
-
|
|
30805
|
+
init_agent_wiring();
|
|
30725
30806
|
init_blast();
|
|
30726
30807
|
init_scan_derive();
|
|
30727
30808
|
init_protection();
|