Last active
August 29, 2015 14:21
-
-
Save fritzy/310deeb28c7fb63eeeb0 to your computer and use it in GitHub Desktop.
Potentially dangerous use of SET ROLE in Postgres with Node.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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 | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
:!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