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 <github@erik.michelson.eu>
This commit is contained in:
Erik Michelson
2025-05-05 18:13:58 +02:00
committed by Philip Molares
parent c449d3a815
commit 637c451486
7 changed files with 18 additions and 25 deletions

View File

@@ -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)
: {

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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",

View File

@@ -3,16 +3,14 @@
## <i class="fa fa-tag"></i> 1.x.x <i class="fa fa-calendar-o"></i> 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
## <i class="fa fa-tag"></i> 1.10.3 <i class="fa fa-calendar-o"></i> 2025-04-09
### Security fixes

View File

@@ -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"