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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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