← Back to CVE Explorer

CVE-2026-33318

Full vulnerability record from the local CVENow database.

Description

Actual is a local-first personal finance tool. Prior to version 26.4.0, any authenticated user (including `BASIC` role) can escalate to `ADMIN` on servers migrated from password authentication to OpenID Connect. Three weaknesses combine: `POST /account/change-password` has no authorization check, allowing any session to overwrite the password hash; the inactive password `auth` row is never removed on migration; and the login endpoint accepts a client-supplied `loginMethod` that bypasses the server's active auth configuration. Together these allow an attacker to set a known password and authenticate as the anonymous admin account created during the multiuser migration. The three weaknesses form a single, sequential exploit chain — none produces privilege escalation on its own. Missing authorization on POST /change-password allows overwriting a password hash, but only matters if there is an orphaned row to target. Orphaned password row persisting after migration provides the target row, but is harmless without the ability to authenticate using it. Client-controlled loginMethod: "password" allows forcing password-based auth, but is useless without a known hash established by step 1. All three must be chained in sequence to achieve the impact. No single weakness independently results in privilege escalation. The single root cause is the missing authorization check on /change-password; the other two are preconditions that make it exploitable. Version 26.4.0 contains a fix.

Severity
HIGH
CVSS score
8.8 (v3.1)
Vulnerability status
Analyzed
Source identifier
Published
2026-04-24 03:16:11.203000
Last modified
2026-10-26 21:10:00.170000
View original CVE JSON
{
  "id": "CVE-2026-33318",
  "sourceIdentifier": "[email protected]",
  "published": "2026-04-24T03:16:11.203",
  "lastModified": "2026-10-26T21:10:00.170",
  "vulnStatus": "Analyzed",
  "cveTags": [],
  "descriptions": [
    {
      "lang": "en",
      "value": "Actual is a local-first personal finance tool. Prior to version 26.4.0, any authenticated user (including `BASIC` role) can escalate to `ADMIN` on servers migrated from password authentication to OpenID Connect. Three weaknesses combine: `POST /account/change-password` has no authorization check, allowing any session to overwrite the password hash; the inactive password `auth` row is never removed on migration; and the login endpoint accepts a client-supplied `loginMethod` that bypasses the server's active auth configuration. Together these allow an attacker to set a known password and authenticate as the anonymous admin account created during the multiuser migration. The three weaknesses form a single, sequential exploit chain — none produces privilege escalation on its own. Missing authorization on POST /change-password allows overwriting a password hash, but only matters if there is an orphaned row to target. Orphaned password row persisting after migration provides the target row, but is harmless without the ability to authenticate using it. Client-controlled loginMethod: \"password\" allows forcing password-based auth, but is useless without a known hash established by step 1. All three must be chained in sequence to achieve the impact. No single weakness independently results in privilege escalation. The single root cause is the missing authorization check on /change-password; the other two are preconditions that make it exploitable. Version 26.4.0 contains a fix."
    },
    {
      "lang": "es",
      "value": "Actual es una herramienta de finanzas personales local-first. Antes de la versión 26.4.0, cualquier usuario autenticado (incluido el rol ’BASIC’) puede escalar a ’ADMIN’ en servidores migrados de la autenticación por contraseña a OpenID Connect. Se combinan tres debilidades: ’POST /account/change-password’ no tiene verificación de autorización, lo que permite a cualquier sesión sobrescribir el hash de la contraseña; la fila ’auth’ de contraseña inactiva nunca se elimina durante la migración; y el endpoint de inicio de sesión acepta un ’loginMethod’ proporcionado por el cliente que omite la configuración de autenticación activa del servidor. Juntas, estas permiten a un atacante establecer una contraseña conocida y autenticarse como la cuenta de administrador anónima creada durante la migración multiusuario. Las tres debilidades forman una única cadena de exploit secuencial - ninguna produce escalada de privilegios por sí misma. La falta de autorización en POST /change-password permite sobrescribir un hash de contraseña, pero solo importa si hay una fila huérfana a la que apuntar. La fila de contraseña huérfana que persiste después de la migración proporciona la fila objetivo, pero es inofensiva sin la capacidad de autenticarse usándola. El ’loginMethod’: ’password’ controlado por el cliente permite forzar la autenticación basada en contraseña, pero es inútil sin un hash conocido establecido en el paso 1. Las tres deben encadenarse en secuencia para lograr el impacto. Ninguna debilidad individual resulta independientemente en escalada de privilegios. La única causa raíz es la falta de verificación de autorización en /change-password; las otras dos son precondiciones que lo hacen explotable. La versión 26.4.0 contiene una corrección."
    }
  ],
  "affected": [
    {
      "source": "[email protected]",
      "affectedData": [
        {
          "vendor": "actualbudget",
          "product": "actual",
          "versions": [
            {
              "version": "< 26.4.0",
              "status": "affected"
            }
          ]
        }
      ]
    }
  ],
  "metrics": {
    "cvssMetricV31": [
      {
        "source": "[email protected]",
        "type": "Secondary",
        "cvssData": {
          "version": "3.1",
          "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
          "baseScore": 8.8,
          "baseSeverity": "HIGH",
          "attackVector": "NETWORK",
          "attackComplexity": "LOW",
          "privilegesRequired": "LOW",
          "userInteraction": "NONE",
          "scope": "UNCHANGED",
          "confidentialityImpact": "HIGH",
          "integrityImpact": "HIGH",
          "availabilityImpact": "HIGH"
        },
        "exploitabilityScore": 2.8,
        "impactScore": 5.9
      }
    ],
    "ssvcV203": [
      {
        "source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
        "ssvcData": {
          "timestamp": "2026-04-25T01:43:46.313187Z",
          "id": "CVE-2026-33318",
          "options": [
            {
              "exploitation": "poc"
            },
            {
              "automatable": "no"
            },
            {
              "technicalImpact": "total"
            }
          ],
          "role": "CISA Coordinator",
          "version": "2.0.3"
        }
      }
    ]
  },
  "weaknesses": [
    {
      "source": "[email protected]",
      "type": "Secondary",
      "description": [
        {
          "lang": "en",
          "value": "CWE-284"
        },
        {
          "lang": "en",
          "value": "CWE-862"
        }
      ]
    }
  ],
  "configurations": [
    {
      "nodes": [
        {
          "operator": "OR",
          "negate": false,
          "cpeMatch": [
            {
              "vulnerable": true,
              "criteria": "cpe:2.3:a:actualbudget:actual:*:*:*:*:*:node.js:*:*",
              "versionEndExcluding": "26.4.0",
              "matchCriteriaId": "5EC7E455-5004-4D86-9FBD-DD88A4C3A1AA"
            }
          ]
        }
      ]
    }
  ],
  "references": [
    {
      "url": "https://actualbudget.org/blog/release-26.4.0",
      "source": "[email protected]",
      "tags": [
        "Release Notes"
      ]
    },
    {
      "url": "https://github.com/actualbudget/actual/security/advisories/GHSA-prp4-2f49-fcgp",
      "source": "[email protected]",
      "tags": [
        "Exploit",
        "Mitigation",
        "Vendor Advisory"
      ]
    },
    {
      "url": "https://github.com/actualbudget/actual/security/advisories/GHSA-prp4-2f49-fcgp",
      "source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
      "tags": [
        "Exploit",
        "Mitigation",
        "Vendor Advisory"
      ]
    }
  ]
}