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, '`'))
+}