diff --git a/src/routes/profile.js b/src/routes/profile.js index 11b5edb..49048c2 100644 --- a/src/routes/profile.js +++ b/src/routes/profile.js @@ -28,12 +28,11 @@ if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see . */ import express from 'express' -import { param } from 'express-validator' import bodyParserImport from 'body-parser' import { rateLimit } from 'express-rate-limit' import { generateSignatureProfile, utils, generateWKDProfile, generateHKPProfile, generateAutoProfile, generateKeybaseProfile } from '../server/index.js' import { Profile } from 'doipjs' -import { generateProfileTheme, getMetaFromReq } from '../server/utils.js' +import { generateProfileTheme, getMetaFromReq, escapedParam } from '../server/utils.js' import logger from '../log.js' const router = express.Router() @@ -87,7 +86,7 @@ router.post('/sig', router.get('/wkd/:id', profileRateLimiter, - param('id').escape(), + escapedParam('id'), async (req, res) => { const data = await generateWKDProfile(req.params.id) const title = utils.generatePageTitle('profile', data) @@ -103,7 +102,7 @@ router.get('/wkd/:id', router.get('/hkp/:id', profileRateLimiter, - param('id').escape(), + escapedParam('id'), async (req, res) => { const data = await generateHKPProfile(req.params.id) const title = utils.generatePageTitle('profile', data) @@ -119,8 +118,8 @@ router.get('/hkp/:id', router.get('/hkp/:server/:id', profileRateLimiter, - param('server').escape(), - param('id').escape(), + escapedParam('server'), + escapedParam('id'), async (req, res) => { const data = await generateHKPProfile(req.params.id, req.params.server) const title = utils.generatePageTitle('profile', data) @@ -136,8 +135,8 @@ router.get('/hkp/:server/:id', router.get('/keybase/:username/:fingerprint', profileRateLimiter, - param('username').escape(), - param('fingerprint').escape(), + escapedParam('username'), + escapedParam('fingerprint'), async (req, res) => { const data = await generateKeybaseProfile(req.params.username, req.params.fingerprint) const title = utils.generatePageTitle('profile', data) @@ -153,7 +152,7 @@ router.get('/keybase/:username/:fingerprint', router.get('/:id', profileRateLimiter, - param('id').escape(), + escapedParam('id'), async (req, res) => { const data = await generateAutoProfile(req.params.id) const theme = generateProfileTheme(data) diff --git a/src/routes/util.js b/src/routes/util.js index bc5d207..9cc3f3d 100644 --- a/src/routes/util.js +++ b/src/routes/util.js @@ -28,7 +28,7 @@ if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see . */ import express from 'express' -import { getMetaFromReq } from '../server/utils.js' +import { escapedParam, getMetaFromReq } from '../server/utils.js' const router = express.Router() @@ -38,43 +38,55 @@ router.get('/', function (req, res) { router.get('/profile-url', function (req, res) { res.render('util/profile-url', { meta: getMetaFromReq(req) }) }) -router.get('/profile-url/:input', function (req, res) { - res.render('util/profile-url', { input: req.params.input, meta: getMetaFromReq(req) }) -}) +router.get('/profile-url/:input', + escapedParam('input'), + function (req, res) { + res.render('util/profile-url', { input: req.params.input, meta: getMetaFromReq(req) }) + }) router.get('/qr', function (req, res) { res.render('util/qr', { meta: getMetaFromReq(req) }) }) -router.get('/qr/:input', function (req, res) { - res.render('util/qr', { input: req.params.input, meta: getMetaFromReq(req) }) -}) +router.get('/qr/:input', + escapedParam('input'), + function (req, res) { + res.render('util/qr', { input: req.params.input, meta: getMetaFromReq(req) }) + }) router.get('/qrfp', function (req, res) { res.render('util/qrfp', { meta: getMetaFromReq(req) }) }) -router.get('/qrfp/:input', function (req, res) { - res.render('util/qrfp', { input: req.params.input, meta: getMetaFromReq(req) }) -}) +router.get('/qrfp/:input', + escapedParam('input'), + function (req, res) { + res.render('util/qrfp', { input: req.params.input, meta: getMetaFromReq(req) }) + }) router.get('/wkd', function (req, res) { res.render('util/wkd', { meta: getMetaFromReq(req) }) }) -router.get('/wkd/:input', function (req, res) { - res.render('util/wkd', { input: req.params.input, meta: getMetaFromReq(req) }) -}) +router.get('/wkd/:input', + escapedParam('input'), + function (req, res) { + res.render('util/wkd', { input: req.params.input, meta: getMetaFromReq(req) }) + }) router.get('/argon2', function (req, res) { res.render('util/argon2', { meta: getMetaFromReq(req) }) }) -router.get('/argon2/:input', function (req, res) { - res.render('util/argon2', { input: req.params.input, meta: getMetaFromReq(req) }) -}) +router.get('/argon2/:input', + escapedParam('input'), + function (req, res) { + res.render('util/argon2', { input: req.params.input, meta: getMetaFromReq(req) }) + }) router.get('/bcrypt', function (req, res) { res.render('util/bcrypt', { meta: getMetaFromReq(req) }) }) -router.get('/bcrypt/:input', function (req, res) { - res.render('util/bcrypt', { input: req.params.input, meta: getMetaFromReq(req) }) -}) +router.get('/bcrypt/:input', + escapedParam('input'), + function (req, res) { + res.render('util/bcrypt', { input: req.params.input, meta: getMetaFromReq(req) }) + }) export default router diff --git a/src/server/utils.js b/src/server/utils.js index 4c65b8f..0475f5d 100644 --- a/src/server/utils.js +++ b/src/server/utils.js @@ -30,6 +30,7 @@ more information on this, and how to apply and follow the GNU AGPL, see ]+@[^\s@<>]+>)/ + +export function escapedParam(name) { + return param(name).customSanitizer(value => { + return value.split(reEmailLike).map(token => { + if (reEmailLike.test(token)) return token + return escape(token) + }).join('') + }) +} + +// Copied from https://github.com/validatorjs/validator.js/blob/b958bd7d1026a434ad3bf90064d3dcb8b775f1a9/src/lib/escape.js +function escape(input) { + return (input.replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>') + .replace(/\//g, '/') + .replace(/\\/g, '\') + .replace(/`/g, '`')) +}