|
| 1 | +From 32f468f1245574785ec080705737a579be1223aa Mon Sep 17 00:00:00 2001 |
| 2 | +From: Luke McFarlane <luke@innoware.com.au> |
| 3 | +Date: Mon, 12 Feb 2024 13:22:18 +1100 |
| 4 | +Subject: [PATCH] lib: fixed CVE-2023-42282 and added unit test |
| 5 | + |
| 6 | +Unit test code is not applicable for NodeJS sources hence not included. |
| 7 | + |
| 8 | +diff --git a/deps/npm/node_modules/ip/lib/ip.js b/deps/npm/node_modules/ip/lib/ip.js |
| 9 | +index 4b2adb5add..9022443ae5 100644 |
| 10 | +--- a/deps/npm/node_modules/ip/lib/ip.js |
| 11 | ++++ b/deps/npm/node_modules/ip/lib/ip.js |
| 12 | +@@ -306,12 +306,26 @@ ip.isEqual = function (a, b) { |
| 13 | + }; |
| 14 | + |
| 15 | + ip.isPrivate = function (addr) { |
| 16 | +- return /^(::f{4}:)?10\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i |
| 17 | +- .test(addr) |
| 18 | ++ // check loopback addresses first |
| 19 | ++ if (ip.isLoopback(addr)) { |
| 20 | ++ return true; |
| 21 | ++ } |
| 22 | ++ |
| 23 | ++ // ensure the ipv4 address is valid |
| 24 | ++ if (!ip.isV6Format(addr)) { |
| 25 | ++ const ipl = ip.normalizeToLong(addr); |
| 26 | ++ if (ipl < 0) { |
| 27 | ++ throw new Error('invalid ipv4 address'); |
| 28 | ++ } |
| 29 | ++ // normalize the address for the private range checks that follow |
| 30 | ++ addr = ip.fromLong(ipl); |
| 31 | ++ } |
| 32 | ++ |
| 33 | ++ // check private ranges |
| 34 | ++ return /^(::f{4}:)?10\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) |
| 35 | + || /^(::f{4}:)?192\.168\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) |
| 36 | + || /^(::f{4}:)?172\.(1[6-9]|2\d|30|31)\.([0-9]{1,3})\.([0-9]{1,3})$/i |
| 37 | + .test(addr) |
| 38 | +- || /^(::f{4}:)?127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) |
| 39 | + || /^(::f{4}:)?169\.254\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) |
| 40 | + || /^f[cd][0-9a-f]{2}:/i.test(addr) |
| 41 | + || /^fe80:/i.test(addr) |
| 42 | +@@ -324,9 +338,16 @@ ip.isPublic = function (addr) { |
| 43 | + }; |
| 44 | + |
| 45 | + ip.isLoopback = function (addr) { |
| 46 | ++ // If addr is an IPv4 address in long integer form (no dots and no colons), convert it |
| 47 | ++ if (!/\./.test(addr) && !/:/.test(addr)) { |
| 48 | ++ addr = ip.fromLong(Number(addr)); |
| 49 | ++ } |
| 50 | ++ |
| 51 | + return /^(::f{4}:)?127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/ |
| 52 | + .test(addr) |
| 53 | +- || /^fe80::1$/.test(addr) |
| 54 | ++ || /^0177\./.test(addr) |
| 55 | ++ || /^0x7f\./i.test(addr) |
| 56 | ++ || /^fe80::1$/i.test(addr) |
| 57 | + || /^::1$/.test(addr) |
| 58 | + || /^::$/.test(addr); |
| 59 | + }; |
| 60 | +@@ -420,3 +441,51 @@ ip.fromLong = function (ipl) { |
| 61 | + ipl >> 8 & 255}.${ |
| 62 | + ipl & 255}`); |
| 63 | + }; |
| 64 | ++ |
| 65 | ++ip.normalizeToLong = function (addr) { |
| 66 | ++ const parts = addr.split('.').map(part => { |
| 67 | ++ // Handle hexadecimal format |
| 68 | ++ if (part.startsWith('0x') || part.startsWith('0X')) { |
| 69 | ++ return parseInt(part, 16); |
| 70 | ++ } |
| 71 | ++ // Handle octal format (strictly digits 0-7 after a leading zero) |
| 72 | ++ else if (part.startsWith('0') && part !== '0' && /^[0-7]+$/.test(part)) { |
| 73 | ++ return parseInt(part, 8); |
| 74 | ++ } |
| 75 | ++ // Handle decimal format, reject invalid leading zeros |
| 76 | ++ else if (/^[1-9]\d*$/.test(part) || part === '0') { |
| 77 | ++ return parseInt(part, 10); |
| 78 | ++ } |
| 79 | ++ // Return NaN for invalid formats to indicate parsing failure |
| 80 | ++ else { |
| 81 | ++ return NaN; |
| 82 | ++ } |
| 83 | ++ }); |
| 84 | ++ |
| 85 | ++ if (parts.some(isNaN)) return -1; // Indicate error with -1 |
| 86 | ++ |
| 87 | ++ let val = 0; |
| 88 | ++ const n = parts.length; |
| 89 | ++ |
| 90 | ++ switch (n) { |
| 91 | ++ case 1: |
| 92 | ++ val = parts[0]; |
| 93 | ++ break; |
| 94 | ++ case 2: |
| 95 | ++ if (parts[0] > 0xff || parts[1] > 0xffffff) return -1; |
| 96 | ++ val = (parts[0] << 24) | (parts[1] & 0xffffff); |
| 97 | ++ break; |
| 98 | ++ case 3: |
| 99 | ++ if (parts[0] > 0xff || parts[1] > 0xff || parts[2] > 0xffff) return -1; |
| 100 | ++ val = (parts[0] << 24) | (parts[1] << 16) | (parts[2] & 0xffff); |
| 101 | ++ break; |
| 102 | ++ case 4: |
| 103 | ++ if (parts.some(part => part > 0xff)) return -1; |
| 104 | ++ val = (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8) | parts[3]; |
| 105 | ++ break; |
| 106 | ++ default: |
| 107 | ++ return -1; // Error case |
| 108 | ++ } |
| 109 | ++ |
| 110 | ++ return val >>> 0; |
| 111 | ++}; |
0 commit comments