chore(release): public-release readiness and security fixes for 1.1.16

Security:
- Escape user-supplied values in LDAP filters and DNs (group_ldap.js, user_ldap.js)
- Replace Math.random() token/UUID/OTP generation with crypto.randomUUID / crypto.randomInt
- Refuse startup when oauth.jwtSecret is missing or placeholder

Fixes:
- Correct from-address template rendering in email.js

Packaging:
- Remove private flag and bump version to 1.1.16

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-18 22:08:11 -04:00
parent 37f2ece172
commit efe3e514b0
9 changed files with 72 additions and 13 deletions
+19 -3
View File
@@ -45,6 +45,20 @@ function escapeLDAPSearchValue(val) {
.replace(/\0/g, '\\00');
}
// Escape a value used in an LDAP DN (RFC 4514).
function escapeLDAPDNValue(val) {
return String(val)
.replace(/\\/g, '\\\\')
.replace(/,/g, '\\,')
.replace(/\+/g, '\\+')
.replace(/"/g, '\\"')
.replace(/</g, '\\<')
.replace(/>/g, '\\>')
.replace(/;/g, '\\;')
.replace(/=/g, '\\=')
.replace(/^\s|\s$/g, match => match === ' ' ? '\\ ' : match);
}
// Compute the next available uid/gidNumber: the highest existing value below
// conf.uidGidReservedFloor, plus one -- or conf.uidGidMin if there are no
// such entries yet. Entries at/above the reserved floor (e.g. a bootstrap
@@ -72,7 +86,8 @@ async function addPosixGroup(client, data){
data.gidNumber = nextPosixId(groups, 'gidNumber');
await client.add(`cn=${data.cn},${conf.groupBase}`, {
const safeCn = escapeLDAPDNValue(data.cn);
await client.add(`cn=${safeCn},${conf.groupBase}`, {
cn: data.cn,
gidNumber: data.gidNumber,
objectclass: [ 'posixGroup', 'top' ]
@@ -94,6 +109,7 @@ async function addPosixAccount(client, data){
data.uidNumber = nextPosixId(people, 'uidNumber');
const safeCn = escapeLDAPDNValue(data.cn);
const entry = {
cn: data.cn,
sn: data.sn,
@@ -143,7 +159,7 @@ async function addPosixAccount(client, data){
entry.manager = [].concat(data.manager);
}
await client.add(`cn=${data.cn},${conf.userBase}`, entry);
await client.add(`cn=${safeCn},${conf.userBase}`, entry);
return data
@@ -799,7 +815,7 @@ User.addSSHkey = async function(data) {
// memberUid (RFC 2307, posixGroup) is a bare username, not a DN, unlike
// groupOfNames' `member` used by app_sso_* groups in group_ldap.js.
function personalGroupDN(uid){
return `cn=${uid},${conf.groupBase}`;
return `cn=${escapeLDAPDNValue(uid)},${conf.groupBase}`;
}
User.getPersonalGroupMembers = async function(uid) {