@node9/proxy 2.14.2 → 2.15.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.
@@ -1,7 +1,12 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __getOwnPropNames = Object.getOwnPropertyNames;
3
- var __esm = (fn, res) => function __init() {
4
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
3
+ var __esm = (fn, res, err) => function __init() {
4
+ if (err) throw err[0];
5
+ try {
6
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
7
+ } catch (e) {
8
+ throw err = [e], e;
9
+ }
5
10
  };
6
11
  var __export = (target, all) => {
7
12
  for (var name in all)
@@ -4660,6 +4665,51 @@ var init_trusted_hosts = __esm({
4660
4665
  }
4661
4666
  });
4662
4667
 
4668
+ // src/auth/api-url.ts
4669
+ function defaultHostSuffixes() {
4670
+ const host = new URL(DEFAULT_API_URL).hostname.toLowerCase();
4671
+ const parent = host.split(".").slice(1).join(".");
4672
+ return parent.includes(".") ? [host, parent] : [host];
4673
+ }
4674
+ function allowedSuffixes() {
4675
+ const extra = (process.env[HOST_ALLOW_ENV] ?? "").split(",").map(
4676
+ (s) => s.trim().toLowerCase().replace(/^\*?\./, "")
4677
+ ).filter(Boolean);
4678
+ return [...defaultHostSuffixes(), ...extra];
4679
+ }
4680
+ function validateApiUrl(raw) {
4681
+ if (typeof raw !== "string" || raw.length === 0 || raw.length > 2048) return null;
4682
+ let u;
4683
+ try {
4684
+ u = new URL(raw);
4685
+ } catch {
4686
+ return null;
4687
+ }
4688
+ if (u.username || u.password) return null;
4689
+ if (u.protocol !== "https:" && u.protocol !== "http:") return null;
4690
+ const host = u.hostname.toLowerCase();
4691
+ if (LOOPBACK.has(host)) return u;
4692
+ if (u.protocol !== "https:") return null;
4693
+ const suffixes = allowedSuffixes();
4694
+ const ok = suffixes.some((s) => host === s || host.endsWith("." + s));
4695
+ return ok ? u : null;
4696
+ }
4697
+ function safeApiUrl(raw, onReject) {
4698
+ const ok = validateApiUrl(raw);
4699
+ if (ok) return typeof raw === "string" ? raw : ok.toString();
4700
+ onReject?.(raw);
4701
+ return DEFAULT_API_URL;
4702
+ }
4703
+ var DEFAULT_API_URL, LOOPBACK, HOST_ALLOW_ENV;
4704
+ var init_api_url = __esm({
4705
+ "src/auth/api-url.ts"() {
4706
+ "use strict";
4707
+ DEFAULT_API_URL = "https://api.node9.ai/api/v1/intercept";
4708
+ LOOPBACK = /* @__PURE__ */ new Set(["127.0.0.1", "localhost", "::1", "[::1]", "0.0.0.0"]);
4709
+ HOST_ALLOW_ENV = "NODE9_API_HOST_ALLOW";
4710
+ }
4711
+ });
4712
+
4663
4713
  // src/config/index.ts
4664
4714
  import fs6 from "fs";
4665
4715
  import path7 from "path";
@@ -4678,12 +4728,26 @@ function sanitizeSsrfAllow(entries, source) {
4678
4728
  }
4679
4729
  return kept;
4680
4730
  }
4731
+ function noteRejectedApiUrl(raw) {
4732
+ const key = String(raw).slice(0, 200);
4733
+ if (rejectedApiUrlsSeen.has(key)) return;
4734
+ rejectedApiUrlsSeen.add(key);
4735
+ try {
4736
+ fs6.appendFileSync(
4737
+ path7.join(os7.homedir(), ".node9", "hook-debug.log"),
4738
+ `[${(/* @__PURE__ */ new Date()).toISOString()}] REFUSED apiUrl, using the default instead: ${String(raw).slice(0, 200).replace(/[\r\n]+/g, " ")}
4739
+ `
4740
+ );
4741
+ } catch {
4742
+ }
4743
+ }
4681
4744
  function getCredentials() {
4682
- const DEFAULT_API_URL = "https://api.node9.ai/api/v1/intercept";
4683
4745
  if (process.env.NODE9_API_KEY) {
4684
4746
  return {
4685
4747
  apiKey: process.env.NODE9_API_KEY,
4686
- apiUrl: process.env.NODE9_API_URL || DEFAULT_API_URL
4748
+ // NODE9_API_URL is env, and a hook inherits the agent's env, so it is
4749
+ // no more trusted than the file below.
4750
+ apiUrl: safeApiUrl(process.env.NODE9_API_URL || DEFAULT_API_URL, noteRejectedApiUrl)
4687
4751
  };
4688
4752
  }
4689
4753
  try {
@@ -4695,14 +4759,14 @@ function getCredentials() {
4695
4759
  if (profile?.apiKey) {
4696
4760
  return {
4697
4761
  apiKey: profile.apiKey,
4698
- apiUrl: profile.apiUrl || DEFAULT_API_URL,
4762
+ apiUrl: safeApiUrl(profile.apiUrl || DEFAULT_API_URL, noteRejectedApiUrl),
4699
4763
  localOnly: profile.localOnly === true || profileName !== "default"
4700
4764
  };
4701
4765
  }
4702
4766
  if (creds.apiKey) {
4703
4767
  return {
4704
4768
  apiKey: creds.apiKey,
4705
- apiUrl: creds.apiUrl || DEFAULT_API_URL,
4769
+ apiUrl: safeApiUrl(creds.apiUrl || DEFAULT_API_URL, noteRejectedApiUrl),
4706
4770
  localOnly: creds.localOnly === true
4707
4771
  };
4708
4772
  }
@@ -5332,7 +5396,7 @@ ${error.replace("Invalid config:\n", "")}
5332
5396
  }
5333
5397
  return sanitized;
5334
5398
  }
5335
- var DANGEROUS_WORDS, DEFAULT_CONFIG, RM_SAFE_PATH_PATTERN, VERDICT_ORDER, ADVISORY_SMART_RULES, cachedConfig, lastParsedRulesCache, CACHE_LOG_REARM_MS, cacheReadLastLoggedAt;
5399
+ var DANGEROUS_WORDS, DEFAULT_CONFIG, RM_SAFE_PATH_PATTERN, VERDICT_ORDER, ADVISORY_SMART_RULES, cachedConfig, rejectedApiUrlsSeen, lastParsedRulesCache, CACHE_LOG_REARM_MS, cacheReadLastLoggedAt;
5336
5400
  var init_config = __esm({
5337
5401
  "src/config/index.ts"() {
5338
5402
  "use strict";
@@ -5343,6 +5407,7 @@ var init_config = __esm({
5343
5407
  init_trusted_hosts();
5344
5408
  init_dist();
5345
5409
  init_dist();
5410
+ init_api_url();
5346
5411
  DANGEROUS_WORDS = [
5347
5412
  "mkfs",
5348
5413
  // formats/wipes a filesystem partition
@@ -5616,6 +5681,7 @@ var init_config = __esm({
5616
5681
  }
5617
5682
  ];
5618
5683
  cachedConfig = null;
5684
+ rejectedApiUrlsSeen = /* @__PURE__ */ new Set();
5619
5685
  lastParsedRulesCache = null;
5620
5686
  CACHE_LOG_REARM_MS = 5 * 60 * 1e3;
5621
5687
  cacheReadLastLoggedAt = 0;
@@ -6615,6 +6681,13 @@ var init_setup_pi_shim = __esm({
6615
6681
  }
6616
6682
  });
6617
6683
 
6684
+ // src/utils/atomic-write.ts
6685
+ var init_atomic_write = __esm({
6686
+ "src/utils/atomic-write.ts"() {
6687
+ "use strict";
6688
+ }
6689
+ });
6690
+
6618
6691
  // src/setup.ts
6619
6692
  import chalk3 from "chalk";
6620
6693
  import { confirm as rawConfirm } from "@inquirer/prompts";
@@ -6627,6 +6700,7 @@ var init_setup = __esm({
6627
6700
  init_hook_baseline();
6628
6701
  init_setup_opencode_shim();
6629
6702
  init_setup_pi_shim();
6703
+ init_atomic_write();
6630
6704
  }
6631
6705
  });
6632
6706
 
@@ -6651,6 +6725,7 @@ var init_scan_json = __esm({
6651
6725
  var init_scan_history = __esm({
6652
6726
  "src/cli/render/scan-history.ts"() {
6653
6727
  "use strict";
6728
+ init_atomic_write();
6654
6729
  }
6655
6730
  });
6656
6731