Security advisory GHSA-xqh8-5j36-4556: SQL Injection in connect-pg-simple
Package: connect-pg-simple (npm), vulnerable version: 6.0.0, fixed in: 6.0.1
CWE: CWE-89
Files changed by the fix:
b/index.js
b/test/db-utils.js
b/test/main.spec.js

Fix diff:
diff -ruN --no-dereference /home/ubuntu/closed-source-intelligence/data/cache/npm-tarballs/connect-pg-simple-6.0.0/.github/workflows/nodejs.yml /home/ubuntu/closed-source-intelligence/data/cache/npm-tarballs/connect-pg-simple-6.0.1/.github/workflows/nodejs.yml
--- a/.github/workflows/nodejs.yml
+++ b/.github/workflows/nodejs.yml
@@ -0,0 +1,25 @@
+name: Node CI
+
+on: [push]
+
+jobs:
+  test:
+    name: Test on node ${{ matrix.node_version }} and ${{ matrix.os }}
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        node_version: [10, 12]
+        os: [ubuntu-latest, windows-latest]
+
+    steps:
+    - uses: actions/checkout@v1
+    - name: Use Node.js ${{ matrix.node_version }}
+      uses: actions/setup-node@v1
+      with:
+        version: ${{ matrix.node_version }}
+
+    - name: npm install, build and test
+      run: |
+        npm install
+        npm run build --if-present
+        npm test
diff -ruN --no-dereference /home/ubuntu/closed-source-intelligence/data/cache/npm-tarballs/connect-pg-simple-6.0.0/.travis.yml /home/ubuntu/closed-source-intelligence/data/cache/npm-tarballs/connect-pg-simple-6.0.1/.travis.yml
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,7 +2,7 @@
 before_script:
   - psql -c 'create database connect_pg_simple_test;' -U postgres
 sudo: false
-script: npm test
+script: npm run test:mocha
 after_success:
   - "cat coverage/lcov.info | ./node_modules/.bin/coveralls"
 matrix:
@@ -13,3 +13,10 @@
     - node_js: "10"
       addons:
         postgresql: "9.6"
+jobs:
+  include:
+    - stage: static checks
+      node_js: "12"
+      addons:
+        postgresql: "9.6"
+      script: npm run check
diff -ruN --no-dereference /home/ubuntu/closed-source-intelligence/data/cache/npm-tarballs/connect-pg-simple-6.0.0/CHANGELOG.md /home/ubuntu/closed-source-intelligence/data/cache/npm-tarballs/connect-pg-simple-6.0.1/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,15 @@
 # Changelog
 
-## 6.0.0 (YYYY-MM-DD)
+## 6.0.1 (2019-08-21)
+
+* Very minor security fix: `schemaName` and `tableName` wasn't escaped. If any of the two contained a string with a double quote in it, then that would enable an SQL injection. This was previously a feature of `tableName`, before the introduction of a separate `schemaName`, as that allowed a schema to be defined as part of `tableName`. Defining schema name through `tableName` is still supported after this fix, but is now *deprecated*.
+* Fix: Errors wasn't propagated properly. Fixed in #150. Thanks @bobnil!
+
+## 6.0.0 (2019-07-28)
 
 * Breaking change: Now requires at least Node.js 10.x, this as Node.js 8.x [only have a short time left in its LTS](https://github.com/nodejs/Release)
 * Breaking change: This project now uses [`INSERT ... ON CONFLICT`](https://www.postgresql.org/docs/current/sql-insert.html#SQL-ON-CONFLICT), more popularly known as `UPSERT`. This is only supported on PostgreSQL version 9.5 and above.
+* Listen on pool errors. Fixes #29
 
 ## 5.0.0 (2018-06-06)
 
diff -ruN --no-dereference /home/ubuntu/closed-source-intelligence/data/cache/npm-tarballs/connect-pg-simple-6.0.0/README.md /home/ubuntu/closed-source-intelligence/data/cache/npm-tarballs/connect-pg-simple-6.0.1/README.md
--- a/README.md
+++ b/README.md
@@ -3,13 +3,13 @@
 A simple, minimal PostgreSQL session store for Express/Connect
 
 [![js-semistandard-style](https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg?style=flat)](https://github.com/Flet/semistandard)
-[![Build Status](https://travis-ci.org/voxpelli/node-connect-pg-simple.svg?branch=master)](https://travis-ci.org/voxpelli/node-connect-pg-simple)
+[![Build Status](https://travis-ci.com/voxpelli/node-connect-pg-simple.svg?branch=master)](https://travis-ci.com/voxpelli/node-connect-pg-simple)
 [![Coverage Status](https://coveralls.io/repos/voxpelli/node-connect-pg-simple/badge.svg)](https://coveralls.io/r/voxpelli/node-connect-pg-simple)
 [![dependencies Status](https://david-dm.org/voxpelli/node-connect-pg-simple/status.svg)](https://david-dm.org/voxpelli/node-connect-pg-simple)
 [![Known Vulnerabilities](https://snyk.io/test/github/voxpelli/node-connect-pg-simple/badge.svg?targetFile=package.json)](https://snyk.io/test/github/voxpelli/node-connect-pg-simple?targetFile=package.json)
 [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fvoxpelli%2Fnode-connect-pg-simple.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fvoxpelli%2Fnode-connect-pg-simple?ref=badge_shield)
-[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/voxpelli/node-connect-pg-simple.svg)](http://isitmaintained.com/project/voxpelli/node-connect-pg-simple "Average time to resolve an issue")
-[![Percentage of issues still open](http://isitmaintained.com/badge/open/voxpelli/node-connect-pg-simple.svg)](http://isitmaintained.com/project/voxpelli/node-connect-pg-simple "Percentage of issues still open")
+[![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/voxpelli/node-connect-pg-simple.svg)](https://isitmaintained.com/project/voxpelli/node-connect-pg-simple "Average time to resolve an issue")
+[![Percentage of issues still open](https://isitmaintained.com/badge/open/voxpelli/node-connect-pg-simple.svg)](https://isitmaintained.com/project/voxpelli/node-connect-pg-simple "Percentage of issues still open")
 [![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/voxpelli/node-connect-pg-simple.svg?style=flat)](https://lgtm.com/projects/g/voxpelli/node-connect-pg-simple/context:javascript)
 
 
diff -ruN --no-dereference /home/ubuntu/closed-source-intelligence/data/cache/npm-tarballs/connect-pg-simple-6.0.0/index.js /home/ubuntu/closed-source-intelligence/data/cache/npm-tarballs/connect-pg-simple-6.0.1/index.js
--- a/index.js
+++ b/index.js
@@ -7,6 +7,12 @@
   return Math.ceil(Date.now() / 1000);
 };
 
+/**
+ * See
+ * @see https://www.postgresql.org/docs/9.5/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
+ */
+const escapePgIdentifier = (value) => value.replace(/"/g, '""');
+
 module.exports = function (session) {
   const Store = session.Store || session.session.Store;
 
@@ -14,8 +20,13 @@
     options = options || {};
     Store.call(this, options);
 
-    this.schemaName = options.schemaName || null;
-    this.tableName = options.tableName || 'session';
+    this.schemaName = options.schemaName ? escapePgIdentifier(options.schemaName) : null;
+    this.tableName = options.tableName ? escapePgIdentifier(options.tableName) : 'session';
+
+    if (!this.schemaName && this.tableName.includes('"."')) {
+      console.warn('DEPRECATION WARNING: Schema should be provided through its dedicated "schemaName" option rather than through "tableName"');
+      this.tableName = this.tableName.replace(/^([^"]+)""\.""([^"]+)$/, '$1"."$2');
+    }
 
     this.ttl = options.ttl;
 
@@ -53,9 +64,7 @@
       this.pruneSessionInterval = false;
     } else {
       this.pruneSessionInterval = (options.pruneSessionInterval || 60) * 1000;
-      setImmediate(function () {
-        this.pruneSessions();
-      }.bind(this));
+      setImmediate(() => { this.pruneSessions(); });
     }
   };
 
@@ -94,7 +103,7 @@
    */
 
   PGStore.prototype.pruneSessions = function (fn) {
-    this.query('DELETE FROM ' + this.quotedTable() + ' WHERE expire < to_timestamp($1)', [currentTimestamp()], function (err) {
+    this.query('DELETE FROM ' + this.quotedTable() + ' WHERE expire < to_timestamp($1)', [currentTimestamp()], err => {
       if (fn && typeof fn === 'function') {
         return fn(err);
       }
@@ -107,10 +116,10 @@
         if (this.pruneTimer) {
           clearTimeout(this.pruneTimer);
         }
-        this.pruneTimer = setTimeout(this.pruneSessions.bind(this, true), this.pruneSessionInterval);
+        this.pruneTimer = setTimeout(() => { this.pruneSessions(); }, this.pruneSessionInterval);
         this.pruneTimer.unref();
       }
-    }.bind(this));
+    });
   };
 
   /**
@@ -182,7 +191,7 @@
    */
 
   PGStore.prototype.get = function (sid, fn) {
-    this.query('SELECT sess FROM ' + this.quotedTable() + ' WHERE sid = $1 AND expire >= to_timestamp($2)', [sid, currentTimestamp()], function (err, data) {
+    this.query('SELECT sess FROM ' + this.quotedTable() + ' WHERE sid = $1 AND expire >= to_timestamp($2)', [sid, currentTimestamp()], (err, data) => {
       if (err) { return fn(err); }
       if (!data) { return fn(); }
       try {
@@ -190,7 +199,7 @@
       } catch (e) {
         return this.destroy(sid, fn);
       }
-    }.bind(this));
+    });
   };
 
   /**
@@ -207,7 +216,7 @@
     const query = 'INSERT INTO ' + this.quotedTable() + ' (sess, expire, sid) SELECT $1, to_timestamp($2), $3 ON CONFLICT (sid) DO UPDATE SET sess=$1, expire=to_timestamp($2) RETURNING sid';
 
     this.query(query, [sess, expireTime, sid], function (err) {
-      if (fn) { fn.apply(this, err); }
+      if (fn) { fn.call(this, err); }
     });
   };
 
diff -ruN --no-dereference /home/ubuntu/closed-source-intelligence/data/cache/npm-tarballs/connect-pg-simple-6.0.0/package.json /home/ubuntu/closed-source-intelligence/data/cache/npm-tarballs/connect-pg-simple-6.0.1/package.json
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "connect-pg-simple",
-  "version": "6.0.0",
+  "version": "6.0.1",
   "description": "A simple, minimal PostgreSQL session store for Connect/Express",
   "url": "http://github.com/voxpelli/node-connect-pg-simple",
   "repository": {
@@ -22,7 +22,7 @@
   "main": "index.js",
   "scripts": {
     "check:dependency-check": "dependency-check *.js 'test/**/*.js' --no-dev",
-    "check:installed-check": "installed-check -e -i eslint",
+    "check:installed-check": "installed-check -i eslint",
     "check:lint": "eslint .",
     "check": "run-p check:*",
     "light:mocha": "NODE_ENV=test nyc --reporter=lcov --reporter text mocha test/*.spec.js",
@@ -36,32 +36,31 @@
     }
   },
   "devDependencies": {
-    "chai": "4.2.0",
-    "chai-as-promised": "7.1.1",
-    "cookie-signature": "1.1.0",
-    "cookiejar": "2.1.2",
-    "coveralls": "3.0.5",
-    "denodeify": "1.2.1",
-    "dependency-check": "4.0.1",
-    "dotenv": "8.0.0",
-    "eslint": "6.1.0",
-    "eslint-config-semistandard": "14.0.0",
-    "eslint-config-standard": "13.0.1",
-    "eslint-plugin-import": "2.18.2",
-    "eslint-plugin-node": "9.1.0",
-    "eslint-plugin-promise": "4.2.1",
-    "eslint-plugin-standard": "4.0.0",
-    "express": "4.17.1",
-    "express-session": "1.16.2",
-    "husky": "3.0.1",
-    "installed-check": "2.2.0",
-    "mocha": "6.2.0",
-    "npm-run-all": "4.1.5",
-    "nyc": "14.1.1",
-    "pg-promise": "9.0.0",
-    "proxyquire": "2.1.1",
-    "sinon": "7.3.2",
-    "sinon-chai": "3.3.0",
-    "supertest": "4.0.2"
+    "chai": "^4.2.0",
+    "chai-as-promised": "^7.1.1",
+    "cookie-signature": "^1.1.0",
+    "cookiejar": "^2.1.2",
+    "coveralls": "^3.0.6",
+    "dependency-check": "^4.1.0",
+    "dotenv": "^8.0.0",
+    "eslint": "^6.1.0",
+    "eslint-config-semistandard": "^14.0.0",
+    "eslint-config-standard": "^13.0.1",
+    "eslint-plugin-import": "^2.18.2",
+    "eslint-plugin-node": "^9.1.0",
+    "eslint-plugin-promise": "^4.2.1",
+    "eslint-plugin-standard": "^4.0.0",
+    "express": "^4.17.1",
+    "express-session": "^1.16.2",
+    "husky": "^3.0.3",
+    "installed-check": "^3.0.0",
+    "mocha": "^6.2.0",
+    "npm-run-all": "^4.1.5",
+    "nyc": "^14.1.1",
+    "pg-promise": "^9.0.0",
+    "proxyquire": "^2.1.2",
+    "sinon": "^7.4.1",
+    "sinon-chai": "^3.3.0",
+    "supertest": "^4.0.2"
   }
 }
diff -ruN --no-dereference /home/ubuntu/closed-source-intelligence/data/cache/npm-tarballs/connect-pg-simple-6.0.0/test/db-utils.js /home/ubuntu/closed-source-intelligence/data/cache/npm-tarballs/connect-pg-simple-6.0.1/test/db-utils.js
--- a/test/db-utils.js
+++ b/test/db-utils.js
@@ -10,12 +10,12 @@
   database: process.env.PGDATABASE || 'connect_pg_simple_test'
 };
 
-const denodeify = require('denodeify');
+const { promisify } = require('util');
 const pg = require('pg');
 
 const pool = new pg.Pool(conObject);
 
-const readFile = denodeify(require('fs').readFile);
+const readFile = promisify(require('fs').readFile);
 
 const tables = ['session'];
 
diff -ruN --no-dereference /home/ubuntu/closed-source-intelligence/data/cache/npm-tarballs/connect-pg-simple-6.0.0/test/main.spec.js /home/ubuntu/closed-source-intelligence/data/cache/npm-tarballs/connect-pg-simple-6.0.1/test/main.spec.js
--- a/test/main.spec.js
+++ b/test/main.spec.js
@@ -150,6 +150,16 @@
       options.tableName = 'barfoo.foobar';
       (new PGStore(options)).quotedTable().should.be.a('string').that.equals('"barfoo.foobar"');
     });
+
+    it('should escape table name', function () {
+      options.tableName = 'foo"ba"r';
+      (new PGStore(options)).quotedTable().should.be.a('string').that.equals('"foo""ba""r"');
+    });
+
+    it('should escape schema name', function () {
+      options.schemaName = 'b""ar"foo';
+      (new PGStore(options)).quotedTable().should.be.a('string').that.equals('"b""""ar""foo"."session"');
+    });
   });
 
   describe('configSetup', function () {