Overview
Comprehensive security audit found 26 instances where User, GroupUsers, and OrganizationUser entities are returned to the frontend without filtering sensitive fields (password hashes, tokens).
Total Findings: 26
- P0 (Critical): 7 findings — fix this week
- P1 (High): 8 findings — fix next week
- P2 (Medium): 11 findings — fix later
Sensitive Fields Being Exposed:
password (bcrypt hash - crackable)
invitationToken (bypasses login)
forgotPasswordToken (resets password)
expiredPasswordToken (resets password)
passwordRetryCount, passwordExpiry, invitationTokenExpiry, forgotPasswordTokenExpiry
🔴 P0 - CRITICAL (Fix This Week)
1. Account Activation Exposes Password Hash
File: server/src/modules/onboarding/service.ts:217-220
Endpoint: POST /onboarding/setup-account-from-token
Impact: Password hash returned to frontend during account activation
Fix: Add select clause filtering to safe fields only
2. Role User List (getRoleUsersList)
File: server/src/modules/roles/repository.ts:27-57
Impact: Returns User[] with all fields; called 4+ times across codebase
Used by: group-permissions util, organization-users, granular-permissions
Fix: Add select clause
3. Group Admin Lookup (getAdminUserForOrg)
File: server/src/modules/group-permissions/repository.ts:401-413
Impact: Uses createQueryBuilder without .select(); called 6+ times
Note: Callers only need adminUser.id, unnecessary full load
Fix: Add .select() to queryBuilder
4. User Create/Update Leakage
File: server/src/modules/users/repositories/repository.ts:108-121
Issue: Lines 112 and 116 both missing select clauses in createOrUpdate()
Impact: Password exposed on user create/update operations
Fix: Add select clauses to both findOne calls
5. Email Lookups in Auth Flow (Multiple)
File: server/src/modules/users/repositories/repository.ts:233-258
Impact: THREE findOne calls without select in email validation paths
Used by: Password verification, user lookup during auth
Note: Password needed for bcrypt validation internally, but result should be sanitized before return
Fix: Add select clause or sanitize before returning
6. getUsersInGroup() - Group Members Exposed
File: server/src/modules/group-permissions/repository.ts:212-287
Endpoint: GET /api/v2/group-permissions/{id}/users
Impact: All group members' passwords/tokens leaked to anyone with group access
Both paths affected: Search and non-search branches
Fix: Add select clause to both .find() calls
7. getGroupUser() - Individual Member Exposed
File: server/src/modules/group-permissions/repository.ts:289-292
Impact: Returns GroupUsers with unfiltered User object
Used by: util-services (could bubble up)
Fix: Add select clause
🟠 P1 - HIGH (Fix Next Week)
External APIs Module (EE)
File: server/ee/external-apis/util.service.ts
Unsafe lines: 242, 580, 642, 786
Also: server/ee/external-apis/service.ts lines 177, 305, 921
Impact: 7 User queries without select in external API flows
Fix: Add select clauses to all queries
Workspace Branches (EE)
File: server/ee/workspace-branches/service.ts
Unsafe lines: 368, 686, 1276
Impact: User data loaded unnecessarily in git sync operations
Fix: Add select clauses
Organization-Users Repository
File: server/src/modules/organization-users/repository.ts:137-144
Method: findByInvitationToken()
Impact: Full User object returned
Fix: Add select clause
Also: server/src/modules/organization-users/util.service.ts:189
Method: findInvitingUserByEmail()
Fix: Add select clause
🟡 P2 - MEDIUM (Fix Later)
Files with 2-3 unsafe queries each:
server/src/modules/ai/util.service.ts
server/src/modules/profile/service.ts
server/ee/licensing/services/
server/ee/scim/services/ (mostly safe, 1-2 fixes)
server/src/modules/data-sources/service.ts
server/src/modules/apps/services/
server/ee/modules/marketplace/
✅ Safe Pattern Reference
Correct implementation (use this as template):
const user = await manager.findOne(User, {
where: { email },
select: {
id: true,
email: true,
firstName: true,
lastName: true,
avatarId: true,
status: true,
defaultOrganizationId: true,
userType: true,
createdAt: true,
// EXCLUDE: password, invitationToken, forgotPasswordToken,
// expiredPasswordToken, passwordRetryCount, etc.
},
relations: { organizationUsers: true }
});
Safe implementation examples found in:
server/src/modules/users/repositories/repository.ts:72-101 (getPaginatedData)
server/ee/scim/services/scim-users.service.ts:34-39
🔧 Verification Command
grep -rn 'manager\.find.*User\|createQueryBuilder(User' server/src/modules server/ee --include='*.ts' | grep -v 'select:' | grep -v node_modules
📋 Remediation Checklist
References
- Linear ticket: DEV-98
- Audit completed: 2026-08-28
- Audit scope: server/src/modules, server/ee
- Verification: 26 distinct findings, 15+ modules affected
- User entity location: server/src/entities/user.entity.ts
Overview
Comprehensive security audit found 26 instances where User, GroupUsers, and OrganizationUser entities are returned to the frontend without filtering sensitive fields (password hashes, tokens).
Total Findings: 26
Sensitive Fields Being Exposed:
password(bcrypt hash - crackable)invitationToken(bypasses login)forgotPasswordToken(resets password)expiredPasswordToken(resets password)passwordRetryCount,passwordExpiry,invitationTokenExpiry,forgotPasswordTokenExpiry🔴 P0 - CRITICAL (Fix This Week)
1. Account Activation Exposes Password Hash
File:
server/src/modules/onboarding/service.ts:217-220Endpoint:
POST /onboarding/setup-account-from-tokenImpact: Password hash returned to frontend during account activation
Fix: Add select clause filtering to safe fields only
2. Role User List (getRoleUsersList)
File:
server/src/modules/roles/repository.ts:27-57Impact: Returns User[] with all fields; called 4+ times across codebase
Used by: group-permissions util, organization-users, granular-permissions
Fix: Add select clause
3. Group Admin Lookup (getAdminUserForOrg)
File:
server/src/modules/group-permissions/repository.ts:401-413Impact: Uses createQueryBuilder without .select(); called 6+ times
Note: Callers only need adminUser.id, unnecessary full load
Fix: Add .select() to queryBuilder
4. User Create/Update Leakage
File:
server/src/modules/users/repositories/repository.ts:108-121Issue: Lines 112 and 116 both missing select clauses in createOrUpdate()
Impact: Password exposed on user create/update operations
Fix: Add select clauses to both findOne calls
5. Email Lookups in Auth Flow (Multiple)
File:
server/src/modules/users/repositories/repository.ts:233-258Impact: THREE findOne calls without select in email validation paths
Used by: Password verification, user lookup during auth
Note: Password needed for bcrypt validation internally, but result should be sanitized before return
Fix: Add select clause or sanitize before returning
6. getUsersInGroup() - Group Members Exposed
File:
server/src/modules/group-permissions/repository.ts:212-287Endpoint:
GET /api/v2/group-permissions/{id}/usersImpact: All group members' passwords/tokens leaked to anyone with group access
Both paths affected: Search and non-search branches
Fix: Add select clause to both .find() calls
7. getGroupUser() - Individual Member Exposed
File:
server/src/modules/group-permissions/repository.ts:289-292Impact: Returns GroupUsers with unfiltered User object
Used by: util-services (could bubble up)
Fix: Add select clause
🟠 P1 - HIGH (Fix Next Week)
External APIs Module (EE)
File:
server/ee/external-apis/util.service.tsUnsafe lines: 242, 580, 642, 786
Also:
server/ee/external-apis/service.tslines 177, 305, 921Impact: 7 User queries without select in external API flows
Fix: Add select clauses to all queries
Workspace Branches (EE)
File:
server/ee/workspace-branches/service.tsUnsafe lines: 368, 686, 1276
Impact: User data loaded unnecessarily in git sync operations
Fix: Add select clauses
Organization-Users Repository
File:
server/src/modules/organization-users/repository.ts:137-144Method: findByInvitationToken()
Impact: Full User object returned
Fix: Add select clause
Also:
server/src/modules/organization-users/util.service.ts:189Method: findInvitingUserByEmail()
Fix: Add select clause
🟡 P2 - MEDIUM (Fix Later)
Files with 2-3 unsafe queries each:
server/src/modules/ai/util.service.tsserver/src/modules/profile/service.tsserver/ee/licensing/services/server/ee/scim/services/(mostly safe, 1-2 fixes)server/src/modules/data-sources/service.tsserver/src/modules/apps/services/server/ee/modules/marketplace/✅ Safe Pattern Reference
Correct implementation (use this as template):
Safe implementation examples found in:
server/src/modules/users/repositories/repository.ts:72-101(getPaginatedData)server/ee/scim/services/scim-users.service.ts:34-39🔧 Verification Command
📋 Remediation Checklist
References