Skip to content

Commit

Permalink
feat: Escape user input before executing sql
Browse files Browse the repository at this point in the history
  • Loading branch information
morgsmccauley committed Jul 18, 2023
1 parent 2116c94 commit f2c9269
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 8 deletions.
14 changes: 14 additions & 0 deletions indexer-js-queue-handler/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions indexer-js-queue-handler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"near-api-js": "1.1.0",
"node-fetch": "^3.3.0",
"pg": "^8.11.1",
"pg-format": "^1.0.4",
"pluralize": "^8.0.0",
"verror": "^1.10.1",
"vm2": "^3.9.13"
Expand Down
13 changes: 8 additions & 5 deletions indexer-js-queue-handler/provisioner.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import VError from "verror";
import pg from "pg";
import cryptoModule from "crypto";
import pgFormatModule from "pg-format";

import HasuraClient from "./hasura-client.js";

Expand All @@ -20,11 +21,13 @@ export default class Provisioner {
constructor(
hasuraClient = new HasuraClient(),
pgPool = pool,
crypto = cryptoModule
crypto = cryptoModule,
pgFormat = pgFormatModule
) {
this.hasuraClient = hasuraClient;
this.pgPool = pgPool;
this.crypto = crypto;
this.pgFormat = pgFormat;
}

async query(query, params = []) {
Expand All @@ -46,16 +49,16 @@ export default class Provisioner {
}

async createDatabase(name) {
await this.query(`CREATE DATABASE ${name}`);
await this.query(this.pgFormat('CREATE DATABASE %I', name));
}

async createUser(name, password) {
await this.query(`CREATE USER ${name} WITH PASSWORD '${password}';`)
await this.query(this.pgFormat(`CREATE USER %I WITH PASSWORD '%I'`, name, password))
}

async restrictDatabaseToUser(databaseName, userName) {
await this.query(`GRANT ALL PRIVILEGES ON DATABASE ${databaseName} TO ${userName};`);
await this.query(`REVOKE CONNECT ON DATABASE ${databaseName} FROM PUBLIC;`);
await this.query(this.pgFormat('GRANT ALL PRIVILEGES ON DATABASE %I TO %I', databaseName, userName));
await this.query(this.pgFormat('REVOKE CONNECT ON DATABASE %I FROM PUBLIC', databaseName));
}

async createUserDb(name, password) {
Expand Down
19 changes: 16 additions & 3 deletions indexer-js-queue-handler/provisioner.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ describe('Provisioner', () => {

expect(pgClient.query.mock.calls).toEqual([
['CREATE DATABASE morgs_near', []],
['CREATE USER morgs_near WITH PASSWORD \'password\';', []],
['GRANT ALL PRIVILEGES ON DATABASE morgs_near TO morgs_near;', []],
['REVOKE CONNECT ON DATABASE morgs_near FROM PUBLIC;', []],
['CREATE USER morgs_near WITH PASSWORD \'password\'', []],
['GRANT ALL PRIVILEGES ON DATABASE morgs_near TO morgs_near', []],
['REVOKE CONNECT ON DATABASE morgs_near FROM PUBLIC', []],
]);
expect(hasuraClient.addDatasource).toBeCalledWith(userName, password, databaseName);
expect(hasuraClient.runSql).toBeCalledWith(databaseName, databaseSchema);
Expand All @@ -84,6 +84,19 @@ describe('Provisioner', () => {
);
});

it('formats user input before executing the query', async () => {
const provisioner = new Provisioner(hasuraClient, pgPool, crypto);

await provisioner.createUserDb('morgs_near UNION SELECT * FROM users --', 'pass; DROP TABLE users;--');

expect(pgClient.query.mock.calls).toEqual([
['CREATE DATABASE "morgs_near UNION SELECT * FROM users --"', []],
["CREATE USER \"morgs_near UNION SELECT * FROM users --\" WITH PASSWORD '\"pass; DROP TABLE users;--\"'", []],
["GRANT ALL PRIVILEGES ON DATABASE \"morgs_near UNION SELECT * FROM users --\" TO \"morgs_near UNION SELECT * FROM users --\"", []],
["REVOKE CONNECT ON DATABASE \"morgs_near UNION SELECT * FROM users --\" FROM PUBLIC", []]
]);
});

it('throws an error when it fails to create a postgres db', async () => {
pgClient.query = jest.fn().mockRejectedValue(error);

Expand Down

0 comments on commit f2c9269

Please sign in to comment.