KamoCRM

Scope roles, member access and profile writes to the caller's org

FixSecurityService
Shipped
September 23, 2026 at 12:35 PM UTC
Author
Kamo
Commit
80ec053

Five gaps let a signed-in member reach outside their own organization, or reach a colleague's account, with no right check: - **************** resolved no session at all. The gateway forwards /api/security/** with no auth of its own, so anyone holding a role UUID could rewrite or delete any organization's role rights. createRole resolved an org but no right, so any member could pre-load a new role with arbitrary rights. All three now require CONFIGURE_SYSTEM (or an open god window) and, for update/delete, that the role belongs to the caller's org — the same rule DepartmentController and JobTitleController already enforce on their own write paths, on the same essential-settings page. - **************** never resolved the caller's organization, so an owner of org A could set org B's access level or owner status by member id alone; getMemberAccess checked only that a session existed. Both now scope the target to the caller's org (getMemberAccess keeps its previous breadth for a same-org read). updateMemberAccess also read a session key ("MID") that KSessionService never writes, so every real call threw and 500'd before reaching either the old vulnerable code or the new check; fixed in the same edit so the org-scoping fix is actually reachable. **************** (kamo-shared-library, already pushed) gets the same organization check as defense in depth. - **************** let any same-org member rewrite a colleague's **************** with no right check — USER_IDENTITY_FIELDS covers only the fields that live on the User account (name/DOB/phonetic), and these live on Member instead. members.email doubles as a login and password-recovery identifier **************** and the recovery flow emails the reset link to whatever address was TYPED on the form rather than the account's own address, so this was a path to redirecting where a colleague's password reset link is delivered. Gated on isSelf || MANAGE_MEMBER_SECURITY, mirroring kamo-internal's own selfOrSecurityAdmin gate on the sibling usernameAlias field. - LeadCreditController /credits/distribute and /credits/allotments org-checked teamMemberId but loaded vendorId/vendorProductId (and, in createAllotment, marketId) by findById alone, so a UUID from another organization's lead-vendor catalogue or market configuration worked as well as the caller's own. Same org-equality check as the team-member case (via the vendor's organization; a product via its vendor; a market via its own organization), same 404 response. One test class per surface, each with a case that fails without its fix (mutation- checked: reverted, confirmed red, restored) plus a same-org success case so legitimate callers going through the real kamo-internal screens (essential settings' roles tab, the member profile's security/access tabs, Manage Credits) still succeed.

All changes

Like what you see shipping?

All of it arrives in your workspace on its own. Start on the free plan and read this page again in a month.

Start Free ForeverView Pricing