Skip to content

Security: User Entity Sensitive Field Exposure (26 Findings) #17717

Description

@RndmCodeGuy20

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

  • P0-1: Fix onboarding account activation
  • P0-2: Fix getRoleUsersList with select
  • P0-3: Fix getAdminUserForOrg with queryBuilder select
  • P0-4: Fix user createOrUpdate email lookups
  • P0-5: Fix email validation lookups
  • P0-6: Fix getUsersInGroup (both paths)
  • P0-7: Fix getGroupUser
  • P1: Fix external APIs (7 queries)
  • P1: Fix workspace-branches (3 queries)
  • P1: Fix organization-users (2 methods)
  • P2: Fix AI, Profile, Licensing, SCIM, etc.
  • Verify no API response changes (except removed fields)
  • Run full test suite
  • Spot-check affected endpoints in browser

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingsecurity

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions