urllib 2.43.0 → 2.44.1
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/lib/index.d.ts +2 -2
- package/lib/urllib.js +85 -2
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ export interface RequestOptions {
|
|
|
32
32
|
writeStream?: Writable;
|
|
33
33
|
/** consume the writeStream, invoke the callback after writeStream close. */
|
|
34
34
|
consumeWriteStream?: boolean;
|
|
35
|
-
/**
|
|
35
|
+
/**
|
|
36
36
|
* The files will send with multipart/form-data format, base on formstream.
|
|
37
37
|
* If method not set, will use POST method by default.
|
|
38
38
|
*/
|
|
@@ -130,7 +130,7 @@ export interface RequestOptions {
|
|
|
130
130
|
* It receive two arguments(ip and family) and should return true or false to identified the address is legal or not.
|
|
131
131
|
* It rely on lookup and have the same version requirement.
|
|
132
132
|
*/
|
|
133
|
-
checkAddress?: (ip: string, family: number | string) => boolean;
|
|
133
|
+
checkAddress?: (ip: string, family: number | string, hostname: string) => boolean;
|
|
134
134
|
/**
|
|
135
135
|
* UNIX domain socket path. (Windows is not supported)
|
|
136
136
|
*/
|
package/lib/urllib.js
CHANGED
|
@@ -66,6 +66,71 @@ var TEXT_DATA_TYPES = [
|
|
|
66
66
|
|
|
67
67
|
var PROTO_RE = /^https?:\/\//i;
|
|
68
68
|
|
|
69
|
+
// Credential-bearing headers that must not be forwarded across an origin
|
|
70
|
+
// boundary when following a redirect, to avoid leaking them to a third party.
|
|
71
|
+
var CROSS_ORIGIN_SENSITIVE_HEADERS = [ 'authorization', 'cookie', 'proxy-authorization' ];
|
|
72
|
+
|
|
73
|
+
// Build an absolute href good enough to compute the origin. `currentUrl` may be
|
|
74
|
+
// a parsed URL object (with href) or an http options-style object built from
|
|
75
|
+
// { host/hostname, port, path }, which has no href.
|
|
76
|
+
function resolveOriginHref(currentUrl) {
|
|
77
|
+
if (currentUrl.href) {
|
|
78
|
+
return currentUrl.href;
|
|
79
|
+
}
|
|
80
|
+
var host = currentUrl.host || currentUrl.hostname;
|
|
81
|
+
if (!host) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
var protocol = currentUrl.protocol || 'http:';
|
|
85
|
+
if (protocol.charAt(protocol.length - 1) !== ':') {
|
|
86
|
+
protocol += ':';
|
|
87
|
+
}
|
|
88
|
+
if (currentUrl.port && String(host).indexOf(':') === -1) {
|
|
89
|
+
host += ':' + currentUrl.port;
|
|
90
|
+
}
|
|
91
|
+
return protocol + '//' + host + (currentUrl.path || currentUrl.pathname || '/');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function isCrossOriginRedirect(currentUrl, toUrl) {
|
|
95
|
+
try {
|
|
96
|
+
var fromHref = resolveOriginHref(currentUrl);
|
|
97
|
+
if (!fromHref) {
|
|
98
|
+
// origin cannot be determined: fail closed
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
if (URL) {
|
|
102
|
+
return new URL(fromHref).origin !== new URL(toUrl, fromHref).origin;
|
|
103
|
+
}
|
|
104
|
+
// Fallback for runtimes without the WHATWG URL global.
|
|
105
|
+
// urlutil.parse does not normalize default ports, so compare protocol +
|
|
106
|
+
// hostname + normalized port instead of the raw `host`.
|
|
107
|
+
var from = urlutil.parse(fromHref);
|
|
108
|
+
var to = urlutil.parse(urlutil.resolve(fromHref, toUrl));
|
|
109
|
+
var fromPort = from.port || (from.protocol === 'https:' ? '443' : '80');
|
|
110
|
+
var toPort = to.port || (to.protocol === 'https:' ? '443' : '80');
|
|
111
|
+
return from.protocol !== to.protocol || from.hostname !== to.hostname || fromPort !== toPort;
|
|
112
|
+
} catch (err) {
|
|
113
|
+
// Fail closed: if the origin cannot be determined, treat it as cross-origin
|
|
114
|
+
// so credentials are stripped rather than leaked.
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function cleanCrossOriginHeaders(headers, sensitive) {
|
|
120
|
+
var list = sensitive || CROSS_ORIGIN_SENSITIVE_HEADERS;
|
|
121
|
+
var cleaned = {};
|
|
122
|
+
if (headers) {
|
|
123
|
+
var names = utility.getOwnEnumerables(headers, true);
|
|
124
|
+
for (var i = 0; i < names.length; i++) {
|
|
125
|
+
var name = names[i];
|
|
126
|
+
if (list.indexOf(name.toLowerCase()) === -1) {
|
|
127
|
+
cleaned[name] = headers[name];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return cleaned;
|
|
132
|
+
}
|
|
133
|
+
|
|
69
134
|
// Keep-Alive: timeout=5, max=100
|
|
70
135
|
var KEEP_ALIVE_RE = /^timeout=(\d+)/i;
|
|
71
136
|
|
|
@@ -276,7 +341,7 @@ function requestWithCallback(url, args, callback) {
|
|
|
276
341
|
lookup = function(host, dnsopts, callback) {
|
|
277
342
|
_lookup(host, dnsopts, function emitLookup(err, ip, family) {
|
|
278
343
|
// add check address logic in custom dns lookup
|
|
279
|
-
if (!err && !args.checkAddress(ip, family)) {
|
|
344
|
+
if (!err && !args.checkAddress(ip, family, host)) {
|
|
280
345
|
err = new Error('illegal address');
|
|
281
346
|
err.name = 'IllegalAddressError';
|
|
282
347
|
err.hostname = host;
|
|
@@ -688,6 +753,24 @@ function requestWithCallback(url, args, callback) {
|
|
|
688
753
|
options.headers.host = null;
|
|
689
754
|
args.headers = options.headers;
|
|
690
755
|
}
|
|
756
|
+
// do not forward credential-bearing headers / auth to a different origin
|
|
757
|
+
if (isCrossOriginRedirect(parsedUrl, newUrl)) {
|
|
758
|
+
// Clone so this redirect-specific sanitization never corrupts the
|
|
759
|
+
// caller's reusable options object.
|
|
760
|
+
var redirectArgs = Object.assign({}, args);
|
|
761
|
+
var sensitiveHeaders = CROSS_ORIGIN_SENSITIVE_HEADERS;
|
|
762
|
+
if (proxyTunnelAgent) {
|
|
763
|
+
// Proxy-Authorization authenticates the (unchanged) proxy hop, not
|
|
764
|
+
// the redirected origin, so keep it when the request is proxied.
|
|
765
|
+
sensitiveHeaders = sensitiveHeaders.filter(function (name) {
|
|
766
|
+
return name !== 'proxy-authorization';
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
redirectArgs.headers = cleanCrossOriginHeaders(args.headers || options.headers, sensitiveHeaders);
|
|
770
|
+
redirectArgs.auth = null;
|
|
771
|
+
redirectArgs.digestAuth = null;
|
|
772
|
+
args = redirectArgs;
|
|
773
|
+
}
|
|
691
774
|
// avoid done will be execute in the future change.
|
|
692
775
|
var cb = callback;
|
|
693
776
|
callback = null;
|
|
@@ -1017,7 +1100,7 @@ function requestWithCallback(url, args, callback) {
|
|
|
1017
1100
|
family = 6;
|
|
1018
1101
|
}
|
|
1019
1102
|
if (family) {
|
|
1020
|
-
if (!args.checkAddress(hostname, family)) {
|
|
1103
|
+
if (!args.checkAddress(hostname, family, hostname)) {
|
|
1021
1104
|
var err = new Error('illegal address');
|
|
1022
1105
|
err.name = 'IllegalAddressError';
|
|
1023
1106
|
err.hostname = hostname;
|