本指南介绍了如何迁移到安全的Buffer构造函数方法,迁移修复了以下弃用警告:
由于安全性和可用性问题,不建议使用 Buffer()和 new Buffer()构造函数,请改用 new Buffer.alloc()、Buffer.allocUnsafe()或 Buffer.from()构造方法。
只需运行grep -nrE '[^a-zA-Z](Slow)?Buffer\s*\(' --exclude-dir node_modules。
它会在你自己的代码中找到所有可能不安全的地方(有一些不太常见的例外)。
如果你使用的是Node.js ≥ 8.0.0(推荐使用),Node.js会公开多个选项,以帮助你找到相关的代码片段:
你可以使用环境变量设置这些标志:
$ export NODE_OPTIONS='--trace-warnings --pending-deprecation'
$ cat example.js
'use strict';
const foo = new Buffer('foo');
$ node example.js
(node:7147) [DEP0005] DeprecationWarning: The Buffer() and new Buffer() constructors are not recommended for use due to security and usability concerns. Please use the new Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() construction methods instead.
at showFlaggedDeprecation (buffer.js:127:13)
at new Buffer (buffer.js:148:3)
at Object.<anonymous> (/path/to/example.js:2:13)
[... more stack trace lines ...]
ESLint规则no-buffer-constructor或node/no-deprecated-api也查找对不推荐使用的Buffer() api的调用,这些规则包含在一些预设中。
但是有一个缺点,当Buffer被重写时,它并不总是正确工作,例如使用polyfill,因此建议将此与上述其他方法结合使用。
这是目前推荐的解决方案,仅意味着最小的开销。
自2016年7月以来,Node.js 5.x版本系列一直未得到支持,并且Node.js 4.x版本系列在2018年4月达到其生命周期结束(→计划)。
这意味着即使出现安全问题,这些版本的Node.js也不会收到任何更新,因此如果可能的话,应该避免使用这些版本线。
在这种情况下,你要做的是将所有new Buffer()或Buffer()调用转换为使用Buffer.alloc()或Buffer.from(),方法如下:
对于new Buffer(number),将其替换为Buffer.alloc(number)。
请注意,Buffer.alloc()在当前Node.js版本上的速度也比new Buffer(size).fill(0)快,这是你需要确保零填充的原因。
建议启用ESLint规则no-buffer-constructor或node/no-deprecated-api以避免意外的不安全Buffer API使用。
还有一个JSCodeshift codemod,用于自动将Buffer构造函数迁移到Buffer.alloc()或Buffer.from(),请注意,它目前仅适用于参数为文字或使用两个参数调用构造函数的情况。
如果你当前支持那些较旧的Node.js版本并且无法删除对它们的支持,或者如果你支持包的旧分支,考虑在较旧的分支上使用变式2或变式3,因此使用这些旧分支的人也将收到修复。这样,你将消除由不谨慎的Buffer API使用引起的潜在问题,并且在Node.js 10上运行代码时,你的用户将不会观察到运行时弃用警告。
有三种不同的polyfill可用:
你将采用与变式1完全相同的步骤,但是在使用新的Buffer API的所有文件中都使用polyfill const Buffer = require('safer-buffer').Buffer。
不要使用旧的new Buffer() API,在添加上面一行的任何文件中,使用旧的new Buffer() API将抛出。
你可以使用适当的名称导入所需的模块,例如const bufferFrom = require('buffer-from')然后使用它而不是调用new Buffer(),例如:new Buffer('test')变为bufferFrom('test')。
使用这种方法的一个缺点是从它们迁移出来的代码更改略多(因为你将使用不同名称下的Buffer.from())。
这种方法的缺点是它允许你在代码中使用较旧的new Buffer() API,这是有问题的,因为它可能会导致代码中出现问题,并将从Node.js 10开始发出运行时弃用警告(在此处阅读更多内容)。
请注意,在任何一种情况下,你还必须手动删除对旧Buffer API的所有调用,只是投入safe-buffer本身并不能解决问题,它只是为新API提供了一个polyfill,我看到有人犯了这个错误。
建议启用ESLint规则no-buffer-constructor或node/no-deprecated-api。
放弃对Node.js <4.5.0的支持后,不要忘记删除polyfill使用。
如果你只在几个地方(例如一个)创建Buffer实例,或者你有自己的包装器,这将非常有用。
这个用于创建空缓冲区的特殊情况可以安全地替换为Buffer.concat([]),它返回相同的结果一直到Node.js 0.8.x。
之前:
const buf = new Buffer(notNumber, encoding);
以后:
let buf;
if (Buffer.from && Buffer.from !== Uint8Array.from) {
buf = Buffer.from(notNumber, encoding);
} else {
if (typeof notNumber === 'number') {
throw new Error('The "size" argument must be not of type number.');
}
buf = new Buffer(notNumber, encoding);
}
encoding是可选的。
请注意,typeof notNumber必须在new Buffer()之前,(对于notNumber参数未进行硬编码的情况)并且不是由Buffer构造函数的弃用引起的 - 这正是不推荐使用Buffer构造函数的原因。缺乏此类型检查的生态系统包导致了许多安全问题 - 当未经过处理的用户输入可能最终出现在Buffer(arg)中时,会出现从DoS到从进程内存向攻击者泄漏敏感信息等问题。
当notNumber参数被硬编码时(例如文字"abc"或[0,1,2]),可以省略typeof检查。
另请注意,使用TypeScript不能解决此问题 - 当从JS中使用用TypeScript编写的库时,或者当用户输入结束时 - 它的行为与纯JS一样,因为所有类型检查只是转换时间,并且不存在于TS编译的实际JS代码中。
对于Node.js 0.10.x(及以下)支持:
var buf;
if (Buffer.alloc) {
buf = Buffer.alloc(number);
} else {
buf = new Buffer(number);
buf.fill(0);
}
否则(Node.js ≥ 0.12.x):
const buf = Buffer.alloc ? Buffer.alloc(number) : new Buffer(number).fill(0);
使用Buffer.allocUnsafe()时要格外小心:
如果你没有充分的理由,请不要使用它。
如果使用它,请确保永远不会以部分填充状态返回buffer。
处理使用Buffer.allocUnsafe()分配的缓冲区中的错误可能会导致各种问题,包括代码的未定义行为,以及泄露给远程攻击者的敏感数据(用户输入、密码、证书)。
请注意,这同样适用于没有零填充的new Buffer()用法,具体取决于Node.js版本(缺少类型检查也会将DoS添加到潜在问题列表中)。
Buffer构造函数有什么问题?
Buffer构造函数可用于以多种不同方式创建缓冲区:
这意味着在像var buffer = new Buffer(foo);这样的代码中,在不知道foo类型的情况下,无法确定生成的缓冲区的确切内容。
有时,foo的值来自外部来源,例如,此函数可以作为Web服务器上的服务公开,将UTF-8字符串转换为其Base64格式:
function stringToBase64(req, res) {
// The request body should have the format of `{ string: 'foobar' }`.
const rawBytes = new Buffer(req.body.string);
const encoded = rawBytes.toString('base64');
res.end({ encoded });
}
请注意,此代码不验证req.body.string的类型:
如果req.body.string是数字50,则rawBytes将是50个字节:
由于缺少类型检查,攻击者可以故意发送一个号码作为请求的一部分,使用它,他们可以:
在现实世界的Web服务器环境中,这两种情况都被认为是严重的安全问题。
当使用Buffer.from(req.body.string)时,传递一个数字将总是抛出一个异常,提供可由程序始终处理的受控行为。
npm生态系统中的代码调查表明,Buffer()构造函数仍然被广泛使用,这包括新代码,并且此类代码的总体使用实际上已经增加。
在ES5中,咱们合并对象通常使用Lodash的_.extend(target, [sources]) 方法,在ES6中咱们使用 Object.assign(target, [sources])来合并对象,当然现在最常用应该是使用 Rest/Spread(展开运算符与剩余操作符)。
开发人员需要做的决策有很多。当 Web 应用程序的需求确定下来之后,就该选择效率最高的 Web 技术栈了。Web 技术栈是用于创建 Web 应用程序的技术工具集。一套 Web 技术栈由 OS(操作系统)、Web 服务器
闭包就是指 能够访问另一个函数作用域的变量的函数 ,闭包就是一个函数,能够访问其他函数的作用域中的变量,js有一个全局对象,在浏览器下是window,node下是global,所有的函数都在这个对象下
一切都从对象开始。对象,即我们相互交流的一个载体,有其属性和方法。对象是面向对象编程的核心,不仅用于JavaScript,而且还适用于Java、C语言、C++等。
WebAssembly(Wasm)是 Web 浏览器中相对较新的功能,但它地扩展了把 Web 作为服务应用平台的功能潜力。对于 Web 开发人员来说,学习使用 WebAssembly 可能会有一个艰难的过程
很多接触过程序员的人,都有一种体会:程序员=聊天终结者。经常用简短有力的几个字结束掉你苦心经营的聊天氛围,比如:你现在忙不忙?忙。那我真的是打扰了
SVG,即可缩放矢量图形(Scalable Vector Graphics),是一种 XML 应用,可以以一种简洁、可移植的形式表示图形信息。目前,人们对 SVG 越来越感兴趣。大多数现代浏览器都能显示 SVG 图形,并且大多数矢量绘图软件都能导出 SVG 图形
JavaScript 使用原型继承:每个对象都从其原型对象继承属性和方法。在 JavaScript 中不存在 Java 或 Swift 等语言中所使用的作为创建对象 蓝图的传统类,原型继承仅处理对象。
很多时候 <textarea> 并不能满足我们对文本输入的需求,当我们需要为输入的文本添加格式时,我们需要使用像 quill 这样的富文本编辑器来完成富文本的输入。本文将会详细的讲解如何使用 quill 定制一个自己的富文本编辑器。
RxJS 是 Reactive Extensions for JavaScript 的缩写,起源于 Reactive Extensions,是一个基于可观测数据流 Stream 结合观察者模式和迭代器模式的一种异步编程的应用库。RxJS 是 Reactive Extensions 在 JavaScript 上的实现
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!