Securing & Inspecting Node.js Dependencies

Get To Know Your Packages

$ cd api-starter-kit

$ npm ls --prod

$ npm ls --prod --long

api-starter-kit@1.0.0
│ /home/ahmad/Projects/telus/api-starter-kit
│ ES6 RESTful Express API, with Telus OAuth.
├─┬ @newrelic/native-metrics@2.1.1
│ │ A module for generating metrics from V8.
│ │ git+ssh://git@github.com/newrelic/node-native-metrics.git
│ │ https://github.com/newrelic/node-native-metrics#readme
│ └── nan@2.6.2
│     Native Abstractions for Node.js: C++ header for Node 0.8 -> 7 compatibility
│     git://github.com/nodejs/nan.git
│     https://github.com/nodejs/nan#readme
├── @telusdigital/express-error-handlers@1.0.1
│   express error handlers
└── @telusdigital/node-utility-middlewares@2.3.0

npm ERR! extraneous: arc-object@1.5.0 /home/ahmad/Projects/telus/api-starter-kit/node_modules/arc-object/node_modules/arc-object
npm ERR! missing: arc-object@^1.2.0, required by arc-check@1.0.3

Clean-up Unused Packages

$ npm i -g depcheck

$ cd api-starter-kit

$ depcheck

Unused dependencies
* @newrelic/native-metrics
* compression

$ npm prune [--prod]

Latest & Greatest

$ cd api-starter-kit

$ npm outdated 

Package                    Current  Wanted  Latest  Location
codeclimate-test-reporter    0.4.1   0.4.1   0.5.0  api-starter-kit
eslint                      3.19.0  3.19.0   4.1.1  api-starter-kit
swagger-ui-express           1.0.8   1.0.8   2.0.1  api-starter-kit

$ npm i -g david

$ david

dependencies

┌────────────────────┬─────────┬────────┐
│ Name                  │ Package   │ Latest   │
├────────────────────┼─────────┼────────┤
│ swagger-ui-express    │ ^1.0.4    │ 2.0.1    │
└────────────────────┴─────────┴────────┘

npm install --save swagger-ui-express@2.0.1

Package BOMBS

$ more api-starter-kit/package.json

  "dependencies": {
    "@newrelic/native-metrics": "^2.1.0",
    "@telusdigital/node-utility-middlewares": "^2.0.0",
    "@telusdigital/express-error-handlers": "^1.0.0",
    "body-parser": "^1.13.3",
    "compression": "^1.5.2",
    "cors": "^2.7.1",
    "express": "^4.13.3",
    "express-winston": "^2.3.0",
    "newrelic": "^1.38.0",
    "node-fetch": "^1.6.3",
    "swagger-ui-express": "^1.0.4",
    "winston": "^2.3.1",
    "winston-tcp": "*"
  }


$ more winston-tcp/package.json

  "devDependencies": {
    "echint": "^4.0.*",
    "standard": "^10.0.2",
    "tap": "^10.3.2"
  }

Check Maintenance

$ npm view cors time.modified
2017-07-01T22:57:40.060Z

$ npm view cors repository

{ type: 'git',
  url: 'git+https://github.com/expressjs/cors.git' }

$ http https://api.github.com/repos/expressjs/cors/commits | jq ".[] | (.commit.author.date + .commit.message)"

"2017-03-30T02:55:30Z 2.8.3"
"2017-03-30T02:53:27Z docs: add partial history\n\ncloses #111"
"2017-03-30T02:20:24Z Fix error when options delegate missing \"methods\" option\n\nfixes #112"
"2017-03-29T00:56:54Z bump to 2.8.2"
"2017-03-26T06:04:04Z Send \"Vary: Access-Control-Request-Headers\" when dynamic allowedHeaders\n\nfixes #61"
"2017-03-02T08:16:55Z Send \"Vary: Origin\" when using regular expressions\n\ncloses #105\nfixes #106"
"2017-03-26T05:30:42Z tests: add test for empty list of exposed headers"
"2017-03-26T05:16:37Z build: add coverage reporting"
"2017-03-26T04:40:48Z tests: set express to test mode for tests"
"2017-03-26T04:26:33Z build: use shorthand package repository format"
"2017-03-26T04:24:54Z build: remove author from package contributors"
"2017-03-26T04:21:58Z build: use shorter package description"
"2017-03-26T04:18:04Z docs: remove old badge from contributing"
"2017-03-26T04:11:30Z docs: use standard badge set instead of nodeICO"
"2017-03-26T04:05:23Z build: update package scripts to work cross platform"
$ npm view cors maintainers
 
[ 'troygoode <troygoode@gmail.com>',
  'dougwilson <doug@somethingdoug.com>' ]

$ npm view cors repository

{ type: 'git',
  url: 'git+https://github.com/expressjs/cors.git' }

Check Maintainers

Beware Popular Packages!

Security Vulnerabilities!

$ npm i -g nsp snyk 

$ nsp check --output summary
(+) No known vulnerabilities found

$ snyk test

✗ Low severity vulnerability found on ms@0.7.1
- desc: Regular Expression Denial of Service (ReDoS)
- info: https://snyk.io/vuln/npm:ms:20170412
- from: api-starter-kit@1.0.0 > compression@1.6.2 > debug@2.2.0 > ms@0.7.1
No direct dependency upgrade can address this issue.
Run `snyk wizard` to explore remediation options.

Tested 122 dependencies for known vulnerabilities, found 1 vulnerability, 1 vulnerable path.

Certified Modules

Certified Modules

Native modules!

Node.js Addons are dynamically-linked shared objects, written in C++, that can be loaded into Node.js using the require() function, and used just as if they were an ordinary Node.js module. They are used primarily to provide an interface between JavaScript running in Node.js and C/C++ libraries.

Native modules!

  • verify at source code
  • check compiled distribution
  • binary scaner
     
  • compile yourself!

Known Suspects

Eval

HTTP response splitting

Exec / Spawn Command Injection

Raw log injection

Filesystem access

XSS / SQLi

CSRF

IDOR (insecure direct object reference)

Buffers  (out of bounds corruption)

BE PARANOID!

RTFC!

OWASP TOP 10

(Open Web Application Security Project)

  1. Injection
  2. Broken Authentication and Session Management
  3. Cross-Site Scripting (XSS)
  4. Broken Access Control
  5. Security Misconfiguration
  6. Sensitive Data Exposure
  7. Insufficient Attack Protection
  8. Cross-Site Request Forgery (CSRF)
  9. Using Components with Known Vulnerabilities
  10. Underprotected APIs

POP QUIZ!


const http = require('http')
const url = require('url')

http.createServer((req, res) => {
  const queryData = url.parse(req.url, true).query
  const name = queryData.id
  const name = queryData.name

  model.findById = (id, done) => {
    conn.query('SELECT * FROM table WHERE id = ' + id, function (err, rows) {
      res.writeHead(200, { 'Content-Type': 'text/html' })
      res.end(`Hello ${name}, here is your records ${JSON.stringify(rows)}`)
    })
  }
})

TL;DR

Security is Hard

ONE MORE THING!

Check for quality! 💛

Package          | LOC | Dependents | Downloads / Day | Downloads / Month | Last Month
---------------- | --- | ---------- | --------------- | ----------------- | ------------
isarray          | `1` | `184`      | `995,000 +`     | `22,714,000 +`    | 
trim-newlines    | `3` | `14`       | `200,000 +`     | `4,543,000 +`     | 
mkdirp-promise   | `3` | `38`       | `640 +`         | `12,800 +`        | (80,092 !!!)
stringify-clone  | `1` | `3`        | `900 +`         | `19,300 +`        | (57,757 !!!)


## github.com/juliangruber/isarray

var toString = {}.toString;

module.exports = Array.isArray || function (arr) {
  return toString.call(arr) == '[object Array]';
};

## github.com/sindresorhus/trim-newlines

'use strict';
module.exports = x => x.replace(/^[\r\n]+/, '').replace(/[\r\n]+$/, '');
module.exports.start = x => x.replace(/^[\r\n]+/, '');
module.exports.end = x => x.replace(/[\r\n]+$/, '');

## github.com/ahmadnassri/mkdirp-promise

const mkdirp = require('mkdirp')

module.exports = function (dir, opts) {
  return new Promise((resolve, reject) => {
    mkdirp(dir, opts, (err, made) => err === null ? resolve(made) : reject(err))
  })
}

## github.com/ahmadnassri/stringify-clone

module.exports = function (obj) {
  return JSON.parse(JSON.stringify(obj))
}

Securing and inspecting your node modules

By Ahmad Nassri

Securing and inspecting your node modules

  • 1,068