Skip to content

Instantly share code, notes, and snippets.

@fritzy
Last active August 29, 2015 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fritzy/310deeb28c7fb63eeeb0 to your computer and use it in GitHub Desktop.
Save fritzy/310deeb28c7fb63eeeb0 to your computer and use it in GitHub Desktop.
Potentially dangerous use of SET ROLE in Postgres with Node.js
//POTENTIALLY DANGEROUS
pg.query('SET ROLE fritzy', function (err) {
//this doesn't happen until the event loop calls it after SET ROLE
//you don't know if the role has been changed since then on this connection
//your next query could be ANY role
pg.query('INSERT INTO some_table (...) VALUES (...)', function (err, result) {
// ...
});
});
//If you work around this problem, make sure you're using the same client instance.
//--------------
pg.query('SET ROLE fritzy; INSERT INTO some_table (...) VALUES (...);', function (err) {
//safe, but doesn't work with prepared statemens as this is two queries
});
var async = require('async');
var pg = require('pg');
var client = new pg.Client('postgres://fritzy@localhost/fritzy');
//TEST TO SEE IF ASYNC CALLS TO SET ROLE ARE A PROBLEM
client.connect(function (err) {
var count = 0;
async.whilst(
function () {
return count < 2000;
},
function (wcb) {
//SET a random role from other handled events
var role = 'async' + Math.ceil(Math.random() * 10);
count++;
console.log('Role:', role);
client.query('SET ROLE ' + role, function (err) {
wcb();
});
},
function (err) {
}
);
async.whilst(
function () {
return count < 2000;
},
function (wcb) {
//set a specific role and then do a query using that role
client.query('SET ROLE async11', function (err) {
//you might think current_user is async11 right here... not necessarily true
client.query('SELECT current_user', [], function (err, result) {
var user = result.rows[0].current_user;
console.log('actual role:', user);
if (user !== 'async11') {
//it doesn't take long before this blows up
throw new Error('Not right role! User: ' + user);
}
wcb();
});
});
},
function (err) {
client.end();
}
);
});
:!node test_async_role.js
Role: async7
Role: async1
Role: async2
actual role: async1
/Users/fritzy/projects/test/dbtest/index.js:39
throw new Error('Not right role! User: ' + user);
^
Error: Not right role! User: async1
at null.callback (/Users/fritzy/projects/test/dbtest/index.js:39:31)
at Query.handleReadyForQuery (/Users/fritzy/projects/test/dbtest/node_modules/pg/lib/query.js:80:10)
at null.<anonymous> (/Users/fritzy/projects/test/dbtest/node_modules/pg/lib/client.js:158:19)
at emitOne (events.js:82:20)
at emit (events.js:169:7)
at Socket.<anonymous> (/Users/fritzy/projects/test/dbtest/node_modules/pg/lib/connection.js:109:12)
at emitOne (events.js:77:13)
at Socket.emit (events.js:169:7)
at readableAddChunk (_stream_readable.js:145:16)
at Socket.Readable.push (_stream_readable.js:109:10)
shell returned 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment