arn-browser 0.1.26 → 0.1.28

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arn-browser",
3
- "version": "0.1.26",
3
+ "version": "0.1.28",
4
4
  "description": "A lightweight, browser autmation helper.",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
@@ -124,6 +124,17 @@ export interface ProxyServerController {
124
124
 
125
125
  /** Returns formatted statistics for hostnames per proxy channel */
126
126
  getHostStats: () => Record<string, Record<string, TrafficStats>>;
127
+
128
+ /**
129
+ * Dynamically update host routing at runtime.
130
+ * Only provided arrays are rebuilt — omitted ones stay unchanged.
131
+ * Affects all NEW connections; existing connections are untouched.
132
+ */
133
+ updateHosts: (options?: {
134
+ PROXY_1_HOSTS?: string[];
135
+ PROXY_2_HOSTS?: string[];
136
+ NO_PROXY_HOSTS?: string[];
137
+ }) => void;
127
138
  }
128
139
 
129
140
  /**
@@ -464,5 +464,16 @@ export async function startProxyServer({
464
464
 
465
465
  getProxyStats: getProxyStatsFormatted,
466
466
  getHostStats: getHostStatsFormatted,
467
+
468
+ /**
469
+ * Dynamically update host routing at runtime.
470
+ * Only provided arrays are rebuilt — omitted ones stay unchanged.
471
+ * Affects all NEW connections; existing connections are untouched.
472
+ */
473
+ updateHosts: ({ PROXY_1_HOSTS, PROXY_2_HOSTS, NO_PROXY_HOSTS } = {}) => {
474
+ if (PROXY_1_HOSTS) matchers.proxy1 = createHostMatcher([...PROXY_1_HOSTS, "proxy.multilogin.com", "multilogin.com"]);
475
+ if (PROXY_2_HOSTS) matchers.proxy2 = createHostMatcher([...PROXY_2_HOSTS, "proxy.multilogin.com", "multilogin.com"]);
476
+ if (NO_PROXY_HOSTS) matchers.noProxy = createHostMatcher([...NO_PROXY_HOSTS, "%brave.com%", "%gvt1.com%"]);
477
+ },
467
478
  };
468
479
  }
@@ -72,44 +72,77 @@ function createProxyAgent(proxyUrl) {
72
72
  }
73
73
 
74
74
  /**
75
- * Strips sensitive headers from outgoing request headers.
76
- * Removes cookie and authorization to prevent session/IP correlation.
75
+ * Sanitizes outgoing request headers using an allowlist approach.
76
+ * Only keeps essential headers needed for the server to respond correctly.
77
+ * Everything else (cookies, auth, fingerprint hints, HTTP/2 pseudo-headers, etc.) is stripped.
77
78
  */
78
79
  function sanitizeRequestHeaders(headers, logger, url) {
79
- const cleaned = { ...headers };
80
+ // Allowlist of essential request headers to keep
81
+ const allowedHeaders = new Set([
82
+ "accept",
83
+ "accept-encoding",
84
+ "accept-language",
85
+ "referer",
86
+ "user-agent",
87
+ "sec-ch-ua",
88
+ "sec-ch-ua-mobile",
89
+ "sec-ch-ua-platform",
90
+ "sec-ch-ua-platform-version",
91
+ "sec-fetch-dest",
92
+ "sec-fetch-mode",
93
+ "sec-fetch-site",
94
+ ]);
95
+
96
+ const cleaned = {};
80
97
  const stripped = [];
81
- // Remove known auth headers
82
- if (cleaned["cookie"]) { stripped.push("cookie"); delete cleaned["cookie"]; }
83
- if (cleaned["authorization"]) { stripped.push("authorization"); delete cleaned["authorization"]; }
84
- // Remove any header containing auth/token/csrf keywords
85
- for (const key of Object.keys(cleaned)) {
98
+
99
+ for (const [key, value] of Object.entries(headers)) {
86
100
  const lower = key.toLowerCase();
87
- if (lower.includes("token") || lower.includes("csrf") || lower.includes("auth")) {
101
+ if (allowedHeaders.has(lower)) {
102
+ cleaned[lower] = value;
103
+ } else {
88
104
  stripped.push(key);
89
- delete cleaned[key];
90
105
  }
91
106
  }
92
- if (logger && stripped.length) console.log(`[stripGot] Request stripped: [${stripped.join(", ")}] → ${url}`);
107
+
108
+ if (logger && stripped.length) console.log(`[stripGot] Request stripped ${stripped.length} headers: [${stripped.join(", ")}] → ${url}`);
93
109
  return cleaned;
94
110
  }
95
111
 
96
112
  /**
97
- * Sanitizes response headers for safe caching across origins.
98
- * - Replaces access-control-allow-origin with * (if present)
99
- * - Removes access-control-allow-credentials, set-cookie, CSP, HSTS
113
+ * Sanitizes response headers using an allowlist approach.
114
+ * Only keeps essential headers needed for correct content delivery.
115
+ * Everything else (tracking, fingerprint, security policy, cookies, etc.) is stripped.
100
116
  */
101
117
  function sanitizeResponseHeaders(headers, logger, url) {
102
- const cleaned = { ...headers };
103
- const changes = [];
104
- if (cleaned["access-control-allow-origin"]) {
105
- changes.push(`access-control-allow-origin: ${cleaned["access-control-allow-origin"]} → *`);
106
- cleaned["access-control-allow-origin"] = "*";
118
+ // Allowlist of essential response headers to keep
119
+ const allowedHeaders = new Set([
120
+ "content-type",
121
+ "content-length",
122
+ "content-encoding",
123
+ "cache-control",
124
+ "etag",
125
+ "last-modified",
126
+ "location",
127
+ "access-control-allow-origin",
128
+ "accept-ranges",
129
+ "vary",
130
+ ]);
131
+
132
+ const cleaned = {};
133
+ const stripped = [];
134
+
135
+ for (const [key, value] of Object.entries(headers)) {
136
+ const lower = key.toLowerCase();
137
+ if (allowedHeaders.has(lower)) {
138
+ // Force access-control-allow-origin to wildcard for cross-origin safety
139
+ cleaned[lower] = lower === "access-control-allow-origin" ? "*" : value;
140
+ } else {
141
+ stripped.push(key);
142
+ }
107
143
  }
108
- if (cleaned["access-control-allow-credentials"]) { changes.push("access-control-allow-credentials"); delete cleaned["access-control-allow-credentials"]; }
109
- if (cleaned["set-cookie"]) { changes.push("set-cookie"); delete cleaned["set-cookie"]; }
110
- if (cleaned["content-security-policy"]) { changes.push("content-security-policy"); delete cleaned["content-security-policy"]; }
111
- if (cleaned["strict-transport-security"]) { changes.push("strict-transport-security"); delete cleaned["strict-transport-security"]; }
112
- if (logger && changes.length) console.log(`[stripGot] Response stripped: [${changes.join(", ")}] → ${url}`);
144
+
145
+ if (logger && stripped.length) console.log(`[stripGot] Response stripped ${stripped.length} headers: [${stripped.join(", ")}] ${url}`);
113
146
  return cleaned;
114
147
  }
115
148