arn-browser 0.1.27 → 0.1.29

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.27",
3
+ "version": "0.1.29",
4
4
  "description": "A lightweight, browser autmation helper.",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
@@ -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
 
@@ -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