upgrade otplib to v13.4.1 #7702
Signed-off-by: si458 <simonsmith5521@gmail.com>
si458 committed
Jun 9, 2026 at 11:32 UTC
b42bedfcaac70324656b0a0e00a8fd0ee76a7ff5
9 files changed
+105
-67
dependencies.txt
+1
-1
@@ -10,7 +10,7 @@
10
"minimist": "1.2.8",
11
"multiparty": "4.3.0",
12
"node-forge": "1.4.0",
13
- "otplib": "12.0.1",
13
+ "otplib": "13.4.1",
14
"ua-client-hints-js": "0.1.2",
15
"ua-parser-js": "1.0.40",
16
"ws": "8.21.0",
docker/Dockerfile
+1
-1
@@ -147,7 +147,7 @@ RUN case "$PREINSTALL_LIBS" in \
147
true|yes|TRUE|YES) \
148
cd meshcentral && \
149
echo -e "----------\nPREINSTALLING LIBRARIES...\n----------"; \
150
- npm install ssh2@1.17.0 nodemailer@6.10.1 image-size@2.0.2 wildleek@2.0.0 otplib@12.0.1 yub@0.11.1;; \
150
+ npm install ssh2@1.17.0 nodemailer@6.10.1 image-size@2.0.2 wildleek@2.0.0 yub@0.11.1;; \
151
false|no|FALSE|NO) \
152
echo "Not pre-installing libraries.";; \
153
*) \
docker/Dockerfile-debian
+1
-1
@@ -183,7 +183,7 @@ RUN case "$PREINSTALL_LIBS" in \
183
true|yes|TRUE|YES) \
184
cd meshcentral && \
185
echo -e "----------\nPREINSTALLING LIBRARIES...\n----------"; \
186
- npm install ssh2@1.17.0 nodemailer@6.10.1 image-size@2.0.2 wildleek@2.0.0 otplib@12.0.1 yub@0.11.1;; \
186
+ npm install ssh2@1.17.0 nodemailer@6.10.1 image-size@2.0.2 wildleek@2.0.0 yub@0.11.1;; \
187
false|no|FALSE|NO) \
188
echo "Not pre-installing libraries.";; \
189
*) \
meshcentral.js
+1
-1
@@ -4397,7 +4397,7 @@ function mainStart() {
4397
if (config.settings.no2factorauth !== true) {
4398
// Setup YubiKey OTP if configured
4399
if (yubikey == true) { modules.push('yub@0.11.1'); } // Add YubiKey OTP support (replaced yubikeyotp due to form-data issues)
4400
- if (allsspi == false) { modules.push('otplib@12.0.1'); } // Google Authenticator support (v10 supports older NodeJS versions).
4400
+ if (allsspi == false) { modules.push('otplib@13.4.1'); } // Google Authenticator support (v10 supports older NodeJS versions).
4401
}
4402
4403
// Desktop multiplexor support
meshuser.js
+11
-4
@@ -3763,7 +3763,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
3763
var otplib = null;
3764
try { otplib = require('otplib'); } catch (ex) { }
3765
if (otplib == null) { ws.send(JSON.stringify({ action: 'otpauth-request', err: 6 })); return; }
3766
- const secret = otplib.authenticator.generateSecret(); // TODO: Check the random source of this value.
3766
+ const secret = otplib.generateSecret(); // TODO: Check the random source of this value.
3767
3768
var domainName = parent.certificates.CommonName;
3769
if (domain.dns != null) {
@@ -3771,7 +3771,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
3771
} else if (domain.dns == null && domain.id != '') {
3772
domainName += "/" + domain.id;
3773
}
3774
- ws.send(JSON.stringify({ action: 'otpauth-request', secret: secret, url: otplib.authenticator.keyuri(user.name, domainName, secret) }));
3774
+ ws.send(JSON.stringify({ action: 'otpauth-request', secret: secret, url: otplib.generateURI({ issuer: domainName, label: user.name, secret: secret }) }));
3775
}
3776
break;
3777
}
@@ -3795,8 +3795,15 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
3795
var otplib = null;
3796
try { otplib = require('otplib'); } catch (ex) { }
3797
if (otplib == null) { break; }
3798
- otplib.authenticator.options = { window: 2 }; // Set +/- 1 minute window
3799
- if (otplib.authenticator.check(command.token, command.secret) === true) {
3798
+ const verified = require('otplib').verifySync({
3799
+ epochTolerance: 60,
3800
+ token: command.token,
3801
+ secret: command.secret,
3802
+ guardrails: otplib.createGuardrails({
3803
+ MIN_SECRET_BYTES: 10, // https://github.com/yeojz/otplib/issues/671#issuecomment-4368647105
3804
+ })
3805
+ });
3806
+ if (verified.valid === true) {
3807
// Token is valid, activate 2-step login on this account.
3808
user.otpsecret = command.secret;
3809
parent.db.SetUser(user);
package-lock.json
+73
-51
@@ -21,7 +21,7 @@
21
"minimist": "1.2.8",
22
"multiparty": "4.3.0",
23
"node-forge": "1.4.0",
24
- "otplib": "12.0.1",
24
+ "otplib": "13.4.1",
25
"ua-client-hints-js": "0.1.2",
26
"ua-parser-js": "1.0.40",
27
"ws": "8.21.0",
@@ -51,54 +51,72 @@
51
"node": ">=12"
52
}
53
},
54
+ "node_modules/@noble/hashes": {
55
+ "version": "2.2.0",
56
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.2.0.tgz",
57
+ "integrity": "sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg==",
58
+ "license": "MIT",
59
+ "engines": {
60
+ "node": ">= 20.19.0"
61
+ },
62
+ "funding": {
63
+ "url": "https://paulmillr.com/funding/"
64
+ }
65
+ },
66
"node_modules/@otplib/core": {
55
- "version": "12.0.1",
56
- "resolved": "https://registry.npmjs.org/@otplib/core/-/core-12.0.1.tgz",
57
- "integrity": "sha512-4sGntwbA/AC+SbPhbsziRiD+jNDdIzsZ3JUyfZwjtKyc/wufl1pnSIaG4Uqx8ymPagujub0o92kgBnB89cuAMA==",
67
+ "version": "13.4.1",
68
+ "resolved": "https://registry.npmjs.org/@otplib/core/-/core-13.4.1.tgz",
69
+ "integrity": "sha512-KIXgK1hNtWJEBMTastbe1bpmuais+3f+ATeO8TkMs2rNkfGO1FbQy8+/UWVEu3TR/iTJerU0idkPudaPmLP2BA==",
70
"license": "MIT"
71
},
60
- "node_modules/@otplib/plugin-crypto": {
61
- "version": "12.0.1",
62
- "resolved": "https://registry.npmjs.org/@otplib/plugin-crypto/-/plugin-crypto-12.0.1.tgz",
63
- "integrity": "sha512-qPuhN3QrT7ZZLcLCyKOSNhuijUi9G5guMRVrxq63r9YNOxxQjPm59gVxLM+7xGnHnM6cimY57tuKsjK7y9LM1g==",
64
- "deprecated": "Please upgrade to v13 of otplib. Refer to otplib docs for migration paths",
72
+ "node_modules/@otplib/hotp": {
73
+ "version": "13.4.1",
74
+ "resolved": "https://registry.npmjs.org/@otplib/hotp/-/hotp-13.4.1.tgz",
75
+ "integrity": "sha512-g9q04SwpG5ZtMnVkUcgcoAlwCH4YLROZN1qhyBwgkBzqYYVSYhpP6gSGaxGHwePLt1c+e6NqDlgIZN+e1/XPuA==",
76
"license": "MIT",
77
"dependencies": {
67
- "@otplib/core": "^12.0.1"
78
+ "@otplib/core": "13.4.1",
79
+ "@otplib/uri": "13.4.1"
80
}
81
},
70
- "node_modules/@otplib/plugin-thirty-two": {
71
- "version": "12.0.1",
72
- "resolved": "https://registry.npmjs.org/@otplib/plugin-thirty-two/-/plugin-thirty-two-12.0.1.tgz",
73
- "integrity": "sha512-MtT+uqRso909UkbrrYpJ6XFjj9D+x2Py7KjTO9JDPhL0bJUYVu5kFP4TFZW4NFAywrAtFRxOVY261u0qwb93gA==",
74
- "deprecated": "Please upgrade to v13 of otplib. Refer to otplib docs for migration paths",
82
+ "node_modules/@otplib/plugin-base32-scure": {
83
+ "version": "13.4.1",
84
+ "resolved": "https://registry.npmjs.org/@otplib/plugin-base32-scure/-/plugin-base32-scure-13.4.1.tgz",
85
+ "integrity": "sha512-Fs/r5qisC05SRhT6xWXaypB6PVC0vgWf6zztmi0J5RnQ09OJiPDWCJFH6cDm6ANsrdvB9di7X+Jb7L13BoEbUA==",
86
"license": "MIT",
87
"dependencies": {
77
- "@otplib/core": "^12.0.1",
78
- "thirty-two": "^1.0.2"
88
+ "@otplib/core": "13.4.1",
89
+ "@scure/base": "^2.2.0"
90
}
91
},
81
- "node_modules/@otplib/preset-default": {
82
- "version": "12.0.1",
83
- "resolved": "https://registry.npmjs.org/@otplib/preset-default/-/preset-default-12.0.1.tgz",
84
- "integrity": "sha512-xf1v9oOJRyXfluBhMdpOkr+bsE+Irt+0D5uHtvg6x1eosfmHCsCC6ej/m7FXiWqdo0+ZUI6xSKDhJwc8yfiOPQ==",
85
- "deprecated": "Please upgrade to v13 of otplib. Refer to otplib docs for migration paths",
92
+ "node_modules/@otplib/plugin-crypto-noble": {
93
+ "version": "13.4.1",
94
+ "resolved": "https://registry.npmjs.org/@otplib/plugin-crypto-noble/-/plugin-crypto-noble-13.4.1.tgz",
95
+ "integrity": "sha512-PJfVW8/1hdS6CfxLheKPZSLTwDq4TijZbN4yRjxlv0ODdzmxpM+wGwWr1JXMdy0xJPxLziydQD5gdVqrR4/gAg==",
96
"license": "MIT",
97
"dependencies": {
88
- "@otplib/core": "^12.0.1",
89
- "@otplib/plugin-crypto": "^12.0.1",
90
- "@otplib/plugin-thirty-two": "^12.0.1"
98
+ "@noble/hashes": "^2.2.0",
99
+ "@otplib/core": "13.4.1"
100
}
101
},
93
- "node_modules/@otplib/preset-v11": {
94
- "version": "12.0.1",
95
- "resolved": "https://registry.npmjs.org/@otplib/preset-v11/-/preset-v11-12.0.1.tgz",
96
- "integrity": "sha512-9hSetMI7ECqbFiKICrNa4w70deTUfArtwXykPUvSHWOdzOlfa9ajglu7mNCntlvxycTiOAXkQGwjQCzzDEMRMg==",
102
+ "node_modules/@otplib/totp": {
103
+ "version": "13.4.1",
104
+ "resolved": "https://registry.npmjs.org/@otplib/totp/-/totp-13.4.1.tgz",
105
+ "integrity": "sha512-QOkBVPrf6AM4qZaReZPSk9/I8ATVdZpIISJz115MqeVtcrbcr5llPZ0J7804tpnjnp1vCRkI5Qjd47HhgVteBQ==",
106
"license": "MIT",
107
"dependencies": {
99
- "@otplib/core": "^12.0.1",
100
- "@otplib/plugin-crypto": "^12.0.1",
101
- "@otplib/plugin-thirty-two": "^12.0.1"
108
+ "@otplib/core": "13.4.1",
109
+ "@otplib/hotp": "13.4.1",
110
+ "@otplib/uri": "13.4.1"
111
+ }
112
+ },
113
+ "node_modules/@otplib/uri": {
114
+ "version": "13.4.1",
115
+ "resolved": "https://registry.npmjs.org/@otplib/uri/-/uri-13.4.1.tgz",
116
+ "integrity": "sha512-xaIm7bvICMhoB2rZIR5luiaMdssWR5nY5nXnR1fdezUgZuEO58D6zrGzLp7pQuBmlpmL0HagnscDQFoskp9yiA==",
117
+ "license": "MIT",
118
+ "dependencies": {
119
+ "@otplib/core": "13.4.1"
120
}
121
},
122
"node_modules/@pkgjs/parseargs": {
@@ -111,6 +129,15 @@
129
"node": ">=14"
130
}
131
},
132
+ "node_modules/@scure/base": {
133
+ "version": "2.2.0",
134
+ "resolved": "https://registry.npmjs.org/@scure/base/-/base-2.2.0.tgz",
135
+ "integrity": "sha512-b8XEupJibegiXV+tDUseI8oLQc8ei3d/4Jkb2RpbHh3MfE054ov3uIz2dhFkB3FI8iwYkEh0gGCApkrYggkPNg==",
136
+ "license": "MIT",
137
+ "funding": {
138
+ "url": "https://paulmillr.com/funding/"
139
+ }
140
+ },
141
"node_modules/@seald-io/binary-search-tree": {
142
"version": "1.0.3",
143
"resolved": "https://registry.npmjs.org/@seald-io/binary-search-tree/-/binary-search-tree-1.0.3.tgz",
@@ -1736,14 +1763,17 @@
1763
}
1764
},
1765
"node_modules/otplib": {
1739
- "version": "12.0.1",
1740
- "resolved": "https://registry.npmjs.org/otplib/-/otplib-12.0.1.tgz",
1741
- "integrity": "sha512-xDGvUOQjop7RDgxTQ+o4pOol0/3xSZzawTiPKRrHnQWAy0WjhNs/5HdIDJCrqC4MBynmjXgULc6YfioaxZeFgg==",
1766
+ "version": "13.4.1",
1767
+ "resolved": "https://registry.npmjs.org/otplib/-/otplib-13.4.1.tgz",
1768
+ "integrity": "sha512-o5CxfDw6bh7hoDv0NUUIcc0RqzJ9ipfUrzeKheKJ+vs4rXZnDlA9n4a/7R1cDjpmLjKLix4BgNVRmoDkm5rLSQ==",
1769
"license": "MIT",
1770
"dependencies": {
1744
- "@otplib/core": "^12.0.1",
1745
- "@otplib/preset-default": "^12.0.1",
1746
- "@otplib/preset-v11": "^12.0.1"
1771
+ "@otplib/core": "13.4.1",
1772
+ "@otplib/hotp": "13.4.1",
1773
+ "@otplib/plugin-base32-scure": "13.4.1",
1774
+ "@otplib/plugin-crypto-noble": "13.4.1",
1775
+ "@otplib/totp": "13.4.1",
1776
+ "@otplib/uri": "13.4.1"
1777
}
1778
},
1779
"node_modules/package-json-from-dist": {
@@ -2053,14 +2083,14 @@
2083
}
2084
},
2085
"node_modules/side-channel": {
2056
- "version": "1.1.0",
2057
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
2058
- "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
2086
+ "version": "1.1.1",
2087
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz",
2088
+ "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==",
2089
"license": "MIT",
2090
"dependencies": {
2091
"es-errors": "^1.3.0",
2062
- "object-inspect": "^1.13.3",
2063
- "side-channel-list": "^1.0.0",
2092
+ "object-inspect": "^1.13.4",
2093
+ "side-channel-list": "^1.0.1",
2094
"side-channel-map": "^1.0.1",
2095
"side-channel-weakmap": "^1.0.2"
2096
},
@@ -2300,14 +2330,6 @@
2330
"b4a": "^1.6.4"
2331
}
2332
},
2303
- "node_modules/thirty-two": {
2304
- "version": "1.0.2",
2305
- "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz",
2306
- "integrity": "sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA==",
2307
- "engines": {
2308
- "node": ">=0.2.6"
2309
- }
2310
- },
2333
"node_modules/toidentifier": {
2334
"version": "1.0.1",
2335
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
package.json
+1
-1
@@ -49,7 +49,7 @@
49
"minimist": "1.2.8",
50
"multiparty": "4.3.0",
51
"node-forge": "1.4.0",
52
- "otplib": "12.0.1",
52
+ "otplib": "13.4.1",
53
"ua-client-hints-js": "0.1.2",
54
"ua-parser-js": "1.0.40",
55
"ws": "8.21.0",
reinstall-modules.bat
+1
-1
@@ -1 +1 @@
1
-npm install archiver authdog body-parser compression connect-redis cookie-session express express-handlebars express-ws ipcheck minimist mongojs multiparty nedb node-forge otplib ws xmldom yauzl yubikeyotp
\ No newline at end of file
1
+npm install archiver authdog compression connect-redis cookie-session express express-handlebars express-ws ipcheck minimist mongojs multiparty nedb node-forge otplib ws xmldom yauzl yubikeyotp
\ No newline at end of file
webserver.js
+15
-6
@@ -1110,12 +1110,21 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
1110
}
1111
1112
// Check Google Authenticator
1113
- const otplib = require('otplib')
1114
- otplib.authenticator.options = { window: 2 }; // Set +/- 1 minute window
1115
- if (user.otpsecret && (typeof (token) == 'string') && (token.length == 6) && (otplib.authenticator.check(token, user.otpsecret) == true)) {
1116
- parent.debug('web', 'checkUserOneTimePassword: success (authenticator).');
1117
- func(true, { twoFactorType: 'otp' });
1118
- return;
1113
+ if (user.otpsecret && (typeof (token) == 'string') && (token.length == 6)){
1114
+ const otplib = require('otplib');
1115
+ const verified = otplib.verifySync({
1116
+ epochTolerance: 60,
1117
+ token: token,
1118
+ secret: user.otpsecret,
1119
+ guardrails: otplib.createGuardrails({
1120
+ MIN_SECRET_BYTES: 10, // https://github.com/yeojz/otplib/issues/671#issuecomment-4368647105
1121
+ })
1122
+ });
1123
+ if (verified.valid === true) {
1124
+ parent.debug('web', 'checkUserOneTimePassword: success (authenticator).');
1125
+ func(true, { twoFactorType: 'otp' });
1126
+ return;
1127
+ }
1128
};
1129
1130
// Check written down keys