Skip to content

Commit fc137e3

Browse files
authored
1 parent 6aa7553 commit fc137e3

File tree

3 files changed

+14
-128
lines changed

3 files changed

+14
-128
lines changed

packages/@uppy/companion/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"express-session": "1.17.1",
4646
"grant": "4.7.0",
4747
"helmet": "^4.6.0",
48-
"ip-address": "6.2.0",
48+
"ipaddr.js": "^2.0.1",
4949
"isobject": "3.0.1",
5050
"jsonwebtoken": "8.5.1",
5151
"lodash.merge": "^4.6.2",

packages/@uppy/companion/src/server/helpers/request.js

Lines changed: 10 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,19 @@
1+
// eslint-disable-next-line max-classes-per-file
12
const http = require('http')
23
const https = require('https')
34
const { URL } = require('url')
45
const dns = require('dns')
5-
const ipAddress = require('ip-address')
66
const request = require('request')
7+
const ipaddr = require('ipaddr.js')
8+
79
const logger = require('../logger')
810

911
const FORBIDDEN_IP_ADDRESS = 'Forbidden IP address'
1012

11-
function isIPAddress (address) {
12-
const addressAsV6 = new ipAddress.Address6(address)
13-
const addressAsV4 = new ipAddress.Address4(address)
14-
return addressAsV6.isValid() || addressAsV4.isValid()
15-
}
16-
17-
/* eslint-disable max-len */
18-
/**
19-
* Determine if a IP address provided is a private one.
20-
* Return TRUE if it's the case, FALSE otherwise.
21-
* Excerpt from:
22-
* https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html#case-2---application-can-send-requests-to-any-external-ip-address-or-domain-name
23-
*
24-
* @param {string} ipAddress the ip address to validate
25-
* @returns {boolean}
26-
*/
27-
/* eslint-enable max-len */
28-
function isPrivateIP (ipAddress) {
29-
let isPrivate = false
30-
// Build the list of IP prefix for V4 and V6 addresses
31-
const ipPrefix = []
32-
// Add prefix for loopback addresses
33-
ipPrefix.push('127.')
34-
ipPrefix.push('0.')
35-
// Add IP V4 prefix for private addresses
36-
// See https://en.wikipedia.org/wiki/Private_network
37-
ipPrefix.push('10.')
38-
ipPrefix.push('172.16.')
39-
ipPrefix.push('172.17.')
40-
ipPrefix.push('172.18.')
41-
ipPrefix.push('172.19.')
42-
ipPrefix.push('172.20.')
43-
ipPrefix.push('172.21.')
44-
ipPrefix.push('172.22.')
45-
ipPrefix.push('172.23.')
46-
ipPrefix.push('172.24.')
47-
ipPrefix.push('172.25.')
48-
ipPrefix.push('172.26.')
49-
ipPrefix.push('172.27.')
50-
ipPrefix.push('172.28.')
51-
ipPrefix.push('172.29.')
52-
ipPrefix.push('172.30.')
53-
ipPrefix.push('172.31.')
54-
ipPrefix.push('192.168.')
55-
ipPrefix.push('169.254.')
56-
// Add IP V6 prefix for private addresses
57-
// See https://en.wikipedia.org/wiki/Unique_local_address
58-
// See https://en.wikipedia.org/wiki/Private_network
59-
// See https://simpledns.com/private-ipv6
60-
ipPrefix.push('fc')
61-
ipPrefix.push('fd')
62-
ipPrefix.push('fe')
63-
ipPrefix.push('ff')
64-
ipPrefix.push('::1')
65-
// Verify the provided IP address
66-
// Remove whitespace characters from the beginning/end of the string
67-
// and convert it to lower case
68-
// Lower case is for preventing any IPV6 case bypass using mixed case
69-
// depending on the source used to get the IP address
70-
const ipToVerify = ipAddress.trim().toLowerCase()
71-
// Perform the check against the list of prefix
72-
for (const prefix of ipPrefix) {
73-
if (ipToVerify.startsWith(prefix)) {
74-
isPrivate = true
75-
break
76-
}
77-
}
78-
79-
return isPrivate
80-
}
13+
// Example scary IPs that should return false (ipv6-to-ipv4 mapped):
14+
// ::FFFF:127.0.0.1
15+
// ::ffff:7f00:1
16+
const isDisallowedIP = (ipAddress) => ipaddr.parse(ipAddress).range() !== 'unicast'
8117

8218
module.exports.FORBIDDEN_IP_ADDRESS = FORBIDDEN_IP_ADDRESS
8319

@@ -115,7 +51,7 @@ function dnsLookup (hostname, options, callback) {
11551

11652
const toValidate = Array.isArray(addresses) ? addresses : [{ address: addresses }]
11753
for (const record of toValidate) {
118-
if (isPrivateIP(record.address)) {
54+
if (isDisallowedIP(record.address)) {
11955
callback(new Error(FORBIDDEN_IP_ADDRESS), addresses, maybeFamily)
12056
return
12157
}
@@ -127,7 +63,7 @@ function dnsLookup (hostname, options, callback) {
12763

12864
class HttpAgent extends http.Agent {
12965
createConnection (options, callback) {
130-
if (isIPAddress(options.host) && isPrivateIP(options.host)) {
66+
if (ipaddr.isValid(options.host) && isDisallowedIP(options.host)) {
13167
callback(new Error(FORBIDDEN_IP_ADDRESS))
13268
return undefined
13369
}
@@ -138,7 +74,7 @@ class HttpAgent extends http.Agent {
13874

13975
class HttpsAgent extends https.Agent {
14076
createConnection (options, callback) {
141-
if (isIPAddress(options.host) && isPrivateIP(options.host)) {
77+
if (ipaddr.isValid(options.host) && isDisallowedIP(options.host)) {
14278
callback(new Error(FORBIDDEN_IP_ADDRESS))
14379
return undefined
14480
}

yarn.lock

Lines changed: 3 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -8100,7 +8100,7 @@ __metadata:
81008100
grant: 4.7.0
81018101
helmet: ^4.6.0
81028102
into-stream: ^6.0.0
8103-
ip-address: 6.2.0
8103+
ipaddr.js: ^2.0.1
81048104
isobject: 3.0.1
81058105
jsonwebtoken: 8.5.1
81068106
lodash.merge: ^4.6.2
@@ -23125,21 +23125,6 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
2312523125
languageName: node
2312623126
linkType: hard
2312723127

23128-
"ip-address@npm:6.2.0":
23129-
version: 6.2.0
23130-
resolution: "ip-address@npm:6.2.0"
23131-
dependencies:
23132-
jsbn: 1.1.0
23133-
lodash.find: 4.6.0
23134-
lodash.max: 4.0.1
23135-
lodash.merge: 4.6.2
23136-
lodash.padstart: 4.6.1
23137-
lodash.repeat: 4.1.0
23138-
sprintf-js: 1.1.2
23139-
checksum: bcb93b4b13b3bf17d033fafce45850bf14c56366659ab627d3adbcd7a87ec64e219e7c6dc5cf990dddff5ac59db76520f2b1c7b5b05ea8d069162ca8a5112e44
23140-
languageName: node
23141-
linkType: hard
23142-
2314323128
"ip-regex@npm:^2.1.0":
2314423129
version: 2.1.0
2314523130
resolution: "ip-regex@npm:2.1.0"
@@ -25047,13 +25032,6 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
2504725032
languageName: node
2504825033
linkType: hard
2504925034

25050-
"jsbn@npm:1.1.0":
25051-
version: 1.1.0
25052-
resolution: "jsbn@npm:1.1.0"
25053-
checksum: 944f924f2bd67ad533b3850eee47603eed0f6ae425fd1ee8c760f477e8c34a05f144c1bd4f5a5dd1963141dc79a2c55f89ccc5ab77d039e7077f3ad196b64965
25054-
languageName: node
25055-
linkType: hard
25056-
2505725035
"jsbn@npm:~0.1.0":
2505825036
version: 0.1.1
2505925037
resolution: "jsbn@npm:0.1.1"
@@ -26431,13 +26409,6 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
2643126409
languageName: node
2643226410
linkType: hard
2643326411

26434-
"lodash.find@npm:4.6.0":
26435-
version: 4.6.0
26436-
resolution: "lodash.find@npm:4.6.0"
26437-
checksum: b737f849a4fe36f5c3664ea636780dda2fde18335021faf80cdfdcb300ed75441da6f55cfd6de119092d8bb2ddbc4433f4a8de4b99c0b9c8640465b0901c717c
26438-
languageName: node
26439-
linkType: hard
26440-
2644126412
"lodash.flatten@npm:^4.4.0":
2644226413
version: 4.4.0
2644326414
resolution: "lodash.flatten@npm:4.4.0"
@@ -26543,13 +26514,6 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
2654326514
languageName: node
2654426515
linkType: hard
2654526516

26546-
"lodash.max@npm:4.0.1":
26547-
version: 4.0.1
26548-
resolution: "lodash.max@npm:4.0.1"
26549-
checksum: f887b68db054edabe3a4f4877a7b7d0bef6e4a29e9371ea4d711a6ed0ca2393659a879158c609649aabd0337528ec58ed5b1e9581fed536ec0b8ae45a6e5f278
26550-
languageName: node
26551-
linkType: hard
26552-
2655326517
"lodash.memoize@npm:4.1.2, lodash.memoize@npm:^4.1.2":
2655426518
version: 4.1.2
2655526519
resolution: "lodash.memoize@npm:4.1.2"
@@ -26564,7 +26528,7 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
2656426528
languageName: node
2656526529
linkType: hard
2656626530

26567-
"lodash.merge@npm:4.6.2, lodash.merge@npm:^4.6.1, lodash.merge@npm:^4.6.2":
26531+
"lodash.merge@npm:^4.6.1, lodash.merge@npm:^4.6.2":
2656826532
version: 4.6.2
2656926533
resolution: "lodash.merge@npm:4.6.2"
2657026534
checksum: ad580b4bdbb7ca1f7abf7e1bce63a9a0b98e370cf40194b03380a46b4ed799c9573029599caebc1b14e3f24b111aef72b96674a56cfa105e0f5ac70546cdc005
@@ -26585,13 +26549,6 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
2658526549
languageName: node
2658626550
linkType: hard
2658726551

26588-
"lodash.padstart@npm:4.6.1":
26589-
version: 4.6.1
26590-
resolution: "lodash.padstart@npm:4.6.1"
26591-
checksum: 0d6ad92c626d351db85de539e41df3238d7d36c5fbfc5f57c4f060c90c73ad9f1db566463487795fdf0bf290a8f133189a0bd91d051032f6eb2d15b7e1863b5e
26592-
languageName: node
26593-
linkType: hard
26594-
2659526552
"lodash.pick@npm:^4.4.0":
2659626553
version: 4.4.0
2659726554
resolution: "lodash.pick@npm:4.4.0"
@@ -26606,13 +26563,6 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
2660626563
languageName: node
2660726564
linkType: hard
2660826565

26609-
"lodash.repeat@npm:4.1.0":
26610-
version: 4.1.0
26611-
resolution: "lodash.repeat@npm:4.1.0"
26612-
checksum: dac15fc59ed783678e1a9f986fefa180bfdbf95280852165965ecc8e15b871c6f0eaf7b325768a176014594d5186f1d6558fb72a18527bddd82539fb3ef8a4d3
26613-
languageName: node
26614-
linkType: hard
26615-
2661626566
"lodash.set@npm:^4.3.2":
2661726567
version: 4.3.2
2661826568
resolution: "lodash.set@npm:4.3.2"
@@ -37701,7 +37651,7 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
3770137651
languageName: node
3770237652
linkType: hard
3770337653

37704-
"sprintf-js@npm:1.1.2, sprintf-js@npm:^1.0.3, sprintf-js@npm:^1.1.2":
37654+
"sprintf-js@npm:^1.0.3, sprintf-js@npm:^1.1.2":
3770537655
version: 1.1.2
3770637656
resolution: "sprintf-js@npm:1.1.2"
3770737657
checksum: d4bb46464632b335e5faed381bd331157e0af64915a98ede833452663bc672823db49d7531c32d58798e85236581fb7342fd0270531ffc8f914e186187bf1c90

0 commit comments

Comments
 (0)