@bybrave/ip2 (英语)
维护的叉 ip ——Node.js的IP地址公用设施——与 已固定无标SSRF咨询。 。 。 .
原版包有~38M下载量/月,自2024年2月起无发行量,并有高清的咨询(CVE-2024-29415 (中文(简体) ) 编号 : GHSA-2p57-rm9w-gvfp影响 每个已出版的版本 并创造 npm audit 每次安装失败 。 此分叉修正了根因,而不是补丁正格克塞.
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没有预料到的地址的任何拼写——八分音或六分音,缩写为IPv4,未压缩的IPv6——被默默地归类为: 公开数字 :
// 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)
如果这些解答 守卫发出的请求, 这是一个SSF孔(CVE-2024-29415), 不完整的修复 CVE-2023-42282.
这个叉子:
- 先分析,再分类第二. 每个分类函数将地址解为字节并带有严格的解析器(语法相同于
net.isIP,加上IPv6区ID. 分类运行在字节上,从未运行在字符串上. - 拒绝模糊的输入 . 非冠词拼写法(
127.1, (中文(简体) ),0x7f.1, (中文(简体) ),0177.0.0.1, (中文(简体) ),2130706433(中文(简体) ) 掷出 而不是被猜测。 失败关闭,没有打开。 如果你需要接受遗留的标记,首先明确正常化:ip.fromLong(ip.normalizeToLong(addr))。 。 。 . - 涵盖IANA全部特殊用途登记册 (单位:千美元)IPv4 请检查url=值 (帮助), (中文(简体) ), IPv6 请检查url=值 (帮助)),不是四个regex.
isPrivate()现在的意思是"无法在全球达到"——与Python的同一种公约ipaddress。增加了CGNAT(100.64/10,TEST-NET,基准,多播,保留,ULA,文件范围等——见下表. - 通过嵌入式IPv4对过渡地址进行分类.
::ffff:a.b.c.d(v4-被标记),64:ff9b::a.b.c.d(NAT64)和 (中文(简体) )2002:xxxx:xxxx::根据其中的IPv4地址,(6to4)是私有/公有的.
// @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)
全部修正完毕 [email protected]
| 固定 | 原刊 |
|---|---|
| CVE-2024-29415 / GHSA-2p57-rm9w-gvfp – SSRF通过非卡通地址 | 136号, (中文(简体) ), 150号, (中文(简体) ), 153号, (中文(简体) ), 158号 |
isPrivate() 错过 CGNAT、TEST-NET、基准、多播、保留、文件范围 | —— 说 |
cidrSubnet(...).contains() 返回时 false 用于 IPv4- mapped IPv6 地址 | 104号 |
isV6Format() 返回时 true 为 IPv4 地址 | 67号 |
isV4Format() 接受octets 256 键 | 105号 |
address('public') 已返回 私营 地址与反之 (过滤被倒转) | —— 说 |
loopback('ipv6') 已返回 fe80::1,这是链接 - 本地,而不是回转 ~ 现在 ::1 | —— 说 |
cidr()编号 :cidrSubnet() 静态生产垃圾,用于无效的前缀长度(/33, (中文(简体) ), /x) 现在抛出 | —— 说 |
address(name) 坠入 TypeError 未知接口名称 − 现在返回 undefined | —— 说 |
cidrSubnet()编号 :subnet() 给 IPv6 错误的答案 (/48 内有相邻者 /48^ 真实的IPv6子网数学 | 89号, (中文(简体) ), 110号 |
浏览器失败 os (网页包装5) ∗∗ browser 字段映射它离开 | #127号, (中文(简体) ), 132号 |
构造的脚本类型( 无) @types/ip (需要) | —— 说 |
从 ip 移动
- const ip = require('ip');
+ const ip = require('@bybrave/ip2');
API表面是相同的;行为差异是安全和正确性的修补——在升级前参见下面的断裂变化.
中断更改(v3)
第3.0.0版 因为严格性是固定的——如果你输入了这个库 非卡通字符串,v2会给你错误的答案,而不是兼容的答案:
isPrivate编号 :isPublic编号 :isLoopback编号 :toBuffer编号 :toLong掷出 (octal/hex octets,127.1,整数字符串). 使用normalizeToLong()首先,如果你必须接受 遗产标记.isLoopback('fe80::1')现在false(链接- 本地 qq; 仍然)isPrivate) (中文(简体) ).isLoopback('::')现在false(未指定 qq 循环; 仍然)isPrivate) (中文(简体) ).loopback('ipv6')返回时'::1'改为'fe80::1'。 。 。 .isPrivate()返回时true对于更多的范围(CGNAT,TEST-NETs,多播,.)——现在意思是"无法在全球达到".address('public')现在返回公共地址。 如果依靠倒向行为获得局域网地址,请使用address('private')这就是它给你的.- 节点.js 18.
API 密码
所有原始出口,还有 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)
const s6 = ip.cidrSubnet('2001:db8:f53b::/48')
s6.lastAddress // '2001:db8:f53b:ffff:ffff:ffff:ffff:ffff'
s6.contains('2001:db8:f53a::1') // false
s6.length // 2 ** 80 (approximate above 2 ** 53)
IPv6子网没有广播或保留主机地址: firstAddress 是网络地址和 broadcastAddress 等于 lastAddress。 。 。 . ip.subnet(addr, mask) 当地址和口罩都是IPv6时使用IPv6数学. 普通IPv4地址由IPv6子网通过IPv4-mapped范围相匹配(::ffff:0:0/96) (中文(简体) ).
无效的输入抛出
isPrivate, (中文(简体) ), isPublic, (中文(简体) ), isLoopback, (中文(简体) ), toBuffer 财务报告和审定财务报表 toLong 丢弃错误的输入而不是返回一个猜想( e)146号) (中文(简体) ). 当输入不可信时, 请先检查或抓取 :
const isInternal = ip.isValid(host) && ip.isPrivate(host)
浏览器和捆绑器
图书馆为节点第一. 在一个捆绑中, os 被映射通过 browser 字段,所以 address() 没空,其他的都用过一次 Buffer 已提供。 加上多填充(#127号, (中文(简体) ), 132号:
// webpack.config.js, after `npm i buffer`
resolve: { fallback: { buffer: require.resolve('buffer/') } }
作为私有范围处理(无法在全球达到)
IPv4: (英语) 0.0.0.0/8, (中文(简体) ), 10.0.0.0/8, (中文(简体) ), 100.64.0.0/10 (导航卫星系统), 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 (未说明,回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回回, 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地址.
支助
如果此软件包节省了您的时间, 您可以支持维护 :
比特币( BTC): bc1q37557q5jpeaxqydzwvf3jgj7zhnfpn2td3q40q
信贷和许可证
麻省理工学院. 依据 节点-ip 费多尔·印地安尼.