diff --git a/src/controllers/mods.js b/src/controllers/mods.js index 4976dd9e82..c0abc18fe8 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -1,6 +1,7 @@ 'use strict'; const _ = require('lodash'); +const validator = require('validator'); const user = require('../user'); const groups = require('../groups'); @@ -43,9 +44,9 @@ modsController.flags.list = async function (req, res) { filters = filters.reduce((memo, cur) => { if (req.query.hasOwnProperty(cur)) { if (typeof req.query[cur] === 'string' && req.query[cur].trim() !== '') { - memo[cur] = req.query[cur].trim(); + memo[cur] = validator.escape(String(req.query[cur].trim())); } else if (Array.isArray(req.query[cur]) && req.query[cur].length) { - memo[cur] = req.query[cur]; + memo[cur] = req.query[cur].map(item => validator.escape(String(item).trim())); } } diff --git a/src/database/postgres/sorted.js b/src/database/postgres/sorted.js index 916425e0c1..9f59224497 100644 --- a/src/database/postgres/sorted.js +++ b/src/database/postgres/sorted.js @@ -707,9 +707,9 @@ SELECT z."value", ON o."_key" = z."_key" AND o."type" = z."type" WHERE o."_key" = $1::TEXT - AND z."value" LIKE '${match}' + AND z."value" LIKE $3 LIMIT $2::INTEGER`, - values: [params.key, params.limit], + values: [params.key, params.limit, match], }); if (!params.withScores) { return res.rows.map(r => r.value); diff --git a/src/middleware/activitypub.js b/src/middleware/activitypub.js index 490715dbcb..b38caa552a 100644 --- a/src/middleware/activitypub.js +++ b/src/middleware/activitypub.js @@ -33,10 +33,12 @@ middleware.verify = async function (req, res, next) { return next(); } - const verified = await activitypub.verify(req); - if (!verified && req.method === 'POST') { - activitypub.helpers.log('[middleware/activitypub] HTTP signature verification failed.'); - return res.sendStatus(400); + if (req.method === 'POST') { + const verified = await activitypub.verify(req); + if (!verified) { + activitypub.helpers.log('[middleware/activitypub] HTTP signature verification failed.'); + return res.sendStatus(400); + } } // Set calling user diff --git a/src/routes/activitypub.js b/src/routes/activitypub.js index b6a516b481..760287e102 100644 --- a/src/routes/activitypub.js +++ b/src/routes/activitypub.js @@ -25,28 +25,28 @@ module.exports = function (app, middleware, controllers) { middleware.activitypub.normalize, ]; - app.get('/actor', middlewares, controllers.activitypub.actors.application); - app.post('/inbox', [...middlewares, ...inboxMiddlewares], controllers.activitypub.postInbox); + app.get('/actor', middlewares, helpers.tryRoute(controllers.activitypub.actors.application)); + app.post('/inbox', [...middlewares, ...inboxMiddlewares], helpers.tryRoute(controllers.activitypub.postInbox)); - app.get('/uid/:uid', [...middlewares, middleware.assert.user], controllers.activitypub.actors.user); - app.get('/user/:userslug', [...middlewares, middleware.exposeUid, middleware.assert.user], controllers.activitypub.actors.userBySlug); - app.get('/uid/:uid/inbox', [...middlewares, middleware.assert.user], controllers.activitypub.getInbox); - app.post('/uid/:uid/inbox', [...middlewares, middleware.assert.user, ...inboxMiddlewares], controllers.activitypub.postInbox); - app.get('/uid/:uid/outbox', [...middlewares, middleware.assert.user], controllers.activitypub.getOutbox); - app.post('/uid/:uid/outbox', [...middlewares, middleware.assert.user], controllers.activitypub.postOutbox); - app.get('/uid/:uid/following', [...middlewares, middleware.assert.user], controllers.activitypub.getFollowing); - app.get('/uid/:uid/followers', [...middlewares, middleware.assert.user], controllers.activitypub.getFollowers); + app.get('/uid/:uid', [...middlewares, middleware.assert.user], helpers.tryRoute(controllers.activitypub.actors.user)); + app.get('/user/:userslug', [...middlewares, middleware.exposeUid, middleware.assert.user], helpers.tryRoute(controllers.activitypub.actors.userBySlug)); + app.get('/uid/:uid/inbox', [...middlewares, middleware.assert.user], helpers.tryRoute(controllers.activitypub.getInbox)); + app.post('/uid/:uid/inbox', [...middlewares, middleware.assert.user, ...inboxMiddlewares], helpers.tryRoute(controllers.activitypub.postInbox)); + app.get('/uid/:uid/outbox', [...middlewares, middleware.assert.user], helpers.tryRoute(controllers.activitypub.getOutbox)); + app.post('/uid/:uid/outbox', [...middlewares, middleware.assert.user], helpers.tryRoute(controllers.activitypub.postOutbox)); + app.get('/uid/:uid/following', [...middlewares, middleware.assert.user], helpers.tryRoute(controllers.activitypub.getFollowing)); + app.get('/uid/:uid/followers', [...middlewares, middleware.assert.user], helpers.tryRoute(controllers.activitypub.getFollowers)); - app.get('/post/:pid', [...middlewares, middleware.assert.post], controllers.activitypub.actors.note); - app.get('/post/:pid/replies', [...middlewares, middleware.assert.post], controllers.activitypub.actors.replies); + app.get('/post/:pid', [...middlewares, middleware.assert.post], helpers.tryRoute(controllers.activitypub.actors.note)); + app.get('/post/:pid/replies', [...middlewares, middleware.assert.post], helpers.tryRoute(controllers.activitypub.actors.replies)); - app.get('/topic/:tid/:slug?', [...middlewares, middleware.assert.topic], controllers.activitypub.actors.topic); + app.get('/topic/:tid/:slug?', [...middlewares, middleware.assert.topic], helpers.tryRoute(controllers.activitypub.actors.topic)); - app.get('/category/:cid/inbox', [...middlewares, middleware.assert.category], controllers.activitypub.getInbox); - app.post('/category/:cid/inbox', [...inboxMiddlewares, middleware.assert.category, ...inboxMiddlewares], controllers.activitypub.postInbox); - app.get('/category/:cid/outbox', [...middlewares, middleware.assert.category], controllers.activitypub.getCategoryOutbox); - app.post('/category/:cid/outbox', [...middlewares, middleware.assert.category], controllers.activitypub.postOutbox); - app.get('/category/:cid/:slug?', [...middlewares, middleware.assert.category], controllers.activitypub.actors.category); + app.get('/category/:cid/inbox', [...middlewares, middleware.assert.category], helpers.tryRoute(controllers.activitypub.getInbox)); + app.post('/category/:cid/inbox', [...inboxMiddlewares, middleware.assert.category, ...inboxMiddlewares], helpers.tryRoute(controllers.activitypub).postInbox); + app.get('/category/:cid/outbox', [...middlewares, middleware.assert.category], helpers.tryRoute(controllers.activitypub.getCategoryOutbox)); + app.post('/category/:cid/outbox', [...middlewares, middleware.assert.category], helpers.tryRoute(controllers.activitypub.postOutbox)); + app.get('/category/:cid/:slug?', [...middlewares, middleware.assert.category], helpers.tryRoute(controllers.activitypub.actors.category)); - app.get('/message/:mid', [...middlewares, middleware.assert.message], controllers.activitypub.actors.message); + app.get('/message/:mid', [...middlewares, middleware.assert.message], helpers.tryRoute(controllers.activitypub.actors.message)); }; diff --git a/src/socket.io/admin/user.js b/src/socket.io/admin/user.js index 9367ff9c53..698f854597 100644 --- a/src/socket.io/admin/user.js +++ b/src/socket.io/admin/user.js @@ -2,6 +2,8 @@ const async = require('async'); const winston = require('winston'); +const nconf = require('nconf'); +const pubsub = require('../../pubsub'); const db = require('../../database'); const groups = require('../../groups'); @@ -129,8 +131,15 @@ User.forcePasswordReset = async function (socket, uids) { uids.forEach(uid => sockets.in(`uid_${uid}`).emit('event:logout')); }; +pubsub.on('admin.user.restartJobs', () => { + if (nconf.get('runJobs')) { + winston.verbose('[user/jobs] Restarting jobs...'); + user.startJobs(); + } +}); + User.restartJobs = async function () { - user.startJobs(); + pubsub.publish('admin.user.restartJobs', {}); }; User.loadGroups = async function (socket, uids) { diff --git a/test/database/sorted.js b/test/database/sorted.js index 33d3e4c4b5..b98d969730 100644 --- a/test/database/sorted.js +++ b/test/database/sorted.js @@ -78,6 +78,21 @@ describe('Sorted Set methods', () => { assert(data.includes('ddb')); assert(data.includes('adb')); }); + + it('should not error with invalid input', async () => { + const query = `-3217' +OR 1251=CAST((CHR(113)||CHR(98)||CHR(118)||CHR(98)||CHR(113))||(SELECT +(CASE WHEN (1251=1251) THEN 1 ELSE 0 +END))::text||(CHR(113)||CHR(113)||CHR(118)||CHR(98)||CHR(113)) AS +NUMERIC)-- WsPn&query[cid]=-1&parentCid=0&selectedCids[]=-1&privilege=topics:read&states[]=watching&states[]=tracking&states[]=notwatching&showLinks=`; + const match = `*${query.toLowerCase()}*`; + const data = await db.getSortedSetScan({ + key: 'categories:name', + match: match, + limit: 500, + }); + assert.strictEqual(data.length, 0); + }); }); describe('sortedSetAdd()', () => { diff --git a/test/flags.js b/test/flags.js index ee150a10c4..aad4802e7a 100644 --- a/test/flags.js +++ b/test/flags.js @@ -928,6 +928,11 @@ describe('Flags', () => { assert.strictEqual(flagData.reports[0].value, '"<script>alert('ok');</script>'); }); + it('should escape filters', async () => { + const { body } = await request.get(`${nconf.get('url')}/api/flags?quick="`, { jar }); + assert.strictEqual(body.filters.quick, '"<script>alert('foo');</script>'); + }); + it('should not allow flagging post in private category', async () => { const category = await Categories.create({ name: 'private category' }); @@ -1185,5 +1190,7 @@ describe('Flags', () => { } }); }); + + }); });