Skip to content
This repository was archived by the owner on Dec 10, 2022. It is now read-only.

Commit 6fa326b

Browse files
committed
Eliminate potential SQL injection from database queries
The TODO markers indicating the possibility of SQL injection issues were used to guide this implementation. Fixed by applying parameterized queries. Found a unitest issue that was masked by the use of concatenation in SQL and fixed the unit tests to match the runtime code execution.
1 parent 7fd965f commit 6fa326b

File tree

2 files changed

+21
-19
lines changed

2 files changed

+21
-19
lines changed

src/points.js

+13-9
Original file line numberDiff line numberDiff line change
@@ -73,17 +73,21 @@ const updateScore = async( item, operation ) => {
7373
' );
7474

7575
// Atomically record the action.
76-
// TODO: Fix potential SQL injection issues here, even though we know the input should be safe.
77-
await dbClient.query( '\
78-
INSERT INTO ' + scoresTableName + ' VALUES (\'' + item + '\', ' + operation + '1) \
79-
ON CONFLICT (item) DO UPDATE SET score = ' + scoresTableName + '.score ' + operation + ' 1; \
80-
' );
76+
const insertOrUpdateScore = {
77+
text: '\
78+
INSERT INTO ' + scoresTableName + ' VALUES ($1, $2) \
79+
ON CONFLICT (item) DO UPDATE SET score = ' + scoresTableName + '.score ' + operation + ' 1; \
80+
',
81+
values: [ item, operation + '1' ]
82+
};
83+
await dbClient.query( insertOrUpdateScore );
8184

8285
// Get the new value.
83-
// TODO: Fix potential SQL injection issues here, even though we know the input should be safe.
84-
const dbSelect = await dbClient.query( '\
85-
SELECT score FROM ' + scoresTableName + ' WHERE item = \'' + item + '\'; \
86-
' );
86+
const getCurrentScore = {
87+
text: 'SELECT score FROM ' + scoresTableName + ' WHERE item = $1;',
88+
values: [ item ]
89+
};
90+
const dbSelect = await dbClient.query( getCurrentScore );
8791

8892
await dbClient.release();
8993
const score = dbSelect.rows[0].score;

tests/integration-tests.js

+8-10
Original file line numberDiff line numberDiff line change
@@ -214,11 +214,12 @@ describe( 'The database', () => {
214214

215215
it( 'creates the ' + config.scoresTableName + ' table on the first request', async() => {
216216
expect.hasAssertions();
217-
await points.updateScore( defaultItem, '++' );
217+
const newScore = await points.updateScore( defaultItem, '+' );
218218
const dbClient = await postgres.connect();
219219
const query = await dbClient.query( tableExistsQuery );
220220
await dbClient.release();
221221
expect( query.rows[0].exists ).toBeTrue();
222+
expect( newScore ).toBe( 1 );
222223
});
223224

224225
it( 'also creates the case-insensitive extension on the first request', async() => {
@@ -229,14 +230,11 @@ describe( 'The database', () => {
229230
expect( query.rowCount ).toBe( 1 );
230231
});
231232

232-
/* eslint-disable jest/expect-expect */
233-
// TODO: This test really should have an assertion, but I can't figure out how to catch the error
234-
// properly... it's possible that updateScore needs rewriting to catch properly. In the
235-
// meantime, this test *does* actually work like expected.
236233
it( 'does not cause any errors on a second request when everything already exists', async() => {
237-
await points.updateScore( defaultItem, '++' );
234+
expect.hasAssertions();
235+
const newScore = await points.updateScore( defaultItem, '+' );
236+
expect( newScore ).toBe( 2 );
238237
});
239-
/* eslint-enable jest/expect-expect */
240238

241239
it( 'returns a list of top scores in the correct order', async() => {
242240
expect.hasAssertions();
@@ -253,9 +251,9 @@ describe( 'The database', () => {
253251
];
254252

255253
// Give us a few additional scores so we can check the order works.
256-
await points.updateScore( defaultUser, '++' );
257-
await points.updateScore( defaultUser, '++' );
258-
await points.updateScore( defaultUser, '++' );
254+
await points.updateScore( defaultUser, '+' );
255+
await points.updateScore( defaultUser, '+' );
256+
await points.updateScore( defaultUser, '+' );
259257

260258
const topScores = await points.retrieveTopScores();
261259
expect( topScores ).toEqual( expectedScores );

0 commit comments

Comments
 (0)