Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
node-sec-patterns
Advanced tools
Allow projects control over which dependencies can create objects that encapsulate security guarantees.
This project provides an NPM module that enables a variety of security design patterns in Node.js code.
$ npm install node-sec-patterns
Make it easier for project teams to produce code that preserves important security properties.
This module attempts to further that goal by enabling and encouraging development practices that make it transparent what code has to function correctly for a security property to hold.
We assume that the app main file does something like the below before any malicious code can run:
require('node-sec-patterns').authorize(require('./package.json'), '.')
The code below assumes that package.json
contains the configuration
but it is the call to authorize
that determines which configuration
is used.
Ideally this would be the first line in the main file.
Library code authors should not call authorize
. It should only
be called by the main module that integrates a production system
or by test code that tests a module's function under
various configurations.
.authorize(config, projectRoot)
An application's main module should call the authorize
function
before loading modules that need to create mintable types.
It takes two parameters:
"mintable"
.
See Configuration.__dirname
of the module that loaded .authorize
.If you authorize
d the package as above, then configuration happens
via a "mintable"
propery in your package.json
like the below:
{
"name": "my-project",
"...": "...",
"mintable": {
"mode": "enforce",
"grants": {
"contract-key-foo": [
"foo",
"./lib/bar.js"
],
}
}
}
That configuration grants module "foo"
access to the minter for any
mintable types whose contract key is "contract-key-foo"
.
Minters convey the authority to create values of the mintable type
that pass the corresponding verifier.
If "mintable": {...}
is not present, then it defaults to
{ "mode": "permissive", "grants": {} }
so projects that do not
opt-into whitelisting will allow any code access to the minter.
If "mintable"
is present but "mode": ...
is not present,
it defaults to "enforce"
.
If "mode"
is "permissive"
then all accesses are allowed.
If "mode"
is "report-only"
then all accesses are allowed.
Library code may also suggest grants. It may self nominate for certain privileges, and then an application may second those privileges.
For example, if a library's package.json includes
{
...
"mintable": {
"selfNominate": [
"contractKey0",
"contractKey1"
]
}
}
and an application's package.json includes
{
...
"mintable": {
"second": [
"path/to/library"
]
}
}
then Mintable.minterFor
will behave as if the application's
package.json had done
{
...
"mintable": {
"grants": {
"contractKey0": [ "path/to/library" ],
"contractKey1": [ "path/to/library" ]
}
}
}
Application maintainers can run the below to see what effect self nominations have, but keep in mind that a package might change its self nominations in future versions so seconding self-nominated grants for a module is placing trust in that module's future development practices.
$ node -e 'for (const second of require(`./package.json`).mintable.second) {
const config = /[.]json$/.test(second) ? second : `${ second }/package.json`;
console.group(second);
console.log(JSON.stringify(require(config).mintable.selfNominate, null, 2));
console.groupEnd();
}'
Seconded nominations are resolved using the following algorithm:
.json
then targetConfigPath += '/package.json'If a self nomination path ends in .json
then /package.json
is not appended to the
config file.
Internal package directories are stripped when figuring out to whom access is granted.
Mintable types are subclasses of class Mintable
exported by this module.
Mintable types must have a static property that specifies their contract
key. This property should be const.
A simple way to do this is
const { Mintable } = require('node-sec-patterns')
class FooContractType extends Mintable {
constructor () {
super()
}
}
Object.defineProperty(
FooContractType,
'contractKey',
{
value: 'contract-key-foo',
configurable: false,
writable: false
})
If, for example, we wanted to reify the guarantee that a string of HTML is safe to load into an HTML document in the organization's origin, we might create a string wrapper like safe contract types.
class SafeHtml extends Mintable {
constructor (stringContent) {
this.content = '' + stringContent
Object.freeze(this)
}
}
Object.defineProperty(
SafeHtml,
'contentKey',
{
value: 'goog.html.SafeHtml',
configurable: false,
writable: false
})
Instead of using new
just pass the same arguments to the minter.
// The minter may be fetched once.
const fooMinter = require.moduleKeys.unboxStrict(Mintable.minterFor(FooContractType))
const newInstance =
// instead of (new FooContractType(x, y))
fooMinter(x, y)
Minters are boxed, so you have to unbox a minter before using it.
Library code may want to mint a value when it has authority to do so or degrade gracefully when it does not.
Trying to unbox Mintable.minterFor(
T)
when you do not have the
authority to mint values of type T will throw
but you may pass a
fallback function to unbox
to return when you are not
authorized. Either way, users of your library who have not
whitelisted it will get a log warning to prompt them to consider
granting authority to your library.
const fooMinter = require.moduleKeys.unbox(
Mintable.minterFor(FooContractType),
() => true,
fallbackValueMaker)
Values created by the fallback function will not pass the verifier.
Object.create
can forge values that pass instanceof
checks, so
be sure to use the verifier to check whether a value was created
by the minter.
const isFoo = Mintable.verifierFor(FooContractType)
A package may allow some modules access to the minter but not others. This enables workflows like:
package.json
for their
project granting access.package.json
and see that the added dependency is
security critical.This allows a development team, collectively, to reify some security guarantees in JavaScript objects and ensure that only a small, checkable core of code can produce those values.
This module provides a mechanism by which:
package.json
and the main file.FAQs
Allow projects control over which dependencies can create objects that encapsulate security guarantees.
The npm package node-sec-patterns receives a total of 19 weekly downloads. As such, node-sec-patterns popularity was classified as not popular.
We found that node-sec-patterns 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.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.