CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-27638

Actual Budget Sync Authorization Bypass (IDOR)

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 27, 2026·5 min read·23 visits

Executive Summary (TL;DR)

Actual Budget versions prior to 26.2.1 fail to verify file ownership on synchronization endpoints. Any authenticated user can read or overwrite another user's financial data by supplying the target's budget ID in API requests.

A critical authorization flaw exists in Actual Budget's synchronization server, specifically affecting multi-user deployments. The vulnerability allows authenticated users to access, modify, or delete budget files belonging to other users due to missing ownership verification checks in the sync endpoints. This effectively constitutes an Insecure Direct Object Reference (IDOR) where knowledge of a file's UUID is sufficient to grant full access, bypassing intended isolation between users.

Vulnerability Overview

Actual Budget is a local-first personal finance application that supports a server component for syncing data across devices. In multi-user configurations, the server acts as a central repository for multiple distinct user accounts. CVE-2026-27638 identifies a Missing Authorization vulnerability (CWE-862) within this synchronization layer.

The core issue lies in the API endpoints responsible for handling budget file operations, such as downloading, uploading, and syncing changes. While the application correctly enforces authentication—requiring a valid session token to interact with the API—it failed to implement resource-level authorization. Consequently, the server did not verify that the authenticated user was the owner of the budget file specified in the request.

Root Cause Analysis

The vulnerability stems from a reliance on authentication middleware without complementary object-level permission checks. The server utilizes validateSessionMiddleware to ensure that incoming requests originate from a logged-in user. However, once this check passed, the endpoints trustingly accepted the fileId (typically provided via the X-Actual-File-Id header or JSON body) as the target resource.

In packages/sync-server/src/app-sync.ts, handlers for routes like /sync, /download-user-file, and /upload-user-file would retrieve file metadata from the database based on the provided ID. The logic proceeded to perform the requested operation (read/write) immediately after retrieval. Crucially, the code did not compare the owner field of the retrieved file record against the userId associated with the active session. This omission created a direct path for Insecure Direct Object Reference (IDOR), where the identifier alone acted as the authorization token.

Code Analysis

The following comparison highlights the absence of authorization logic in the vulnerable version and the explicit checks introduced in the patch.

Vulnerable Logic (Conceptual Representation):

Before the fix, endpoints would look up a file and immediately return it or process it, assuming that possession of the ID implied permission.

// Vulnerable handler example
app.post('/download-user-file', async (req, res) => {
  const fileId = req.headers['x-actual-file-id'];
  // DANGER: No check to see if req.userId owns fileId
  const file = await db.getFile(fileId);
  
  if (file) {
    res.send(file.content);
  }
});

Patched Logic (Commit 9966c024):

The fix introduces a centralized helper function requireFileAccess which is now invoked at the start of every sync endpoint. This function explicitly validates ownership or administrative privileges.

// New authorization helper
function requireFileAccess(file, userId) {
  // 1. Direct ownership check
  if (file.owner === userId) {
    return null; // Access granted
  }
  
  // 2. Admin override for system tasks
  if (isAdmin(userId)) {
    return null;
  }
 
  // 3. Shared access check (new feature support)
  if (UserService.countUserAccess(file.id, userId) > 0) {
    return null;
  }
 
  // Default deny
  return 'file-access-not-allowed';
}
 
// Patched handler usage
app.post('/download-user-file', async (req, res) => {
  const fileId = req.headers['x-actual-file-id'];
  const file = await db.getFile(fileId);
 
  // Explicit authorization gate
  const accessError = requireFileAccess(file, req.userId);
  if (accessError) {
    return res.status(403).send(accessError);
  }
 
  res.send(file.content);
});

This change ensures that even if an attacker guesses a valid fileId, the server rejects the request if the database record for that file lists a different owner.

Exploitation Scenario

To exploit this vulnerability, an attacker requires a valid account on the target Actual Budget instance. The attack does not require administrative privileges, only a standard user session.

Step 1: Reconnaissance The attacker must obtain the fileId (a UUID) of a target budget. While UUIDs are generally not enumerable, they may be leaked through shared logs, exposed in client-side errors, or obtained via social engineering. In some configurations or older versions, file IDs might be predictable or sequentially generated (though Actual uses UUIDs by default).

Step 2: Execution The attacker crafts a malicious HTTP request to the synchronization API. For example, to exfiltrate a victim's budget:

POST /download-user-file HTTP/1.1
Host: budget.example.com
X-Actual-Token: <attacker-session-token>
X-Actual-File-Id: <victim-budget-uuid>
Content-Type: application/json
 
{}

Step 3: Impact The server processes the request using the attacker's valid session but the victim's file ID. Without the ownership check, the server returns the victim's full budget database. Conversely, an attacker could upload a corrupted database to the same ID, destroying the victim's data.

Impact Assessment

The impact of this vulnerability is significant for multi-user deployments, affecting the confidentiality and integrity of financial data.

Confidentiality: An attacker can download complete budget files, exposing sensitive transaction histories, bank balances, and financial habits of other users.

Integrity: An attacker can modify or overwrite budget files. This allows for the injection of fraudulent transactions, deletion of valid records, or complete corruption of the budget database, rendering it unusable for the legitimate owner.

Availability: The /delete-user-file endpoint is also affected. An attacker could permanently delete other users' budget files, causing data loss if no backups exist.

The CVSS v3.1 score is 7.1 (High), driven by the high Integrity impact and the low complexity required to execute the attack once a file ID is known.

Remediation and Mitigation

The primary remediation is to update the Actual server software.

Patching: Update to Actual version 26.2.1 or later. This version includes the requireFileAccess logic and database migrations to ensure all existing files have correctly assigned owners.

Configuration Workarounds: If immediate patching is not feasible, administrators should restrict the instance to single-user mode. This vulnerability specifically impacts multi-user configurations where isolation between accounts is assumed. By disabling open registration and ensuring only trusted users have accounts, the risk is mitigated, although the underlying code flaw remains.

Database Audit: Post-update, administrators should verify that the migration script (1763873600000-backfill-files-owner.js) successfully populated the owner column for all records in the files table. Orphaned files (files with NULL owners) should be manually assigned or audited.

Official Patches

Actual BudgetRelease notes for version 26.2.1 containing the fix

Fix Analysis (1)

Technical Appendix

CVSS Score
7.1/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:N
EPSS Probability
0.04%
Top 89% most exploited

Affected Systems

Actual Budget Server (Multi-user configuration)

Affected Versions Detail

Product
Affected Versions
Fixed Version
Actual
Actual Budget
< 26.2.126.2.1
AttributeDetail
CWE IDCWE-862
Vulnerability TypeMissing Authorization / IDOR
CVSS v3.17.1 (High)
Attack VectorNetwork
Privileges RequiredLow (Authenticated User)
ImpactData Exfiltration & Integrity Loss

MITRE ATT&CK Mapping

T1068Exploitation for Privilege Escalation
Privilege Escalation
T1565Data Manipulation
Impact
CWE-862
Missing Authorization

Vulnerability Timeline

Initial related fixes for bank sync auth
2026-02-19
Fix commit merged
2026-02-21
Version 26.2.1 Released
2026-02-22
CVE-2026-27638 Public Disclosure
2026-02-26

References & Sources

  • [1]GitHub Security Advisory
  • [2]Actual Budget Official Site

More Reports

•13 minutes ago•CVE-2026-53653
8.7

CVE-2026-53653: Unauthenticated Denial of Service via Unbounded Image Derivative Dimensions in Grav CMS

Grav CMS prior to version 1.7.53 and 2.0.0-rc.8 is vulnerable to an unauthenticated remote denial of service (DoS) vulnerability. By supplying crafted query parameters with extremely large dimensions to image assets, remote unauthenticated attackers can force the server to allocate massive amounts of system memory, leading to kernel Out-Of-Memory (OOM) termination of web worker processes.

Amit Schendel
Amit Schendel
0 views•7 min read
•about 1 hour ago•CVE-2026-53657
8.2

CVE-2026-53657: Privilege Escalation via Overly Permissive Unix Domain Socket in Lima Guest Agent

CVE-2026-53657 is a local privilege escalation vulnerability in Lima (lima-vm/lima) affecting versions prior to 2.1.3 when configured with the QEMU driver. The guest agent daemon, running as root, creates its communication socket `/run/lima-guestagent.sock` with world-writable permissions (0777). This allows unprivileged local users to command the agent to establish arbitrary tunnels, including to privileged local UNIX sockets (like D-Bus). Because the target daemon authenticates the incoming connection using the credentials of the root-owned guest agent (via SO_PEERCRED), unprivileged users can perform root operations, resulting in complete guest VM compromise.

Amit Schendel
Amit Schendel
2 views•9 min read
•about 2 hours ago•CVE-2026-10740
5.3

CVE-2026-10740: Denial of Service in s2n-quic CryptoStream Reassembly

An unauthenticated Denial of Service vulnerability exists in the s2n-quic library's CryptoStream reassembler due to a lack of buffer limits on out-of-order cryptographic frames. An attacker can transmit a crafted CRYPTO frame with an extremely high offset and nominal payload, forcing the receiver to execute unbounded memory allocations and causing service crashes.

Amit Schendel
Amit Schendel
3 views•7 min read
•about 3 hours ago•CVE-2026-55153
7.1

CVE-2026-55153: JNDI Injection and Deserialization Gadget Abuse in mchange-commons-java

A JNDI Injection and Deserialization Gadget vulnerability exists in mchange-commons-java prior to version 0.6.0. The com.mchange.v2.naming.JavaBeanObjectFactory component permits arbitrary class instantiation and setter invocation, allowing attackers to perform Server-Side Request Forgery (SSRF) and remote class loading.

Alon Barad
Alon Barad
6 views•5 min read
•about 4 hours ago•GHSA-8RW6-P7M8-63JP
6.5

GHSA-8RW6-P7M8-63JP: Array Element-Level SELECT Permissions Leak in SurrealDB

SurrealDB versions supporting element-level SELECT permissions on arrays are vulnerable to a logical authorization bypass. Due to an index-shifting error during array filtration, restricted elements can skip permission checks and leak to unauthorized record users.

Alon Barad
Alon Barad
5 views•6 min read
•1 day ago•CVE-2026-12243
7.5

CVE-2026-12243: Incomplete Path Traversal Validation and Percent-Encoding Bypass in NLTK

CVE-2026-12243 is a path traversal vulnerability in the Natural Language Toolkit (NLTK) version 3.9.4. The flaw exists because the input validation routine fails to account for percent-encoded directory traversal sequences like '..%2f' before passing them to urllib.request.url2pathname(), which decodes them into active traversal sequences.

Amit Schendel
Amit Schendel
5 views•8 min read