CVE-2026-50007 Overview
CVE-2026-50007 is a missing authorization vulnerability [CWE-862] in Actual, an open-source personal finance application. Versions prior to 26.7.0 allow a shared user with user_access on a budget file to invoke owner-only file management endpoints. The requireFileAccess middleware treats ordinary shared access as sufficient for privileged operations that should be restricted to the file owner or an administrator. A non-owner shared user can call /delete-user-file, /reset-user-file, and /user-create-key endpoints. This grants them destructive control over budget files they do not own. The issue is fixed in version 26.7.0.
Critical Impact
A low-privilege shared user can delete, reset, or rekey budget files owned by other users, causing data loss and integrity compromise across multi-user Actual deployments.
Affected Products
- Actual Budget (actualbudget/actual) versions prior to 26.7.0
- Self-hosted Actual sync-server deployments with multi-user file sharing enabled
- Any Actual instance where users share budget files via user_access grants
Discovery Timeline
- 2026-07-07 - CVE-2026-50007 published to the National Vulnerability Database (NVD)
- 2026-07-08 - Last updated in NVD database
Technical Details for CVE-2026-50007
Vulnerability Analysis
Actual's sync-server enforces file-level access through a middleware function named requireFileAccess in packages/sync-server/src/app-sync.ts. This function was applied uniformly to both read/write sync operations and to sensitive file management endpoints. Because it permits any user with a user_access record on the file, it fails to distinguish between shared collaborators and the file owner.
The result is a broken access control condition. A shared user can invoke management endpoints such as /delete-user-file (permanently removes the file), /reset-user-file (wipes and reinitializes budget state), and /user-create-key (rotates the encryption key). These actions are intended for the file owner or a server administrator. The vulnerability enables horizontal and vertical privilege escalation within the multi-user model.
Root Cause
The root cause is a single-tier authorization check that conflates "can access the file" with "can manage the file." [CWE-862] Missing Authorization occurs because the code does not differentiate between the ownership role and the shared-access role before executing owner-only operations.
Attack Vector
An authenticated shared user issues HTTP requests to the sync-server file management endpoints against a file where they hold only user_access. The server validates the shared access, passes the middleware check, and executes the destructive operation. No user interaction from the owner is required.
// Patch from packages/sync-server/src/app-sync.ts
// Introduces a stricter requireFileOwner check separate from requireFileAccess
-function requireFileAccess(file: File, userId: string) {
+function requireFileOwner(file: File, userId: string) {
const isOwner = file.owner === userId;
const isServerAdmin = isAdmin(userId);
if (isOwner || isServerAdmin) {
return null;
}
+ return 'file-access-not-allowed';
+}
+
+function requireFileAccess(file: File, userId: string) {
+ if (requireFileOwner(file, userId) === null) {
+ return null;
+ }
if (UserService.countUserAccess(file.id, userId) > 0) {
return null;
}
Source: GitHub Commit 18a8dc0
Detection Methods for CVE-2026-50007
Indicators of Compromise
- HTTP requests to /delete-user-file, /reset-user-file, or /user-create-key originating from user identifiers that do not match the target file's owner column.
- Unexpected budget file deletions, resets, or encryption key rotations recorded in sync-server logs.
- Sync errors or forced re-authentication events reported by budget owners whose files were rekeyed without their action.
Detection Strategies
- Audit sync-server access logs for file-management endpoint calls and correlate the requesting userId against the file owner field in the database.
- Query the Actual database for recent changes to file ownership, encryption keys, or deletion markers and cross-reference with the acting user.
- Enable verbose request logging on the reverse proxy fronting the sync-server to capture endpoint paths and authenticated user identifiers.
Monitoring Recommendations
- Alert on any invocation of /delete-user-file or /reset-user-file where the caller is not the file owner or a server admin.
- Track the rate of /user-create-key calls per user and flag anomalies against baseline behavior.
- Forward sync-server logs to a centralized logging platform and retain them long enough to support post-incident review of shared-user activity.
How to Mitigate CVE-2026-50007
Immediate Actions Required
- Upgrade all Actual sync-server instances to version 26.7.0 or later without delay.
- Review the list of shared users on every budget file and revoke user_access grants that are no longer required.
- Restore any budget files that were deleted or reset by unauthorized shared users from backup.
Patch Information
The fix is delivered in Actual version 26.7.0. It introduces a new requireFileOwner middleware that validates ownership or administrator status before permitting management operations, while requireFileAccess remains for standard sync endpoints. See GitHub Pull Request #7977, GitHub Pull Request #8333, and GitHub Security Advisory GHSA-23vm-ffgg-qvjr for full details.
Workarounds
- If upgrading immediately is not possible, remove all user_access grants and operate budget files in single-owner mode until the patch is applied.
- Restrict network access to the sync-server so that only trusted, known users can reach the file management endpoints.
- Place a reverse proxy in front of the sync-server that blocks requests to /delete-user-file, /reset-user-file, and /user-create-key from non-owner accounts.
# Example: upgrade a self-hosted Actual sync-server Docker deployment
docker pull actualbudget/actual-server:26.7.0
docker stop actual-server && docker rm actual-server
docker run -d --name actual-server \
-p 5006:5006 \
-v /opt/actual/data:/data \
actualbudget/actual-server:26.7.0
# Verify the running version
curl -s http://localhost:5006/info | jq .build.version
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

