Skip to content

Commit 47b367d

Browse files
authored
Merge pull request #5276 from NginxProxyManager/develop
v2.13.7
2 parents f3efaae + d19f5c1 commit 47b367d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+5165
-1754
lines changed

.github/dependabot.yml

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "npm"
4+
directory: "/backend"
5+
schedule:
6+
interval: "weekly"
7+
groups:
8+
dev-patch-updates:
9+
dependency-type: "development"
10+
update-types:
11+
- "patch"
12+
dev-minor-updates:
13+
dependency-type: "development"
14+
update-types:
15+
- "minor"
16+
prod-patch-updates:
17+
dependency-type: "production"
18+
update-types:
19+
- "patch"
20+
prod-minor-updates:
21+
dependency-type: "production"
22+
update-types:
23+
- "minor"
24+
25+
- package-ecosystem: "npm"
26+
directory: "/frontend"
27+
schedule:
28+
interval: "weekly"
29+
groups:
30+
dev-patch-updates:
31+
dependency-type: "development"
32+
update-types:
33+
- "patch"
34+
dev-minor-updates:
35+
dependency-type: "development"
36+
update-types:
37+
- "minor"
38+
prod-patch-updates:
39+
dependency-type: "production"
40+
update-types:
41+
- "patch"
42+
prod-minor-updates:
43+
dependency-type: "production"
44+
update-types:
45+
- "minor"
46+
47+
- package-ecosystem: "npm"
48+
directory: "/docs"
49+
schedule:
50+
interval: "weekly"
51+
groups:
52+
dev-patch-updates:
53+
dependency-type: "development"
54+
update-types:
55+
- "patch"
56+
dev-minor-updates:
57+
dependency-type: "development"
58+
update-types:
59+
- "minor"
60+
prod-patch-updates:
61+
dependency-type: "production"
62+
update-types:
63+
- "patch"
64+
prod-minor-updates:
65+
dependency-type: "production"
66+
update-types:
67+
- "minor"
68+
69+
- package-ecosystem: "npm"
70+
directory: "/test"
71+
schedule:
72+
interval: "weekly"
73+
groups:
74+
dev-patch-updates:
75+
dependency-type: "development"
76+
update-types:
77+
- "patch"
78+
dev-minor-updates:
79+
dependency-type: "development"
80+
update-types:
81+
- "minor"
82+
prod-patch-updates:
83+
dependency-type: "production"
84+
update-types:
85+
- "patch"
86+
prod-minor-updates:
87+
dependency-type: "production"
88+
update-types:
89+
- "minor"
90+
91+
- package-ecosystem: "docker"
92+
directory: "/docker"
93+
schedule:
94+
interval: "weekly"
95+
groups:
96+
updates:
97+
update-types:
98+
- "patch"
99+
- "minor"
100+
101+
- package-ecosystem: "github-actions"
102+
directory: "/"
103+
schedule:
104+
interval: "weekly"

.github/workflows/stale.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
stale:
99
runs-on: ubuntu-latest
1010
steps:
11-
- uses: actions/stale@v9
11+
- uses: actions/stale@v10
1212
with:
1313
stale-issue-label: 'stale'
1414
stale-pr-label: 'stale'

.version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.13.6
1+
2.13.7

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<p align="center">
22
<img src="https://nginxproxymanager.com/github.png">
33
<br><br>
4-
<img src="https://img.shields.io/badge/version-2.13.6-green.svg?style=for-the-badge">
4+
<img src="https://img.shields.io/badge/version-2.13.7-green.svg?style=for-the-badge">
55
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
66
<img src="https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg?style=for-the-badge">
77
</a>

backend/biome.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"$schema": "https://biomejs.dev/schemas/2.3.2/schema.json",
2+
"$schema": "https://biomejs.dev/schemas/2.3.14/schema.json",
33
"vcs": {
44
"enabled": true,
55
"clientKind": "git",

backend/certbot/dns-plugins.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
"cloudns": {
7575
"name": "ClouDNS",
7676
"package_name": "certbot-dns-cloudns",
77-
"version": "~=0.6.0",
77+
"version": "~=0.7.0",
7878
"dependencies": "",
7979
"credentials": "# Target user ID (see https://www.cloudns.net/api-settings/)\n\tdns_cloudns_auth_id=1234\n\t# Alternatively, one of the following two options can be set:\n\t# dns_cloudns_sub_auth_id=1234\n\t# dns_cloudns_sub_auth_user=foobar\n\n\t# API password\n\tdns_cloudns_auth_password=password1",
8080
"full_plugin_name": "dns-cloudns"

backend/internal/2fa.js

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import crypto from "node:crypto";
22
import bcrypt from "bcrypt";
3-
import { authenticator } from "otplib";
3+
import { createGuardrails, generateSecret, generateURI, verify } from "otplib";
44
import errs from "../lib/error.js";
55
import authModel from "../models/auth.js";
66
import internalUser from "./user.js";
@@ -27,7 +27,6 @@ const generateBackupCodes = async () => {
2727
};
2828

2929
const internal2fa = {
30-
3130
/**
3231
* Check if user has 2FA enabled
3332
* @param {number} userId
@@ -72,8 +71,12 @@ const internal2fa = {
7271
startSetup: async (access, userId) => {
7372
await access.can("users:password", userId);
7473
const user = await internalUser.get(access, { id: userId });
75-
const secret = authenticator.generateSecret();
76-
const otpauth_url = authenticator.keyuri(user.email, APP_NAME, secret);
74+
const secret = generateSecret();
75+
const otpauth_url = generateURI({
76+
issuer: APP_NAME,
77+
label: user.email,
78+
secret: secret,
79+
});
7780
const auth = await internal2fa.getUserPasswordAuth(userId);
7881

7982
// ensure user isn't already setup for 2fa
@@ -85,7 +88,8 @@ const internal2fa = {
8588
const meta = auth.meta || {};
8689
meta.totp_pending_secret = secret;
8790

88-
await authModel.query()
91+
await authModel
92+
.query()
8993
.where("id", auth.id)
9094
.andWhere("user_id", userId)
9195
.andWhere("type", "password")
@@ -112,8 +116,8 @@ const internal2fa = {
112116
throw new errs.ValidationError("No pending 2FA setup found");
113117
}
114118

115-
const valid = authenticator.verify({ token: code, secret });
116-
if (!valid) {
119+
const result = await verify({ token: code, secret });
120+
if (!result.valid) {
117121
throw new errs.ValidationError("Invalid verification code");
118122
}
119123

@@ -156,12 +160,12 @@ const internal2fa = {
156160
throw new errs.ValidationError("2FA is not enabled");
157161
}
158162

159-
const valid = authenticator.verify({
163+
const result = await verify({
160164
token: code,
161165
secret: auth.meta.totp_secret,
162166
});
163167

164-
if (!valid) {
168+
if (!result.valid) {
165169
throw new errs.AuthError("Invalid verification code");
166170
}
167171

@@ -194,20 +198,30 @@ const internal2fa = {
194198
return false;
195199
}
196200

197-
// Try TOTP code first
198-
const valid = authenticator.verify({
199-
token,
200-
secret,
201-
});
202-
203-
if (valid) {
204-
return true;
201+
// Try TOTP code first, if it's 6 chars. it will throw errors if it's not 6 chars
202+
// and the backup codes are 8 chars.
203+
if (token.length === 6) {
204+
const result = await verify({
205+
token,
206+
secret,
207+
// These guardrails lower the minimum length requirement for secrets.
208+
// In v12 of otplib the default minimum length is 10 and in v13 it is 16.
209+
// Since there are 2fa secrets in the wild generated with v12 we need to allow shorter secrets
210+
// so people won't be locked out when upgrading.
211+
guardrails: createGuardrails({
212+
MIN_SECRET_BYTES: 10,
213+
}),
214+
});
215+
216+
if (result.valid) {
217+
return true;
218+
}
205219
}
206220

207221
// Try backup codes
208222
const backupCodes = auth?.meta?.backup_codes || [];
209223
for (let i = 0; i < backupCodes.length; i++) {
210-
const match = await bcrypt.compare(code.toUpperCase(), backupCodes[i]);
224+
const match = await bcrypt.compare(token.toUpperCase(), backupCodes[i]);
211225
if (match) {
212226
// Remove used backup code
213227
const updatedCodes = [...backupCodes];
@@ -248,12 +262,12 @@ const internal2fa = {
248262
throw new errs.ValidationError("No 2FA secret found");
249263
}
250264

251-
const valid = authenticator.verify({
265+
const result = await verify({
252266
token,
253267
secret,
254268
});
255269

256-
if (!valid) {
270+
if (!result.valid) {
257271
throw new errs.ValidationError("Invalid verification code");
258272
}
259273

backend/lib/config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { global as logger } from "../logger.js";
55
const keysFile = '/data/keys.json';
66
const mysqlEngine = 'mysql2';
77
const postgresEngine = 'pg';
8-
const sqliteClientName = 'sqlite3';
8+
const sqliteClientName = 'better-sqlite3';
99

1010
let instance = null;
1111

@@ -84,6 +84,7 @@ const configure = () => {
8484
}
8585

8686
const envSqliteFile = process.env.DB_SQLITE_FILE || "/data/database.sqlite";
87+
8788
logger.info(`Using Sqlite: ${envSqliteFile}`);
8889
instance = {
8990
database: {

backend/package.json

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,37 +12,38 @@
1212
"validate-schema": "node validate-schema.js"
1313
},
1414
"dependencies": {
15-
"@apidevtools/json-schema-ref-parser": "^11.7.0",
15+
"@apidevtools/json-schema-ref-parser": "^14.1.1",
1616
"ajv": "^8.17.1",
17-
"archiver": "^5.3.0",
17+
"archiver": "^7.0.1",
1818
"batchflow": "^0.4.0",
19-
"bcrypt": "^5.0.0",
20-
"body-parser": "^1.20.3",
19+
"bcrypt": "^6.0.0",
20+
"better-sqlite3": "^12.6.2",
21+
"body-parser": "^2.2.2",
2122
"compression": "^1.7.4",
22-
"express": "^4.22.0",
23+
"express": "^5.2.1",
2324
"express-fileupload": "^1.5.2",
2425
"gravatar": "^1.8.2",
25-
"jsonwebtoken": "^9.0.2",
26-
"knex": "2.4.2",
27-
"liquidjs": "10.6.1",
28-
"lodash": "^4.17.21",
26+
"jsonwebtoken": "^9.0.3",
27+
"knex": "3.1.0",
28+
"liquidjs": "10.24.0",
29+
"lodash": "^4.17.23",
2930
"moment": "^2.30.1",
30-
"mysql2": "^3.15.3",
31+
"mysql2": "^3.16.3",
3132
"node-rsa": "^1.1.1",
32-
"objection": "3.0.1",
33-
"otplib": "^12.0.1",
33+
"objection": "3.1.5",
34+
"otplib": "^13.2.1",
3435
"path": "^0.12.7",
35-
"pg": "^8.16.3",
36+
"pg": "^8.18.0",
3637
"proxy-agent": "^6.5.0",
3738
"signale": "1.4.0",
3839
"sqlite3": "^5.1.7",
3940
"temp-write": "^4.0.0"
4041
},
4142
"devDependencies": {
42-
"@apidevtools/swagger-parser": "^10.1.0",
43-
"@biomejs/biome": "^2.3.2",
44-
"chalk": "4.1.2",
45-
"nodemon": "^2.0.2"
43+
"@apidevtools/swagger-parser": "^12.1.0",
44+
"@biomejs/biome": "^2.3.14",
45+
"chalk": "5.6.2",
46+
"nodemon": "^3.1.11"
4647
},
4748
"signale": {
4849
"displayDate": true,

backend/schema/paths/tokens/2fa/post.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
},
1818
"code": {
1919
"minLength": 6,
20-
"maxLength": 6,
20+
"maxLength": 8,
2121
"type": "string",
2222
"example": "012345"
2323
}

0 commit comments

Comments
 (0)