@depup/node-fetch 3.3.2-depup.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.
@@ -0,0 +1,340 @@
1
+ import {isIP} from 'node:net';
2
+
3
+ /**
4
+ * @external URL
5
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/URL|URL}
6
+ */
7
+
8
+ /**
9
+ * @module utils/referrer
10
+ * @private
11
+ */
12
+
13
+ /**
14
+ * @see {@link https://w3c.github.io/webappsec-referrer-policy/#strip-url|Referrer Policy §8.4. Strip url for use as a referrer}
15
+ * @param {string} URL
16
+ * @param {boolean} [originOnly=false]
17
+ */
18
+ export function stripURLForUseAsAReferrer(url, originOnly = false) {
19
+ // 1. If url is null, return no referrer.
20
+ if (url == null) { // eslint-disable-line no-eq-null, eqeqeq
21
+ return 'no-referrer';
22
+ }
23
+
24
+ url = new URL(url);
25
+
26
+ // 2. If url's scheme is a local scheme, then return no referrer.
27
+ if (/^(about|blob|data):$/.test(url.protocol)) {
28
+ return 'no-referrer';
29
+ }
30
+
31
+ // 3. Set url's username to the empty string.
32
+ url.username = '';
33
+
34
+ // 4. Set url's password to null.
35
+ // Note: `null` appears to be a mistake as this actually results in the password being `"null"`.
36
+ url.password = '';
37
+
38
+ // 5. Set url's fragment to null.
39
+ // Note: `null` appears to be a mistake as this actually results in the fragment being `"#null"`.
40
+ url.hash = '';
41
+
42
+ // 6. If the origin-only flag is true, then:
43
+ if (originOnly) {
44
+ // 6.1. Set url's path to null.
45
+ // Note: `null` appears to be a mistake as this actually results in the path being `"/null"`.
46
+ url.pathname = '';
47
+
48
+ // 6.2. Set url's query to null.
49
+ // Note: `null` appears to be a mistake as this actually results in the query being `"?null"`.
50
+ url.search = '';
51
+ }
52
+
53
+ // 7. Return url.
54
+ return url;
55
+ }
56
+
57
+ /**
58
+ * @see {@link https://w3c.github.io/webappsec-referrer-policy/#enumdef-referrerpolicy|enum ReferrerPolicy}
59
+ */
60
+ export const ReferrerPolicy = new Set([
61
+ '',
62
+ 'no-referrer',
63
+ 'no-referrer-when-downgrade',
64
+ 'same-origin',
65
+ 'origin',
66
+ 'strict-origin',
67
+ 'origin-when-cross-origin',
68
+ 'strict-origin-when-cross-origin',
69
+ 'unsafe-url'
70
+ ]);
71
+
72
+ /**
73
+ * @see {@link https://w3c.github.io/webappsec-referrer-policy/#default-referrer-policy|default referrer policy}
74
+ */
75
+ export const DEFAULT_REFERRER_POLICY = 'strict-origin-when-cross-origin';
76
+
77
+ /**
78
+ * @see {@link https://w3c.github.io/webappsec-referrer-policy/#referrer-policies|Referrer Policy §3. Referrer Policies}
79
+ * @param {string} referrerPolicy
80
+ * @returns {string} referrerPolicy
81
+ */
82
+ export function validateReferrerPolicy(referrerPolicy) {
83
+ if (!ReferrerPolicy.has(referrerPolicy)) {
84
+ throw new TypeError(`Invalid referrerPolicy: ${referrerPolicy}`);
85
+ }
86
+
87
+ return referrerPolicy;
88
+ }
89
+
90
+ /**
91
+ * @see {@link https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy|Referrer Policy §3.2. Is origin potentially trustworthy?}
92
+ * @param {external:URL} url
93
+ * @returns `true`: "Potentially Trustworthy", `false`: "Not Trustworthy"
94
+ */
95
+ export function isOriginPotentiallyTrustworthy(url) {
96
+ // 1. If origin is an opaque origin, return "Not Trustworthy".
97
+ // Not applicable
98
+
99
+ // 2. Assert: origin is a tuple origin.
100
+ // Not for implementations
101
+
102
+ // 3. If origin's scheme is either "https" or "wss", return "Potentially Trustworthy".
103
+ if (/^(http|ws)s:$/.test(url.protocol)) {
104
+ return true;
105
+ }
106
+
107
+ // 4. If origin's host component matches one of the CIDR notations 127.0.0.0/8 or ::1/128 [RFC4632], return "Potentially Trustworthy".
108
+ const hostIp = url.host.replace(/(^\[)|(]$)/g, '');
109
+ const hostIPVersion = isIP(hostIp);
110
+
111
+ if (hostIPVersion === 4 && /^127\./.test(hostIp)) {
112
+ return true;
113
+ }
114
+
115
+ if (hostIPVersion === 6 && /^(((0+:){7})|(::(0+:){0,6}))0*1$/.test(hostIp)) {
116
+ return true;
117
+ }
118
+
119
+ // 5. If origin's host component is "localhost" or falls within ".localhost", and the user agent conforms to the name resolution rules in [let-localhost-be-localhost], return "Potentially Trustworthy".
120
+ // We are returning FALSE here because we cannot ensure conformance to
121
+ // let-localhost-be-loalhost (https://tools.ietf.org/html/draft-west-let-localhost-be-localhost)
122
+ if (url.host === 'localhost' || url.host.endsWith('.localhost')) {
123
+ return false;
124
+ }
125
+
126
+ // 6. If origin's scheme component is file, return "Potentially Trustworthy".
127
+ if (url.protocol === 'file:') {
128
+ return true;
129
+ }
130
+
131
+ // 7. If origin's scheme component is one which the user agent considers to be authenticated, return "Potentially Trustworthy".
132
+ // Not supported
133
+
134
+ // 8. If origin has been configured as a trustworthy origin, return "Potentially Trustworthy".
135
+ // Not supported
136
+
137
+ // 9. Return "Not Trustworthy".
138
+ return false;
139
+ }
140
+
141
+ /**
142
+ * @see {@link https://w3c.github.io/webappsec-secure-contexts/#is-url-trustworthy|Referrer Policy §3.3. Is url potentially trustworthy?}
143
+ * @param {external:URL} url
144
+ * @returns `true`: "Potentially Trustworthy", `false`: "Not Trustworthy"
145
+ */
146
+ export function isUrlPotentiallyTrustworthy(url) {
147
+ // 1. If url is "about:blank" or "about:srcdoc", return "Potentially Trustworthy".
148
+ if (/^about:(blank|srcdoc)$/.test(url)) {
149
+ return true;
150
+ }
151
+
152
+ // 2. If url's scheme is "data", return "Potentially Trustworthy".
153
+ if (url.protocol === 'data:') {
154
+ return true;
155
+ }
156
+
157
+ // Note: The origin of blob: and filesystem: URLs is the origin of the context in which they were
158
+ // created. Therefore, blobs created in a trustworthy origin will themselves be potentially
159
+ // trustworthy.
160
+ if (/^(blob|filesystem):$/.test(url.protocol)) {
161
+ return true;
162
+ }
163
+
164
+ // 3. Return the result of executing §3.2 Is origin potentially trustworthy? on url's origin.
165
+ return isOriginPotentiallyTrustworthy(url);
166
+ }
167
+
168
+ /**
169
+ * Modifies the referrerURL to enforce any extra security policy considerations.
170
+ * @see {@link https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer|Referrer Policy §8.3. Determine request's Referrer}, step 7
171
+ * @callback module:utils/referrer~referrerURLCallback
172
+ * @param {external:URL} referrerURL
173
+ * @returns {external:URL} modified referrerURL
174
+ */
175
+
176
+ /**
177
+ * Modifies the referrerOrigin to enforce any extra security policy considerations.
178
+ * @see {@link https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer|Referrer Policy §8.3. Determine request's Referrer}, step 7
179
+ * @callback module:utils/referrer~referrerOriginCallback
180
+ * @param {external:URL} referrerOrigin
181
+ * @returns {external:URL} modified referrerOrigin
182
+ */
183
+
184
+ /**
185
+ * @see {@link https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer|Referrer Policy §8.3. Determine request's Referrer}
186
+ * @param {Request} request
187
+ * @param {object} o
188
+ * @param {module:utils/referrer~referrerURLCallback} o.referrerURLCallback
189
+ * @param {module:utils/referrer~referrerOriginCallback} o.referrerOriginCallback
190
+ * @returns {external:URL} Request's referrer
191
+ */
192
+ export function determineRequestsReferrer(request, {referrerURLCallback, referrerOriginCallback} = {}) {
193
+ // There are 2 notes in the specification about invalid pre-conditions. We return null, here, for
194
+ // these cases:
195
+ // > Note: If request's referrer is "no-referrer", Fetch will not call into this algorithm.
196
+ // > Note: If request's referrer policy is the empty string, Fetch will not call into this
197
+ // > algorithm.
198
+ if (request.referrer === 'no-referrer' || request.referrerPolicy === '') {
199
+ return null;
200
+ }
201
+
202
+ // 1. Let policy be request's associated referrer policy.
203
+ const policy = request.referrerPolicy;
204
+
205
+ // 2. Let environment be request's client.
206
+ // not applicable to node.js
207
+
208
+ // 3. Switch on request's referrer:
209
+ if (request.referrer === 'about:client') {
210
+ return 'no-referrer';
211
+ }
212
+
213
+ // "a URL": Let referrerSource be request's referrer.
214
+ const referrerSource = request.referrer;
215
+
216
+ // 4. Let request's referrerURL be the result of stripping referrerSource for use as a referrer.
217
+ let referrerURL = stripURLForUseAsAReferrer(referrerSource);
218
+
219
+ // 5. Let referrerOrigin be the result of stripping referrerSource for use as a referrer, with the
220
+ // origin-only flag set to true.
221
+ let referrerOrigin = stripURLForUseAsAReferrer(referrerSource, true);
222
+
223
+ // 6. If the result of serializing referrerURL is a string whose length is greater than 4096, set
224
+ // referrerURL to referrerOrigin.
225
+ if (referrerURL.toString().length > 4096) {
226
+ referrerURL = referrerOrigin;
227
+ }
228
+
229
+ // 7. The user agent MAY alter referrerURL or referrerOrigin at this point to enforce arbitrary
230
+ // policy considerations in the interests of minimizing data leakage. For example, the user
231
+ // agent could strip the URL down to an origin, modify its host, replace it with an empty
232
+ // string, etc.
233
+ if (referrerURLCallback) {
234
+ referrerURL = referrerURLCallback(referrerURL);
235
+ }
236
+
237
+ if (referrerOriginCallback) {
238
+ referrerOrigin = referrerOriginCallback(referrerOrigin);
239
+ }
240
+
241
+ // 8.Execute the statements corresponding to the value of policy:
242
+ const currentURL = new URL(request.url);
243
+
244
+ switch (policy) {
245
+ case 'no-referrer':
246
+ return 'no-referrer';
247
+
248
+ case 'origin':
249
+ return referrerOrigin;
250
+
251
+ case 'unsafe-url':
252
+ return referrerURL;
253
+
254
+ case 'strict-origin':
255
+ // 1. If referrerURL is a potentially trustworthy URL and request's current URL is not a
256
+ // potentially trustworthy URL, then return no referrer.
257
+ if (isUrlPotentiallyTrustworthy(referrerURL) && !isUrlPotentiallyTrustworthy(currentURL)) {
258
+ return 'no-referrer';
259
+ }
260
+
261
+ // 2. Return referrerOrigin.
262
+ return referrerOrigin.toString();
263
+
264
+ case 'strict-origin-when-cross-origin':
265
+ // 1. If the origin of referrerURL and the origin of request's current URL are the same, then
266
+ // return referrerURL.
267
+ if (referrerURL.origin === currentURL.origin) {
268
+ return referrerURL;
269
+ }
270
+
271
+ // 2. If referrerURL is a potentially trustworthy URL and request's current URL is not a
272
+ // potentially trustworthy URL, then return no referrer.
273
+ if (isUrlPotentiallyTrustworthy(referrerURL) && !isUrlPotentiallyTrustworthy(currentURL)) {
274
+ return 'no-referrer';
275
+ }
276
+
277
+ // 3. Return referrerOrigin.
278
+ return referrerOrigin;
279
+
280
+ case 'same-origin':
281
+ // 1. If the origin of referrerURL and the origin of request's current URL are the same, then
282
+ // return referrerURL.
283
+ if (referrerURL.origin === currentURL.origin) {
284
+ return referrerURL;
285
+ }
286
+
287
+ // 2. Return no referrer.
288
+ return 'no-referrer';
289
+
290
+ case 'origin-when-cross-origin':
291
+ // 1. If the origin of referrerURL and the origin of request's current URL are the same, then
292
+ // return referrerURL.
293
+ if (referrerURL.origin === currentURL.origin) {
294
+ return referrerURL;
295
+ }
296
+
297
+ // Return referrerOrigin.
298
+ return referrerOrigin;
299
+
300
+ case 'no-referrer-when-downgrade':
301
+ // 1. If referrerURL is a potentially trustworthy URL and request's current URL is not a
302
+ // potentially trustworthy URL, then return no referrer.
303
+ if (isUrlPotentiallyTrustworthy(referrerURL) && !isUrlPotentiallyTrustworthy(currentURL)) {
304
+ return 'no-referrer';
305
+ }
306
+
307
+ // 2. Return referrerURL.
308
+ return referrerURL;
309
+
310
+ default:
311
+ throw new TypeError(`Invalid referrerPolicy: ${policy}`);
312
+ }
313
+ }
314
+
315
+ /**
316
+ * @see {@link https://w3c.github.io/webappsec-referrer-policy/#parse-referrer-policy-from-header|Referrer Policy §8.1. Parse a referrer policy from a Referrer-Policy header}
317
+ * @param {Headers} headers Response headers
318
+ * @returns {string} policy
319
+ */
320
+ export function parseReferrerPolicyFromHeader(headers) {
321
+ // 1. Let policy-tokens be the result of extracting header list values given `Referrer-Policy`
322
+ // and response’s header list.
323
+ const policyTokens = (headers.get('referrer-policy') || '').split(/[,\s]+/);
324
+
325
+ // 2. Let policy be the empty string.
326
+ let policy = '';
327
+
328
+ // 3. For each token in policy-tokens, if token is a referrer policy and token is not the empty
329
+ // string, then set policy to token.
330
+ // Note: This algorithm loops over multiple policy values to allow deployment of new policy
331
+ // values with fallbacks for older user agents, as described in § 11.1 Unknown Policy Values.
332
+ for (const token of policyTokens) {
333
+ if (token && ReferrerPolicy.has(token)) {
334
+ policy = token;
335
+ }
336
+ }
337
+
338
+ // 4. Return policy.
339
+ return policy;
340
+ }