From 637c451486b53b0441116ce2b6d081db127a0c70 Mon Sep 17 00:00:00 2001 From: Erik Michelson Date: Mon, 5 May 2025 18:13:58 +0200 Subject: [PATCH] fix: use nanoid instead of shortid shortid is deprecated and they recommend nanoid instead. We're not sure if this has to do with possible name collisions or enumerability, but to be sure and on the safe side, we're changing this. nanoid seems quite safe since it uses node's crypto module underneath. Signed-off-by: Erik Michelson --- lib/models/note.js | 10 +++++++--- lib/models/revision.js | 4 ++-- lib/models/temp.js | 4 ++-- lib/web/note/actions.js | 4 ++-- package.json | 2 +- public/docs/release-notes.md | 6 ++---- yarn.lock | 13 ++----------- 7 files changed, 18 insertions(+), 25 deletions(-) diff --git a/lib/models/note.js b/lib/models/note.js index 628eb254..c5f162ce 100644 --- a/lib/models/note.js +++ b/lib/models/note.js @@ -7,7 +7,7 @@ const base64url = require('base64url') const md = require('markdown-it')() const metaMarked = require('@hedgedoc/meta-marked') const cheerio = require('cheerio') -const shortId = require('shortid') +const nanoid = require('nanoid') const Sequelize = require('sequelize') const async = require('async') const moment = require('moment') @@ -37,7 +37,7 @@ module.exports = function (sequelize, DataTypes) { type: DataTypes.STRING, unique: true, allowNull: false, - defaultValue: shortId.generate + defaultValue: () => nanoid.nanoid(10) }, alias: { type: DataTypes.STRING, @@ -297,8 +297,12 @@ module.exports = function (sequelize, DataTypes) { parseNoteIdByShortId: function (_callback) { // try to parse note id by shortId try { - if (shortId.isValid(noteId)) { + // old short ids generated by the `shortid` package could be from 7 to 14 characters long + // new ones generated by the `nanoid` package are always 10 characters long + if (noteId && noteId.length >= 7 && noteId.length <= 14) { Note.findOne({ + // MariaDB and MySQL do case-insensitive comparison by default (unless a collation charset like utf8mb4 is used) + // The binary conversion ensures, case-sensitive comparison. where: utils.isMySQL(sequelize) ? sequelize.where(sequelize.fn('BINARY', sequelize.col('shortid')), noteId) : { diff --git a/lib/models/revision.js b/lib/models/revision.js index 0a3cfa60..2f7399ff 100644 --- a/lib/models/revision.js +++ b/lib/models/revision.js @@ -4,7 +4,7 @@ const Sequelize = require('sequelize') const async = require('async') const moment = require('moment') const childProcess = require('child_process') -const shortId = require('shortid') +const nanoid = require('nanoid') const path = require('path') const Op = Sequelize.Op @@ -44,7 +44,7 @@ function createDmpWorker () { function sendDmpWorker (data, callback) { if (!dmpWorker) dmpWorker = createDmpWorker() - const cacheKey = Date.now() + '_' + shortId.generate() + const cacheKey = Date.now() + '_' + nanoid.nanoid() dmpCallbackCache[cacheKey] = callback data = Object.assign(data, { cacheKey diff --git a/lib/models/temp.js b/lib/models/temp.js index dee6c573..bfc88a3f 100644 --- a/lib/models/temp.js +++ b/lib/models/temp.js @@ -1,13 +1,13 @@ 'use strict' // external modules -const shortId = require('shortid') +const nanoid = require('nanoid') module.exports = function (sequelize, DataTypes) { const Temp = sequelize.define('Temp', { id: { type: DataTypes.STRING, primaryKey: true, - defaultValue: shortId.generate + defaultValue: nanoid.nanoid }, data: { type: DataTypes.TEXT diff --git a/lib/web/note/actions.js b/lib/web/note/actions.js index 3c10887d..61eab0ee 100644 --- a/lib/web/note/actions.js +++ b/lib/web/note/actions.js @@ -2,7 +2,7 @@ const models = require('../../models') const logger = require('../../logger') const config = require('../../config') const errors = require('../../errors') -const shortId = require('shortid') +const nanoid = require('nanoid') const moment = require('moment') const querystring = require('querystring') @@ -36,7 +36,7 @@ exports.createGist = function createGist (req, res, note) { client_id: config.github.clientID, redirect_uri: config.serverURL + '/auth/github/callback/' + models.Note.encodeNoteId(note.id) + '/gist', scope: 'gist', - state: shortId.generate() + state: nanoid.nanoid() } const query = querystring.stringify(data) res.redirect('https://github.com/login/oauth/authorize?' + query) diff --git a/package.json b/package.json index 1d4c0b13..c7083b29 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "moment": "2.30.1", "morgan": "1.10.0", "mysql2": "3.14.0", + "nanoid": "3.3.11", "node-fetch": "2.7.0", "passport": "patch:passport@npm%3A0.7.0#~/.yarn/patches/passport-npm-0.7.0-df02531736.patch", "passport-dropbox-oauth2": "1.1.0", @@ -95,7 +96,6 @@ "sanitize-filename": "1.6.3", "scrypt-kdf": "2.0.1", "sequelize": "5.22.5", - "shortid": "2.2.17", "socket.io": "2.5.1", "sqlite3": "5.1.7", "store": "2.0.12", diff --git a/public/docs/release-notes.md b/public/docs/release-notes.md index abb29bc2..9e46a404 100644 --- a/public/docs/release-notes.md +++ b/public/docs/release-notes.md @@ -3,16 +3,14 @@ ## 1.x.x UNRELEASED ### Enhancements - - Add `enableUploads` (`CMD_ENABLE_UPLOADS`) config option to restrict uploads to `registered` users, `all` users or `none` to completely disable uploads. +- Allow links to protocols such as xmpp, webcal or geo +- Switch from deprecated shortid to nanoid module, with 10 character long aliases in "public" links ### Bugfixes - Ignore the healthcheck endpoint in the "too busy" limiter -### Enhancements -- Allow links to protocols such as xmpp, webcal or geo - ## 1.10.3 2025-04-09 ### Security fixes diff --git a/yarn.lock b/yarn.lock index e44372be..d894317b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1461,6 +1461,7 @@ __metadata: moment: "npm:2.30.1" morgan: "npm:1.10.0" mysql2: "npm:3.14.0" + nanoid: "npm:3.3.11" node-fetch: "npm:2.7.0" optimize-css-assets-webpack-plugin: "npm:6.0.1" passport: "patch:passport@npm%3A0.7.0#~/.yarn/patches/passport-npm-0.7.0-df02531736.patch" @@ -1491,7 +1492,6 @@ __metadata: scrypt-kdf: "npm:2.0.1" select2: "npm:3.5.2-browserify" sequelize: "npm:5.22.5" - shortid: "npm:2.2.17" socket.io: "npm:2.5.1" socket.io-client: "npm:2.5.0" spin.js: "npm:4.1.2" @@ -11233,7 +11233,7 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.8": +"nanoid@npm:3.3.11, nanoid@npm:^3.3.8": version: 3.3.11 resolution: "nanoid@npm:3.3.11" bin: @@ -14963,15 +14963,6 @@ __metadata: languageName: node linkType: hard -"shortid@npm:2.2.17": - version: 2.2.17 - resolution: "shortid@npm:2.2.17" - dependencies: - nanoid: "npm:^3.3.8" - checksum: 10/5c85635e31c08f8c6824b1802a0abb4cd26b39a5c84498dacc91b865f9a860979b010420423e5a4c0abf966aedf197a664a610e813745a6df1497f1376a72350 - languageName: node - linkType: hard - "side-channel-list@npm:^1.0.0": version: 1.0.0 resolution: "side-channel-list@npm:1.0.0"