Description
UserService.UpdateAsync (src/Auth/Services/UserService.cs:69-72) and DeleteAsync (:78-80) both reject system users with InvalidActionException, but EnableUserAsync (:272-280) sets user.Enabled with no such check.
Core does not compensate: UserManagementServiceImpl.enableUser and disableUser are gated only on USER:ENABLE and contain no systemUser check either. So the enable/disable path is unguarded on both sides, while every other mutation of a system user is refused.
Consequence: any holder of USER:ENABLE can disable the acme, scep, cmp, localhost or attribute-content-resolver system users, breaking the flows that authenticate as them — ACME, SCEP and CMP enrolment stop working, and attribute dereferencing on the operation path fails.
The fix belongs beside the existing guards in UserService: reject when user.SystemUser in EnableUserAsync, covering both enable and disable.
Note that OmniTrustILM/core#1915 adds a defensive check on core's own enableUser/disableUser, but that only covers callers arriving through core. The auth API is independently reachable, so the authoritative guard has to live here.
Discovered while hardening system-role and system-user handling for the auditor role work (OmniTrustILM/ilm#307). The gap is pre-existing and independent of that feature.
Steps to Reproduce
- Authenticate as a user holding only
USER:ENABLE.
- Disable the
acme system user — PATCH /v1/users/{acmeUserUuid}/disable through core, or the equivalent auth endpoint directly.
- Attempt an ACME order.
Expected Behavior
The request is refused, the same way updating or deleting a system user is refused: InvalidActionException, "Cannot update system user."
Actual Behavior
The system user is disabled and the protocol it backs stops working.
Severity
Major
Description
UserService.UpdateAsync(src/Auth/Services/UserService.cs:69-72) andDeleteAsync(:78-80) both reject system users withInvalidActionException, butEnableUserAsync(:272-280) setsuser.Enabledwith no such check.Core does not compensate:
UserManagementServiceImpl.enableUseranddisableUserare gated only onUSER:ENABLEand contain nosystemUsercheck either. So the enable/disable path is unguarded on both sides, while every other mutation of a system user is refused.Consequence: any holder of
USER:ENABLEcan disable theacme,scep,cmp,localhostorattribute-content-resolversystem users, breaking the flows that authenticate as them — ACME, SCEP and CMP enrolment stop working, and attribute dereferencing on the operation path fails.The fix belongs beside the existing guards in
UserService: reject whenuser.SystemUserinEnableUserAsync, covering both enable and disable.Note that OmniTrustILM/core#1915 adds a defensive check on core's own
enableUser/disableUser, but that only covers callers arriving through core. The auth API is independently reachable, so the authoritative guard has to live here.Discovered while hardening system-role and system-user handling for the auditor role work (OmniTrustILM/ilm#307). The gap is pre-existing and independent of that feature.
Steps to Reproduce
USER:ENABLE.acmesystem user —PATCH /v1/users/{acmeUserUuid}/disablethrough core, or the equivalent auth endpoint directly.Expected Behavior
The request is refused, the same way updating or deleting a system user is refused:
InvalidActionException, "Cannot update system user."Actual Behavior
The system user is disabled and the protocol it backs stops working.
Severity
Major