Actual Privilege Escalation via change-password Endpoint on OpenID-Migrated Servers
Any authenticated user can escalate to ADMIN on Actual servers migrated from password authentication to OpenID Connect by exploiting a lack of authorization checks, orphaned password rows, and client-controlled login methods, leading to full administrative privileges.
Actual is vulnerable to a privilege escalation attack affecting servers migrated from password authentication to OpenID Connect. This vulnerability, identified as CVE-2026-33318, allows any authenticated user, regardless of their initial role (including the BASIC role), to gain full ADMIN access. The vulnerability stems from three weaknesses: a missing authorization check on the /account/change-password endpoint, the persistence of the inactive password auth row after migration, and the acceptance of a client-supplied loginMethod which bypasses the server’s active auth configuration. This allows an attacker to overwrite the password hash for the admin account, authenticate, and gain complete control over the system. This affects multi-user servers running OpenID Connect that were previously configured with password authentication. Servers bootstrapped exclusively with OpenID are not affected. Versions prior to 26.4.0 of @actual-app/sync-server are vulnerable.
Attack Chain
- Attacker obtains a valid session token for any user role (including BASIC) on a migrated Actual server.
- Attacker sends a POST request to
/account/change-passwordwith a new password, using the valid session token in theX-Actual-Tokenheader and a JSON body containing the desired password. - The server updates the password hash in the
authtable for the inactive password authentication method, due to the missing authorization check. - Attacker sends a POST request to
/account/loginwith theloginMethodparameter set to “password” and the password set in the previous step. - The server accepts the client-supplied
loginMethodand authenticates the attacker as the anonymous admin account (username = ‘’), as this is the default user created during multiuser migration with ADMIN role. - The server returns a new session token for the admin account.
- Attacker uses the admin token to access administrative functions on the server.
- Attacker can manage all users, access all budget files, modify file access controls, and change server configuration.
Impact
Successful exploitation of this vulnerability grants an attacker full administrative privileges on the affected Actual server. This allows the attacker to manage all users, access all budget files regardless of ownership, modify file access controls, and change server configuration. The vulnerability affects multi-user servers running OpenID Connect that were previously configured with password authentication, meaning that a wide range of sensitive data and configurations are at risk. This can lead to significant data breaches, financial losses, and reputational damage.
Recommendation
- Apply the patch or upgrade to
@actual-app/sync-serverversion 26.4.0 or later to remediate CVE-2026-33318. - Implement server-side checks to restrict access to the
/account/change-passwordendpoint to password-authenticated sessions only, as recommended in the advisory. - Require current-password confirmation before accepting a new password via the
/account/change-passwordendpoint. - Enforce the
activestatus and remove client control over login method selection in thegetLoginMethod()function. - As an immediate mitigation for existing deployments, administrators who have fully migrated to OpenID and do not need password auth can remove the orphaned password row using the SQL command:
DELETE FROM auth WHERE method = 'password';.
Detection coverage 2
Detect Password Change Attempts on OpenID-Only Servers
highDetects attempts to change the password on servers that should only be using OpenID Connect by monitoring requests to the /account/change-password endpoint when the server is configured for OpenID only.
Detect Login Attempts with Client-Specified Password Method
mediumDetects login attempts where the client specifies the 'password' login method, potentially bypassing server-side authentication configurations.
Detection queries are kept inside the platform. Get full rules →