@node9/proxy 1.0.19 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/cli.js +518 -235
- package/dist/cli.mjs +524 -241
- package/dist/index.js +197 -54
- package/dist/index.mjs +197 -54
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -37,13 +37,14 @@ module.exports = __toCommonJS(src_exports);
|
|
|
37
37
|
// src/core.ts
|
|
38
38
|
var import_chalk2 = __toESM(require("chalk"));
|
|
39
39
|
var import_prompts = require("@inquirer/prompts");
|
|
40
|
-
var
|
|
41
|
-
var
|
|
40
|
+
var import_fs3 = __toESM(require("fs"));
|
|
41
|
+
var import_path5 = __toESM(require("path"));
|
|
42
42
|
var import_os2 = __toESM(require("os"));
|
|
43
43
|
var import_net = __toESM(require("net"));
|
|
44
44
|
var import_crypto = require("crypto");
|
|
45
45
|
var import_child_process2 = require("child_process");
|
|
46
46
|
var import_picomatch = __toESM(require("picomatch"));
|
|
47
|
+
var import_safe_regex2 = __toESM(require("safe-regex2"));
|
|
47
48
|
var import_sh_syntax = require("sh-syntax");
|
|
48
49
|
|
|
49
50
|
// src/ui/native.ts
|
|
@@ -465,8 +466,8 @@ function sanitizeConfig(raw) {
|
|
|
465
466
|
}
|
|
466
467
|
}
|
|
467
468
|
const lines = result.error.issues.map((issue) => {
|
|
468
|
-
const
|
|
469
|
-
return ` \u2022 ${
|
|
469
|
+
const path6 = issue.path.length > 0 ? issue.path.join(".") : "root";
|
|
470
|
+
return ` \u2022 ${path6}: ${issue.message}`;
|
|
470
471
|
});
|
|
471
472
|
return {
|
|
472
473
|
sanitized,
|
|
@@ -679,6 +680,8 @@ function readActiveShields() {
|
|
|
679
680
|
}
|
|
680
681
|
|
|
681
682
|
// src/dlp.ts
|
|
683
|
+
var import_fs2 = __toESM(require("fs"));
|
|
684
|
+
var import_path4 = __toESM(require("path"));
|
|
682
685
|
var DLP_PATTERNS = [
|
|
683
686
|
{ name: "AWS Access Key ID", regex: /\bAKIA[0-9A-Z]{16}\b/, severity: "block" },
|
|
684
687
|
{ name: "GitHub Token", regex: /\bgh[pous]_[A-Za-z0-9]{36}\b/, severity: "block" },
|
|
@@ -690,8 +693,76 @@ var DLP_PATTERNS = [
|
|
|
690
693
|
regex: /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/,
|
|
691
694
|
severity: "block"
|
|
692
695
|
},
|
|
696
|
+
// GCP service account JSON (detects the type field that uniquely identifies it)
|
|
697
|
+
{
|
|
698
|
+
name: "GCP Service Account",
|
|
699
|
+
regex: /"type"\s*:\s*"service_account"/,
|
|
700
|
+
severity: "block"
|
|
701
|
+
},
|
|
702
|
+
// NPM auth token in .npmrc format
|
|
703
|
+
{
|
|
704
|
+
name: "NPM Auth Token",
|
|
705
|
+
regex: /_authToken\s*=\s*[A-Za-z0-9_\-]{20,}/,
|
|
706
|
+
severity: "block"
|
|
707
|
+
},
|
|
693
708
|
{ name: "Bearer Token", regex: /Bearer\s+[a-zA-Z0-9\-._~+/]+=*/i, severity: "review" }
|
|
694
709
|
];
|
|
710
|
+
var SENSITIVE_PATH_PATTERNS = [
|
|
711
|
+
/[/\\]\.ssh[/\\]/i,
|
|
712
|
+
/[/\\]\.aws[/\\]/i,
|
|
713
|
+
/[/\\]\.config[/\\]gcloud[/\\]/i,
|
|
714
|
+
/[/\\]\.azure[/\\]/i,
|
|
715
|
+
/[/\\]\.kube[/\\]config$/i,
|
|
716
|
+
/[/\\]\.env($|\.)/i,
|
|
717
|
+
// .env, .env.local, .env.production — not .envoy
|
|
718
|
+
/[/\\]\.git-credentials$/i,
|
|
719
|
+
/[/\\]\.npmrc$/i,
|
|
720
|
+
/[/\\]\.docker[/\\]config\.json$/i,
|
|
721
|
+
/[/\\][^/\\]+\.pem$/i,
|
|
722
|
+
/[/\\][^/\\]+\.key$/i,
|
|
723
|
+
/[/\\][^/\\]+\.p12$/i,
|
|
724
|
+
/[/\\][^/\\]+\.pfx$/i,
|
|
725
|
+
/^\/etc\/passwd$/,
|
|
726
|
+
/^\/etc\/shadow$/,
|
|
727
|
+
/^\/etc\/sudoers$/,
|
|
728
|
+
/[/\\]credentials\.json$/i,
|
|
729
|
+
/[/\\]id_rsa$/i,
|
|
730
|
+
/[/\\]id_ed25519$/i,
|
|
731
|
+
/[/\\]id_ecdsa$/i
|
|
732
|
+
];
|
|
733
|
+
function scanFilePath(filePath, cwd = process.cwd()) {
|
|
734
|
+
if (!filePath) return null;
|
|
735
|
+
let resolved;
|
|
736
|
+
try {
|
|
737
|
+
const absolute = import_path4.default.resolve(cwd, filePath);
|
|
738
|
+
resolved = import_fs2.default.realpathSync.native(absolute);
|
|
739
|
+
} catch (err) {
|
|
740
|
+
const code = err.code;
|
|
741
|
+
if (code === "ENOENT" || code === "ENOTDIR") {
|
|
742
|
+
resolved = import_path4.default.resolve(cwd, filePath);
|
|
743
|
+
} else {
|
|
744
|
+
return {
|
|
745
|
+
patternName: "Sensitive File Path",
|
|
746
|
+
fieldPath: "file_path",
|
|
747
|
+
redactedSample: filePath,
|
|
748
|
+
severity: "block"
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
const normalised = resolved.replace(/\\/g, "/");
|
|
753
|
+
for (const pattern of SENSITIVE_PATH_PATTERNS) {
|
|
754
|
+
if (pattern.test(normalised)) {
|
|
755
|
+
return {
|
|
756
|
+
patternName: "Sensitive File Path",
|
|
757
|
+
fieldPath: "file_path",
|
|
758
|
+
redactedSample: filePath,
|
|
759
|
+
// show original path in alert, not resolved
|
|
760
|
+
severity: "block"
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
return null;
|
|
765
|
+
}
|
|
695
766
|
function maskSecret(raw, pattern) {
|
|
696
767
|
const match = raw.match(pattern);
|
|
697
768
|
if (!match) return "****";
|
|
@@ -749,17 +820,17 @@ function scanArgs(args, depth = 0, fieldPath = "args") {
|
|
|
749
820
|
}
|
|
750
821
|
|
|
751
822
|
// src/core.ts
|
|
752
|
-
var PAUSED_FILE =
|
|
753
|
-
var TRUST_FILE =
|
|
754
|
-
var LOCAL_AUDIT_LOG =
|
|
755
|
-
var HOOK_DEBUG_LOG =
|
|
823
|
+
var PAUSED_FILE = import_path5.default.join(import_os2.default.homedir(), ".node9", "PAUSED");
|
|
824
|
+
var TRUST_FILE = import_path5.default.join(import_os2.default.homedir(), ".node9", "trust.json");
|
|
825
|
+
var LOCAL_AUDIT_LOG = import_path5.default.join(import_os2.default.homedir(), ".node9", "audit.log");
|
|
826
|
+
var HOOK_DEBUG_LOG = import_path5.default.join(import_os2.default.homedir(), ".node9", "hook-debug.log");
|
|
756
827
|
function checkPause() {
|
|
757
828
|
try {
|
|
758
|
-
if (!
|
|
759
|
-
const state = JSON.parse(
|
|
829
|
+
if (!import_fs3.default.existsSync(PAUSED_FILE)) return { paused: false };
|
|
830
|
+
const state = JSON.parse(import_fs3.default.readFileSync(PAUSED_FILE, "utf-8"));
|
|
760
831
|
if (state.expiry > 0 && Date.now() >= state.expiry) {
|
|
761
832
|
try {
|
|
762
|
-
|
|
833
|
+
import_fs3.default.unlinkSync(PAUSED_FILE);
|
|
763
834
|
} catch {
|
|
764
835
|
}
|
|
765
836
|
return { paused: false };
|
|
@@ -770,20 +841,93 @@ function checkPause() {
|
|
|
770
841
|
}
|
|
771
842
|
}
|
|
772
843
|
function atomicWriteSync(filePath, data, options) {
|
|
773
|
-
const dir =
|
|
774
|
-
if (!
|
|
844
|
+
const dir = import_path5.default.dirname(filePath);
|
|
845
|
+
if (!import_fs3.default.existsSync(dir)) import_fs3.default.mkdirSync(dir, { recursive: true });
|
|
775
846
|
const tmpPath = `${filePath}.${import_os2.default.hostname()}.${process.pid}.tmp`;
|
|
776
|
-
|
|
777
|
-
|
|
847
|
+
import_fs3.default.writeFileSync(tmpPath, data, options);
|
|
848
|
+
import_fs3.default.renameSync(tmpPath, filePath);
|
|
849
|
+
}
|
|
850
|
+
var MAX_REGEX_LENGTH = 100;
|
|
851
|
+
var REGEX_CACHE_MAX = 500;
|
|
852
|
+
var regexCache = /* @__PURE__ */ new Map();
|
|
853
|
+
function validateRegex(pattern) {
|
|
854
|
+
if (!pattern) return "Pattern is required";
|
|
855
|
+
if (pattern.length > MAX_REGEX_LENGTH) return `Pattern exceeds max length of ${MAX_REGEX_LENGTH}`;
|
|
856
|
+
let parens = 0, brackets = 0, isEscaped = false, inCharClass = false;
|
|
857
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
858
|
+
const char = pattern[i];
|
|
859
|
+
if (isEscaped) {
|
|
860
|
+
isEscaped = false;
|
|
861
|
+
continue;
|
|
862
|
+
}
|
|
863
|
+
if (char === "\\") {
|
|
864
|
+
isEscaped = true;
|
|
865
|
+
continue;
|
|
866
|
+
}
|
|
867
|
+
if (char === "[" && !inCharClass) {
|
|
868
|
+
inCharClass = true;
|
|
869
|
+
brackets++;
|
|
870
|
+
continue;
|
|
871
|
+
}
|
|
872
|
+
if (char === "]" && inCharClass) {
|
|
873
|
+
inCharClass = false;
|
|
874
|
+
brackets--;
|
|
875
|
+
continue;
|
|
876
|
+
}
|
|
877
|
+
if (inCharClass) continue;
|
|
878
|
+
if (char === "(") parens++;
|
|
879
|
+
else if (char === ")") parens--;
|
|
880
|
+
}
|
|
881
|
+
if (parens !== 0) return "Unbalanced parentheses";
|
|
882
|
+
if (brackets !== 0) return "Unbalanced brackets";
|
|
883
|
+
if (/\\\d+[*+{]/.test(pattern)) return "Quantified backreferences are forbidden (ReDoS risk)";
|
|
884
|
+
if (!(0, import_safe_regex2.default)(pattern)) return "Pattern rejected: potential ReDoS vulnerability detected";
|
|
885
|
+
try {
|
|
886
|
+
new RegExp(pattern);
|
|
887
|
+
} catch (e) {
|
|
888
|
+
return `Invalid regex syntax: ${e.message}`;
|
|
889
|
+
}
|
|
890
|
+
return null;
|
|
891
|
+
}
|
|
892
|
+
function getCompiledRegex(pattern, flags = "") {
|
|
893
|
+
if (flags && !/^[gimsuy]+$/.test(flags)) {
|
|
894
|
+
if (process.env.NODE9_DEBUG === "1") console.error(`[Node9] Invalid regex flags: "${flags}"`);
|
|
895
|
+
return null;
|
|
896
|
+
}
|
|
897
|
+
const key = `${pattern}\0${flags}`;
|
|
898
|
+
if (regexCache.has(key)) {
|
|
899
|
+
const cached = regexCache.get(key);
|
|
900
|
+
regexCache.delete(key);
|
|
901
|
+
regexCache.set(key, cached);
|
|
902
|
+
return cached;
|
|
903
|
+
}
|
|
904
|
+
const err = validateRegex(pattern);
|
|
905
|
+
if (err) {
|
|
906
|
+
if (process.env.NODE9_DEBUG === "1")
|
|
907
|
+
console.error(`[Node9] Regex blocked: ${err} \u2014 pattern: "${pattern}"`);
|
|
908
|
+
return null;
|
|
909
|
+
}
|
|
910
|
+
try {
|
|
911
|
+
const re = new RegExp(pattern, flags);
|
|
912
|
+
if (regexCache.size >= REGEX_CACHE_MAX) {
|
|
913
|
+
const oldest = regexCache.keys().next().value;
|
|
914
|
+
if (oldest) regexCache.delete(oldest);
|
|
915
|
+
}
|
|
916
|
+
regexCache.set(key, re);
|
|
917
|
+
return re;
|
|
918
|
+
} catch (e) {
|
|
919
|
+
if (process.env.NODE9_DEBUG === "1") console.error(`[Node9] Regex compile failed:`, e);
|
|
920
|
+
return null;
|
|
921
|
+
}
|
|
778
922
|
}
|
|
779
923
|
function getActiveTrustSession(toolName) {
|
|
780
924
|
try {
|
|
781
|
-
if (!
|
|
782
|
-
const trust = JSON.parse(
|
|
925
|
+
if (!import_fs3.default.existsSync(TRUST_FILE)) return false;
|
|
926
|
+
const trust = JSON.parse(import_fs3.default.readFileSync(TRUST_FILE, "utf-8"));
|
|
783
927
|
const now = Date.now();
|
|
784
928
|
const active = trust.entries.filter((e) => e.expiry > now);
|
|
785
929
|
if (active.length !== trust.entries.length) {
|
|
786
|
-
|
|
930
|
+
import_fs3.default.writeFileSync(TRUST_FILE, JSON.stringify({ entries: active }, null, 2));
|
|
787
931
|
}
|
|
788
932
|
return active.some((e) => e.tool === toolName || matchesPattern(toolName, e.tool));
|
|
789
933
|
} catch {
|
|
@@ -794,8 +938,8 @@ function writeTrustSession(toolName, durationMs) {
|
|
|
794
938
|
try {
|
|
795
939
|
let trust = { entries: [] };
|
|
796
940
|
try {
|
|
797
|
-
if (
|
|
798
|
-
trust = JSON.parse(
|
|
941
|
+
if (import_fs3.default.existsSync(TRUST_FILE)) {
|
|
942
|
+
trust = JSON.parse(import_fs3.default.readFileSync(TRUST_FILE, "utf-8"));
|
|
799
943
|
}
|
|
800
944
|
} catch {
|
|
801
945
|
}
|
|
@@ -811,9 +955,9 @@ function writeTrustSession(toolName, durationMs) {
|
|
|
811
955
|
}
|
|
812
956
|
function appendToLog(logPath, entry) {
|
|
813
957
|
try {
|
|
814
|
-
const dir =
|
|
815
|
-
if (!
|
|
816
|
-
|
|
958
|
+
const dir = import_path5.default.dirname(logPath);
|
|
959
|
+
if (!import_fs3.default.existsSync(dir)) import_fs3.default.mkdirSync(dir, { recursive: true });
|
|
960
|
+
import_fs3.default.appendFileSync(logPath, JSON.stringify(entry) + "\n");
|
|
817
961
|
} catch {
|
|
818
962
|
}
|
|
819
963
|
}
|
|
@@ -855,9 +999,9 @@ function matchesPattern(text, patterns) {
|
|
|
855
999
|
const withoutDotSlash = text.replace(/^\.\//, "");
|
|
856
1000
|
return isMatch(withoutDotSlash) || isMatch(`./${withoutDotSlash}`);
|
|
857
1001
|
}
|
|
858
|
-
function getNestedValue(obj,
|
|
1002
|
+
function getNestedValue(obj, path6) {
|
|
859
1003
|
if (!obj || typeof obj !== "object") return null;
|
|
860
|
-
return
|
|
1004
|
+
return path6.split(".").reduce((prev, curr) => prev?.[curr], obj);
|
|
861
1005
|
}
|
|
862
1006
|
function evaluateSmartConditions(args, rule) {
|
|
863
1007
|
if (!rule.conditions || rule.conditions.length === 0) return true;
|
|
@@ -876,19 +1020,16 @@ function evaluateSmartConditions(args, rule) {
|
|
|
876
1020
|
return val !== null && cond.value ? !val.includes(cond.value) : true;
|
|
877
1021
|
case "matches": {
|
|
878
1022
|
if (val === null || !cond.value) return false;
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
return false;
|
|
883
|
-
}
|
|
1023
|
+
const reM = getCompiledRegex(cond.value, cond.flags ?? "");
|
|
1024
|
+
if (!reM) return false;
|
|
1025
|
+
return reM.test(val);
|
|
884
1026
|
}
|
|
885
1027
|
case "notMatches": {
|
|
886
|
-
if (
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
}
|
|
1028
|
+
if (!cond.value) return false;
|
|
1029
|
+
if (val === null) return true;
|
|
1030
|
+
const reN = getCompiledRegex(cond.value, cond.flags ?? "");
|
|
1031
|
+
if (!reN) return false;
|
|
1032
|
+
return !reN.test(val);
|
|
892
1033
|
}
|
|
893
1034
|
case "matchesGlob":
|
|
894
1035
|
return val !== null && cond.value ? import_picomatch.default.isMatch(val, cond.value) : false;
|
|
@@ -1210,9 +1351,9 @@ var ADVISORY_SMART_RULES = [
|
|
|
1210
1351
|
var cachedConfig = null;
|
|
1211
1352
|
function getInternalToken() {
|
|
1212
1353
|
try {
|
|
1213
|
-
const pidFile =
|
|
1214
|
-
if (!
|
|
1215
|
-
const data = JSON.parse(
|
|
1354
|
+
const pidFile = import_path5.default.join(import_os2.default.homedir(), ".node9", "daemon.pid");
|
|
1355
|
+
if (!import_fs3.default.existsSync(pidFile)) return null;
|
|
1356
|
+
const data = JSON.parse(import_fs3.default.readFileSync(pidFile, "utf-8"));
|
|
1216
1357
|
process.kill(data.pid, 0);
|
|
1217
1358
|
return data.internalToken ?? null;
|
|
1218
1359
|
} catch {
|
|
@@ -1332,10 +1473,10 @@ function isIgnoredTool(toolName) {
|
|
|
1332
1473
|
var DAEMON_PORT = 7391;
|
|
1333
1474
|
var DAEMON_HOST = "127.0.0.1";
|
|
1334
1475
|
function isDaemonRunning() {
|
|
1335
|
-
const pidFile =
|
|
1336
|
-
if (
|
|
1476
|
+
const pidFile = import_path5.default.join(import_os2.default.homedir(), ".node9", "daemon.pid");
|
|
1477
|
+
if (import_fs3.default.existsSync(pidFile)) {
|
|
1337
1478
|
try {
|
|
1338
|
-
const { pid, port } = JSON.parse(
|
|
1479
|
+
const { pid, port } = JSON.parse(import_fs3.default.readFileSync(pidFile, "utf-8"));
|
|
1339
1480
|
if (port !== DAEMON_PORT) return false;
|
|
1340
1481
|
process.kill(pid, 0);
|
|
1341
1482
|
return true;
|
|
@@ -1355,9 +1496,9 @@ function isDaemonRunning() {
|
|
|
1355
1496
|
}
|
|
1356
1497
|
function getPersistentDecision(toolName) {
|
|
1357
1498
|
try {
|
|
1358
|
-
const file =
|
|
1359
|
-
if (!
|
|
1360
|
-
const decisions = JSON.parse(
|
|
1499
|
+
const file = import_path5.default.join(import_os2.default.homedir(), ".node9", "decisions.json");
|
|
1500
|
+
if (!import_fs3.default.existsSync(file)) return null;
|
|
1501
|
+
const decisions = JSON.parse(import_fs3.default.readFileSync(file, "utf-8"));
|
|
1361
1502
|
const d = decisions[toolName];
|
|
1362
1503
|
if (d === "allow" || d === "deny") return d;
|
|
1363
1504
|
} catch {
|
|
@@ -1439,7 +1580,7 @@ async function resolveViaDaemon(id, decision, internalToken) {
|
|
|
1439
1580
|
signal: AbortSignal.timeout(3e3)
|
|
1440
1581
|
});
|
|
1441
1582
|
}
|
|
1442
|
-
var ACTIVITY_SOCKET_PATH = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" :
|
|
1583
|
+
var ACTIVITY_SOCKET_PATH = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path5.default.join(import_os2.default.tmpdir(), "node9-activity.sock");
|
|
1443
1584
|
function notifyActivity(data) {
|
|
1444
1585
|
return new Promise((resolve) => {
|
|
1445
1586
|
try {
|
|
@@ -1501,7 +1642,9 @@ async function _authorizeHeadlessCore(toolName, args, allowTerminalFallback = fa
|
|
|
1501
1642
|
let policyMatchedWord;
|
|
1502
1643
|
let riskMetadata;
|
|
1503
1644
|
if (config.policy.dlp.enabled && (!isIgnoredTool(toolName) || config.policy.dlp.scanIgnoredTools)) {
|
|
1504
|
-
const
|
|
1645
|
+
const argsObj = args && typeof args === "object" && !Array.isArray(args) ? args : {};
|
|
1646
|
+
const filePath = String(argsObj.file_path ?? argsObj.path ?? argsObj.filename ?? "");
|
|
1647
|
+
const dlpMatch = (filePath ? scanFilePath(filePath) : null) ?? scanArgs(args);
|
|
1505
1648
|
if (dlpMatch) {
|
|
1506
1649
|
const dlpReason = `\u{1F6A8} DATA LOSS PREVENTION: ${dlpMatch.patternName} detected in field "${dlpMatch.fieldPath}" (${dlpMatch.redactedSample})`;
|
|
1507
1650
|
if (dlpMatch.severity === "block") {
|
|
@@ -1875,8 +2018,8 @@ REASON: Action blocked because no approval channels are available. (Native/Brows
|
|
|
1875
2018
|
}
|
|
1876
2019
|
function getConfig() {
|
|
1877
2020
|
if (cachedConfig) return cachedConfig;
|
|
1878
|
-
const globalPath =
|
|
1879
|
-
const projectPath =
|
|
2021
|
+
const globalPath = import_path5.default.join(import_os2.default.homedir(), ".node9", "config.json");
|
|
2022
|
+
const projectPath = import_path5.default.join(process.cwd(), "node9.config.json");
|
|
1880
2023
|
const globalConfig = tryLoadConfig(globalPath);
|
|
1881
2024
|
const projectConfig = tryLoadConfig(projectPath);
|
|
1882
2025
|
const mergedSettings = {
|
|
@@ -1971,10 +2114,10 @@ function getConfig() {
|
|
|
1971
2114
|
return cachedConfig;
|
|
1972
2115
|
}
|
|
1973
2116
|
function tryLoadConfig(filePath) {
|
|
1974
|
-
if (!
|
|
2117
|
+
if (!import_fs3.default.existsSync(filePath)) return null;
|
|
1975
2118
|
let raw;
|
|
1976
2119
|
try {
|
|
1977
|
-
raw = JSON.parse(
|
|
2120
|
+
raw = JSON.parse(import_fs3.default.readFileSync(filePath, "utf-8"));
|
|
1978
2121
|
} catch (err) {
|
|
1979
2122
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1980
2123
|
process.stderr.write(
|
|
@@ -2036,9 +2179,9 @@ function getCredentials() {
|
|
|
2036
2179
|
};
|
|
2037
2180
|
}
|
|
2038
2181
|
try {
|
|
2039
|
-
const credPath =
|
|
2040
|
-
if (
|
|
2041
|
-
const creds = JSON.parse(
|
|
2182
|
+
const credPath = import_path5.default.join(import_os2.default.homedir(), ".node9", "credentials.json");
|
|
2183
|
+
if (import_fs3.default.existsSync(credPath)) {
|
|
2184
|
+
const creds = JSON.parse(import_fs3.default.readFileSync(credPath, "utf-8"));
|
|
2042
2185
|
const profileName = process.env.NODE9_PROFILE || "default";
|
|
2043
2186
|
const profile = creds[profileName];
|
|
2044
2187
|
if (profile?.apiKey) {
|