Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
safer-buffer
Advanced tools
The safer-buffer package provides a safer alternative to the Node.js Buffer API, which has had security and usability issues, especially Buffer constructor being overloaded and not initializing memory to zero. safer-buffer provides a polyfill for the Buffer.alloc(), Buffer.allocUnsafe(), and Buffer.from() methods that were introduced in Node.js v4.5.0 and v5.10.0 as a safer API. It allows developers to write code that works with older versions of Node.js without the risk of introducing security vulnerabilities.
Creating a buffer with initialized memory
This feature allows the creation of a new Buffer with its memory initialized to zero, preventing the risk of sensitive data being leaked.
var saferBuffer = require('safer-buffer').Buffer;
var buffer = saferBuffer.alloc(10); // creates a buffer of 10 bytes with memory set to zero
Creating a buffer with uninitialized memory
This feature creates a new Buffer with uninitialized memory for better performance, but it should be used with caution as it may contain old or sensitive data.
var saferBuffer = require('safer-buffer').Buffer;
var buffer = saferBuffer.allocUnsafe(10); // creates a buffer of 10 bytes without initializing memory
Creating a buffer from an existing array
This feature allows the creation of a Buffer from an existing array of bytes or other data types.
var saferBuffer = require('safer-buffer').Buffer;
var buffer = saferBuffer.from([0x62, 0x75, 0x66]); // creates a buffer from an array of bytes
The 'buffer' package on npm is a Node.js Buffer polyfill that provides similar functionality to safer-buffer. It includes methods like Buffer.from(), Buffer.alloc(), and Buffer.allocUnsafe(). The main difference is that 'buffer' is a more comprehensive polyfill that also includes additional features and improvements beyond just the safer constructors.
The 'safe-buffer' package is another alternative that provides a safer version of the Node.js Buffer API. It is similar to safer-buffer in that it backports newer Buffer APIs to older versions of Node.js. However, 'safe-buffer' is more widely used and maintained, which might make it a preferable choice for some projects.
Modern Buffer API polyfill without footguns, working on Node.js from 0.8 to current.
First, port all Buffer()
and new Buffer()
calls to Buffer.alloc()
and Buffer.from()
API.
Then, to achieve compatibility with outdated Node.js versions (<4.5.0
and 5.x <5.9.0
), use
const Buffer = require('safer-buffer').Buffer
in all files where you make calls to the new
Buffer API. Use var
instead of const
if you need that for your Node.js version range support.
Also, see the porting Buffer guide.
Hopefully, not — dropping support for outdated Node.js versions should be fine nowdays, and that
is the recommended path forward. You do need to port to the Buffer.alloc()
and Buffer.from()
though.
See the porting guide for a better description.
In short: while safe-buffer
serves as a polyfill for the new API, it allows old API usage and
itself contains footguns.
safe-buffer
could be used safely to get the new API while still keeping support for older
Node.js versions (like this module), but while analyzing ecosystem usage of the old Buffer API
I found out that safe-buffer
is itself causing problems in some cases.
For example, consider the following snippet:
$ cat example.unsafe.js
console.log(Buffer(20))
$ ./node-v6.13.0-linux-x64/bin/node example.unsafe.js
<Buffer 0a 00 00 00 00 00 00 00 28 13 de 02 00 00 00 00 05 00 00 00>
$ standard example.unsafe.js
standard: Use JavaScript Standard Style (https://standardjs.com)
/home/chalker/repo/safer-buffer/example.unsafe.js:2:13: 'Buffer()' was deprecated since v6. Use 'Buffer.alloc()' or 'Buffer.from()' (use 'https://www.npmjs.com/package/safe-buffer' for '<4.5.0') instead.
This is allocates and writes to console an uninitialized chunk of memory. standard linter (among others) catch that and warn people to avoid using unsafe API.
Let's now throw in safe-buffer
!
$ cat example.safe-buffer.js
const Buffer = require('safe-buffer').Buffer
console.log(Buffer(20))
$ standard example.safe-buffer.js
$ ./node-v6.13.0-linux-x64/bin/node example.safe-buffer.js
<Buffer 08 00 00 00 00 00 00 00 28 58 01 82 fe 7f 00 00 00 00 00 00>
See the problem? Adding in safe-buffer
magically removes the lint warning, but the behavior
remains identiсal to what we had before, and when launched on Node.js 6.x LTS — this dumps out
chunks of uninitialized memory.
And this code will still emit runtime warnings on Node.js 10.x and above.
That was done by design. I first considered changing safe-buffer
, prohibiting old API usage or
emitting warnings on it, but that significantly diverges from safe-buffer
design. After some
discussion, it was decided to move my approach into a separate package, and this is that separate
package.
This footgun is not imaginary — I observed top-downloaded packages doing that kind of thing,
«fixing» the lint warning by blindly including safe-buffer
without any actual changes.
Also in some cases, even if the API was migrated to use of safe Buffer API — a random pull request can bring unsafe Buffer API usage back to the codebase by adding new calls — and that could go unnoticed even if you have a linter prohibiting that (becase of the reason stated above), and even pass CI. I also observed that being done in popular packages.
Some examples:
I filed a PR at mysticatea/eslint-plugin-node#110 to partially fix that (for cases when that lint rule is used), but it is a semver-major change for linter rules and presets, so it would take significant time for that to reach actual setups. It also hasn't been released yet (2018-03-20).
Also, safer-buffer
discourages the usage of .allocUnsafe()
, which is often done by a mistake.
It still supports it with an explicit concern barier, by placing it under
require('safer-buffer/dangereous')
.
Not really. It's an error that could be noticed and fixed early, instead of causing havoc later like
unguarded new Buffer()
calls that end up receiving user input can do.
This package affects only the files where var Buffer = require('safer-buffer').Buffer
was done, so
it is really simple to keep track of things and make sure that you don't mix old API usage with that.
Also, CI should hint anything that you might have missed.
New commits, if tested, won't land new usage of unsafe Buffer API this way. Node.js 10.x also deals with that by printing a runtime depecation warning.
No, unless you explicitly do an awful thing like monkey-patching or overriding the built-in Buffer
.
Don't do that.
That is also fine!
Also, it could be better in some cases when you don't comprehensive enough test coverage.
In that case — just don't override Buffer
and use
var SaferBuffer = require('safer-buffer').Buffer
instead.
That way, everything using Buffer
natively would still work, but there would be two drawbacks:
Buffer.from
/Buffer.alloc
won't be polyfilled — use SaferBuffer.from
and
SaferBuffer.alloc
instead.Note that using a linter to catch accidential Buffer
constructor usage in this case is strongly
recommended. Buffer
is not overriden in this usecase, so linters won't get confused.
Well, it is still possible to do some things with Buffer
API, e.g. accessing .buffer
property
on older versions and duping things from there. You shouldn't do that in your code, probabably.
The intention is to remove the most significant footguns that affect lots of packages in the ecosystem, and to do it in the proper way.
Also, this package doesn't protect against security issues affecting some Node.js versions, so for usage in your own production code, it is still recommended to update to a Node.js version supported by upstream.
FAQs
Modern Buffer API polyfill without footguns
The npm package safer-buffer receives a total of 29,203,923 weekly downloads. As such, safer-buffer popularity was classified as popular.
We found that safer-buffer demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.