Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -158,16 +158,19 @@ export class OrganizationService {
return { added: true };
}

async deleteTeamMember(org: Organization, userId: string) {
async deleteTeamMember(org: Organization | string, userId: string) {
if (typeof org === 'string') {
return this._organizationRepository.deleteTeamMember(org, userId);
}
Comment on lines +161 to +164

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

Overloading deleteTeamMember to accept either an Organization object or a string orgId introduces a significant security risk (authorization bypass). When a string is passed, all permission and role checks are silently bypassed. If a developer in a user-facing controller accidentally passes a string orgId instead of the full Organization object, any user could delete team members without authorization.

To prevent this, keep deleteTeamMember strictly typed to Organization to enforce permission checks, and expose a separate, explicitly named method (e.g., deleteTeamMemberByOrgId) for system/webhook actions that are allowed to bypass these checks.

Suggested change
async deleteTeamMember(org: Organization | string, userId: string) {
if (typeof org === 'string') {
return this._organizationRepository.deleteTeamMember(org, userId);
}
async deleteTeamMemberByOrgId(orgId: string, userId: string) {
return this._organizationRepository.deleteTeamMember(orgId, userId);
}
async deleteTeamMember(org: Organization, userId: string) {

const userOrgs = await this._organizationRepository.getOrgsByUserId(userId);
const findOrgToDelete = userOrgs.find((orgUser) => orgUser.id === org.id);
if (!findOrgToDelete) {
throw new Error('User is not part of this organization');
}

// @ts-ignore
const myRole = org.users[0].role;
const userRole = findOrgToDelete.users[0].role;
const myRole = org.users?.[0]?.role;
const userRole = findOrgToDelete.users?.[0]?.role;
const myLevel = myRole === 'USER' ? 0 : myRole === 'ADMIN' ? 1 : 2;
const userLevel = userRole === 'USER' ? 0 : userRole === 'ADMIN' ? 1 : 2;

Expand Down
Loading