
node-ip का अनुरक्षित फोर्क जिसमें अनपैच्ड SSRF एडवाइज़री (CVE-2024-29415) को ठीक कर दिया गया है
ip का अनुरक्षित फोर्क — Node.js के लिए IP एड्रेस उपयोगिताएँ — जिसमें अनपैच्ड SSRF एडवाइज़री ठीक कर दी गई है।
मूल पैकेज की ~38M डाउनलोड/माह हैं, फरवरी 2024 से कोई रिलीज़ नहीं हुई है, और एक HIGH-गंभीरता वाली एडवाइज़री (CVE-2024-29415 / GHSA-2p57-rm9w-gvfp) है जो हर प्रकाशित संस्करण को प्रभावित करती है और हर इंस्टॉल पर npm audit को विफल कर देती है। यह फोर्क regexes को पैच करने के बजाय मूल कारण को ठीक करता है।
npm install @bybrave/ip2
// CommonJS — drop-in
const ip = require('@bybrave/ip2');
// ESM — named imports
import { isPrivate, isPublic, cidrSubnet } from '@bybrave/ip2';
// TypeScript types built in
मूल isPrivate() / isPublic() / isLoopback() कच्चे इनपुट स्ट्रिंग पर regexes चलाते थे। एड्रेस की कोई भी ऐसी वर्तनी जिसकी regexes ने कल्पना नहीं की थी — ऑक्टल या हेक्स ऑक्टेट्स, संक्षिप्त IPv4, असंपीड़ित IPv6 — चुपचाप public के रूप में वर्गीकृत हो जाती थी:
// original [email protected] — all of these are loopback/private, all reported PUBLIC:
ip.isPublic('127.1') // true 💥
ip.isPublic('012.1.2.3') // true 💥 (octal 10.1.2.3)
ip.isPublic('01200034567') // true 💥 (integer 10.0.14.119)
ip.isPublic('000:0:0000::01') // true 💥 (that's ::1)
यदि ये उत्तर बाहर जाने वाले अनुरोधों की रक्षा करते हैं, तो यह एक SSRF छेद है (CVE-2024-29415, CVE-2023-42282 का अधूरा सुधार)।
यह फोर्क:
net.isIP के समान व्याकरण, साथ ही IPv6 ज़ोन आईडी)। वर्गीकरण बाइट्स पर चलता है, स्ट्रिंग्स पर कभी नहीं।127.1, 0x7f.1, 0177.0.0.1, 2130706433) अनुमान लगाए जाने के बजाय throw करती हैं। Fail closed करें, open नहीं। यदि आपको विरासती संकेतन स्वीकार करने हैं, तो पहले स्पष्ट रूप से सामान्यीकृत करें: ip.fromLong(ip.normalizeToLong(addr))।isPrivate() का अब अर्थ है "वैश्विक रूप से पहुंच योग्य नहीं" — Python के ipaddress के समान परंपरा। यह CGNAT (100.64/10), TEST-NETs, बेंचमार्किंग, मल्टीकास्ट, आरक्षित, ULA, दस्तावेज़ीकरण रेंज और बहुत कुछ जोड़ता है — नीचे दी गई तालिका देखें।::ffff:a.b.c.d (v4-mapped), 64:ff9b::a.b.c.d (NAT64) और 2002:xxxx:xxxx:: (6to4) उनके अंदर मौजूद IPv4 एड्रेस के अनुसार private/public हैं।// @bybrave/ip2
ip.isPublic('127.1') // throws Error: Invalid ip address: 127.1
ip.isPrivate('000:0:0000::01') // true (parsed as ::1)
ip.isLoopback('::fFFf:127.0.0.1')// true
ip.isPublic('64:ff9b::8.8.8.8') // true (NAT64 of a public address)
ip.isPrivate('100.64.0.1') // true (CGNAT — original said public)
| सुधार | मूल समस्या |
|---|---|
| CVE-2024-29415 / GHSA-2p57-rm9w-gvfp — गैर-विहित एड्रेस के माध्यम से SSRF | #136, #150, #153, #158 |
isPrivate() CGNAT, TEST-NETs, बेंचमार्किंग, मल्टीकास्ट, आरक्षित, दस्तावेज़ीकरण रेंज को अनदेखा करता है | — |
cidrSubnet(...).contains() IPv4-mapped IPv6 एड्रेस के लिए false लौटाता है | #104 |
isV6Format() IPv4 एड्रेस के लिए true लौटाता है | #67 |
isV4Format() ≥ 256 मान वाले ऑक्टेट्स स्वीकार करता है | #105 |
address('public') private एड्रेस लौटाता था और इसका विपरीत भी (फ़िल्टर उलटा था) | — |
loopback('ipv6') fe80::1 लौटाता था, जो link-local है, loopback नहीं → अब ::1 | — |
cidr()/cidrSubnet() अमान्य प्रीफिक्स लंबाई (/33, /x) के लिए चुपचाप कचरा उत्पन्न करते थे → अब throw करते हैं | — |
address(name) अज्ञात इंटरफ़ेस नामों के लिए TypeError के साथ क्रैश होता था → अब undefined लौटाता है | — |
TypeScript प्रकार बिल्ट-इन हैं (@types/ip की आवश्यकता नहीं), ESM नामित निर्यात | — |
- const ip = require('ip');
+ const ip = require('@bybrave/ip2');
API सतह समान है; व्यवहारिक अंतर सुरक्षा और शुद्धता सुधार हैं — अपग्रेड करने से पहले नीचे दिए गए ब्रेकिंग बदलाव देखें।
संस्करण 3.0.0 इसलिए क्योंकि सख्ती ही सुधार है — यदि आप इस लाइब्रेरी को गैर-विहित स्ट्रिंग्स देते थे, तो v2 आपको संगत उत्तर नहीं, बल्कि गलत उत्तर दे रहा था:
isPrivate / isPublic / isLoopback / toBuffer / toLong विकृत या गैर-विहित इनपुट (ऑक्टल/हेक्स ऑक्टेट्स, 127.1, पूर्णांक स्ट्रिंग्स) पर throw करते हैं। यदि आपको विरासती संकेतन स्वीकार करने ही हैं तो पहले normalizeToLong() का उपयोग करें।isLoopback('fe80::1') अब false है (link-local ≠ loopback; फिर भी isPrivate)। isLoopback('::') अब false है (अनिर्दिष्ट ≠ loopback; फिर भी isPrivate)।loopback('ipv6') 'fe80::1' के बजाय '::1' लौटाता है।isPrivate() अधिक रेंजों के लिए true लौटाता है (CGNAT, TEST-NETs, मल्टीकास्ट, …) — इसका अब अर्थ है "वैश्विक रूप से पहुंच योग्य नहीं"।address('public') अब वास्तव में public एड्रेस लौटाता है। यदि आप LAN एड्रेस पाने के लिए उल्टे व्यवहार पर निर्भर थे, तो address('private') का उपयोग करें — वही यह आपको दे रहा था।मूल जो कुछ भी निर्यात करता है, सब कुछ, साथ ही isValid():
ip.address('public', 'ipv6') // address of a network interface
ip.isPrivate('10.0.0.1') // true — not globally reachable
ip.isPublic('8.8.8.8') // true
ip.isLoopback('127.8.8.8') // true
ip.isValid('300.1.2.3') // false (never throws)
ip.isV4Format('192.168.0.1') // true
ip.isV6Format('2001:db8::1') // true
ip.isEqual('::ffff:7f00:1', '127.0.0.1') // true
ip.toBuffer('127.0.0.1') // Buffer([127, 0, 0, 1])
ip.toString(buf, offset, length) // '127.0.0.1'
ip.toLong('127.0.0.1') // 2130706433
ip.fromLong(2130706433) // '127.0.0.1'
ip.normalizeToLong('127.1') // 2130706433 (lenient, -1 on error)
ip.fromPrefixLen(24) // '255.255.255.0'
ip.mask('192.168.1.134', '255.255.255.0') // '192.168.1.0'
ip.cidr('192.168.1.134/26') // '192.168.1.128'
ip.not('255.255.255.0') // '0.0.0.255'
ip.or('0.0.0.255', '192.168.1.10') // '192.168.1.255'
const s = ip.cidrSubnet('192.168.1.134/26')
s.networkAddress // '192.168.1.128'
s.firstAddress // '192.168.1.129'
s.lastAddress // '192.168.1.190'
s.broadcastAddress // '192.168.1.191'
s.subnetMaskLength // 26
s.numHosts // 62
s.contains('::ffff:192.168.1.180') // true (v4-mapped handled)
IPv4: 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10 (CGNAT), 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.88.99.0/24, 192.168.0.0/16, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/4, 240.0.0.0/4 (ब्रॉडकास्ट सहित)।
IPv6: ::/96 (अनिर्दिष्ट, loopback, v4-compatible), 64:ff9b:1::/48, 100::/64, 2001::/23, 2001:db8::/32, 3fff::/20, 5f00::/16, fc00::/7, fe80::/10, fec0::/10, ff00::/8। ट्रांज़िशन रेंज ::ffff:0:0/96, 64:ff9b::/96 और 2002::/16 अपने एम्बेडेड IPv4 एड्रेस का अनुसरण करते हैं।
यदि यह पैकेज आपका समय बचाता है, तो आप अनुरक्षण में सहयोग कर सकते हैं:
Bitcoin (BTC): bc1q37557q5jpeaxqydzwvf3jgj7zhnfpn2td3q40q
MIT। Fedor Indutny द्वारा node-ip पर आधारित।