GHSA-xvp7-8vm8-xfxx: @actual app/sync server Actual Sync-server Gocardless Service Is Vulnerability

MODERATE
CVSS 4.2
CWE-209 CWE-215 CWE-219
Published
Advisory Summary

GHSA-xvp7-8vm8-xfxx is a MODERATE (CVSS 4.2) actual sync-server gocardless service is vulnerability (CWE-209: Generation of Error Message Containing Sensitive Information) affecting @actual app/sync server libraries in the npm ecosystem. The issue involves actual sync-server gocardless service is logging sensitive data including bearer tokens and account numbers. Remediation is available by upgrading affected packages to version 25.11.0.

GHSA-xvp7-8vm8-xfxx at a Glance

CVE Identifier N/A
GHSA Identifier GHSA-xvp7-8vm8-xfxx
Severity MODERATE
CVSS v3.1 Base Score 4.2
CWE Classification CWE-209: Generation of Error Message Containing Sensitive Information
Affected Product @actual app/sync server
Package Ecosystem npm
Published Date
Last Updated

Security Impact

CVSS: 4.2

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:L/AC:L/PR:H/UI:R/S:U/C:H/I:N/A:N).

Attack Vector Local (AV:L)
Attack Complexity Low (AC:L)
Privileges Required High (PR:H)
User Interaction Required (UI:R)
Scope Unchanged (S:U)
Confidentiality High (C:H)
Integrity None (I:N)
Availability None (A:N)

How to Fix GHSA-xvp7-8vm8-xfxx

To remediate this vulnerability, upgrade all affected @actual app/sync server dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

@actual-app/sync-server fixed: 25.11.0
npm install @actual-app/sync-server@25.11.0
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

npm ls @actual-app/sync-server

How to Check if You Are Affected

To determine whether your Node.js application is affected by GHSA-xvp7-8vm8-xfxx, inspect your project dependencies using npm:

npm ls @actual-app/sync-server

Analyze the terminal output to locate any version of @actual app/sync server in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 25.11.0), your application is affected.

Note: The npm ls @actual-app/sync-server command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-209: Generation of Error Message Containing Sensitive Information, where the product generates an error message that includes sensitive information about its environment, users, or associated data. In @actual app/sync server, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Summary The GoCardless components in Actualbudget in are logging responses to STDOUT in a parsed format using `console.log`and `console.debug` (Which in this version of node is an alias for `console.log`). This is exposing sensitive information in log files including, but not limited to: - Gocardless bearer tokens. - Account IBAN and Bank Account numbers. - PII of the account holder. - Transaction details (Payee bank information, Recipient account numbers, Transaction IDs)... ### Details Whenever GoCardless responds to a request, the payload is printed to the debug log: https://github.com/actualbudget/actual/blob/36c40d90d2fe09eb1f25a6e2f77f6dd40638b267/packages/sync-server/src/app-gocardless/banks/integration-bank.js#L25-L27 This in turn logs the following information to Docker (all values removed here. These fields are possibly dependent on what is returned by each institution so may differ): ```json { "account": { "resourceId": "", "iban": "", "bban": "", "currency": "", "name": "<full legal name in the bank>", "product": "", "status": "", "bic": "", "usage": "", "id": "", "created": "", "last_accessed": "", "institution_id": "", "owner_name": "", "institution": { "id": "", "name": "", "bic": "", "transaction_total_days": "", "countries": [ "" ], "logo": "", "max_access_valid_for_days": "", "supported_features": [ "", "", "" ], "identification_codes": [] } } } ``` https://github.com/actualbudget/actual/blob/36c40d90d2fe09eb1f25a6e2f77f6dd40638b267/packages/sync-server/src/app-gocardless/banks/integration-bank.js#L83-L85 This is the first of the 10 transactions: ```json { "top10Transactions": [{ "transactionId": "", "entryReference": "", "bookingDate": "", "valueDate": "", "transactionAmount": { "amount": "", "currency": "" }, "creditorName": "", "creditorAccount": { "bban": "" }, "debtorName": "", "debtorAccount": { "bban": "" }, "remittanceInformationUnstructured": "", "remittanceInformationStructuredArray": [ {"reference": "", "referenceType": ""} ], "additionalInformation": "", "proprietaryBankTransactionCode": "", "debtorAgent": "", "internalTransactionId": "", "payeeName": "", "date": "" }] } ``` Additionally, in the error handling for GoCardless, there is a catch all for unclassified errors that prints the entire stack trace to the console. https://github.com/actualbudget/actual/blob/36c40d90d2fe09eb1f25a6e2f77f6dd40638b267/packages/sync-server/src/app-gocardless/app-gocardless.js#L263-L264 Our bank was offline today for maintenance which threw a 503 error from Gocardless. The entire response payload was dumped to console, which includes the Bearer tokens for accessing GoCardless: ```java Something went wrong ServiceError: Institution service unavailable at handleGoCardlessError (file:///app/src/app-gocardless/services/gocardless-service.js:59:13) at Object.getTransactions (file:///app/src/app-gocardless/services/gocardless-service.js:530:7) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async Object.getNormalizedTransactions (file:///app/src/app-gocardless/services/gocardless-service.js:267:26) at async file:///app/src/app-gocardless/app-gocardless.js:186:13 { details: h [AxiosError]: Request failed with status code 503 at te (file:///app/node_modules/nordigen-node/dist/index.esm.js:13:914) at IncomingMessage.<anonymous> (file:///app/node_modules/nordigen-node/dist/index.esm.js:17:16315) at IncomingMessage.emit (node:events:529:35) at endReadableNT (node:internal/streams/readable:1400:12) at process.processTicksAndRejections (node:internal/process/task_queues:82:21) { code: 'ERR_BAD_RESPONSE', config: { transitional: { silentJSONParsing: true, forcedJSONParsing: true, clarifyTimeoutError: false }, adapter: [ 'xhr', 'http' ], transformRequest: [ [Function (anonymous)] ], transformResponse: [ [Function (anonymous)] ], timeout: 0, xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', maxContentLength: -1, maxBodyLength: -1, env: { FormData: [Function: _] { LINE_BREAK: '\r\n', DEFAULT_CONTENT_TYPE: 'application/octet-stream' }, Blob: [class Blob] }, validateStatus: [Function: validateStatus], headers: T [AxiosHeaders] { Accept: 'application/json', 'Content-Type': 'application/json', 'User-Agent': 'Nordigen-Node-v2', 'Authorization': 'Bearer eyJ0eXAi... (the full token is in the response)', 'Accept-Encoding': 'gzip, compress, deflate, br' }, method: 'get', url: URL { href: 'https://bankaccountdata.gocardless.com/api/v2/accounts/<Account id Was Here>?date_from=2024-12-22', origin: 'https://bankaccountdata.gocardless.com', protocol: 'https:', username: '', password: '', host: 'bankaccountdata.gocardless.com', hostname: 'bankaccountdata.gocardless.com', port: '', pathname: '/api/v2/accounts/<Account id Was Here>/transactions', search: '?date_from=2024-12-22', searchParams: URLSearchParams { 'date_from' => '2024-12-22' }, hash: '' }, data: undefined }, ``` And quite a few pages more. ### PoC - Setup an Actualbudget server inside of Docker. In this instance I was using the Docker Compose script posted in the repository: https://github.com/actualbudget/actual/blob/master/packages/sync-server/docker-compose.yml - Link a gocardless account to Actualbudget and sync a bank account - Observe in the container using `docker logs actual-actual_server-1 -f` that sensitive details are logged to the console and ingested by docker. ### Impact Information disclosure. The services are available both on-premises and in environments that are not under the control of the end user, such as third-party providers who offer this application as a managed solution.

GHSA-xvp7-8vm8-xfxx Affected @actual app/sync server Versions

1 component(s)
Fixed Versions:
25.11.0
Product / Package Ecosystem Affected Versions Fixed Version
@actual-app/sync-server
npm
< 25.11.0
25.11.0

References

Frequently Asked Questions

What is GHSA-xvp7-8vm8-xfxx?
GHSA-xvp7-8vm8-xfxx is a security vulnerability in @actual app/sync server involving Actual Sync-server Gocardless service is logging sensitive data including bearer tokens and account numbers under CWE-209: Generation of Error Message Containing Sensitive Information.
Which @actual app/sync server versions are affected?
Affected versions include releases prior to 25.11.0 across affected packages: @actual-app/sync-server.
What version fixes GHSA-xvp7-8vm8-xfxx?
Upgrading to 25.11.0 (or the latest patched release for your respective branch) resolves the vulnerability.
Is @actual-app/sync-server affected?
Yes, @actual-app/sync-server is affected in releases prior to 25.11.0. Upgrade your dependency to 25.11.0 or later.
What is the CVSS score of GHSA-xvp7-8vm8-xfxx?
GHSA-xvp7-8vm8-xfxx has a CVSS v3.1 base score of 4.2 (MODERATE) with vector string CVSS:3.1/AV:L/AC:L/PR:H/UI:R/S:U/C:H/I:N/A:N.
What CWE is associated with GHSA-xvp7-8vm8-xfxx?
GHSA-xvp7-8vm8-xfxx is classified under CWE-209: Generation of Error Message Containing Sensitive Information (The product generates an error message that includes sensitive information about its environment, users, or associated data.).
How can I check npm dependencies for GHSA-xvp7-8vm8-xfxx?
Run the dependency tree command: 'npm ls @actual-app/sync-server'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-xvp7-8vm8-xfxx",
  "modified" : "2026-06-08T23:28:41Z",
  "published" : "2025-10-20T17:55:59Z",
  "aliases" : [ ],
  "summary" : "Actual Sync-server Gocardless service is logging sensitive data including bearer tokens and account numbers",
  "details" : "### Summary\nThe GoCardless components in Actualbudget in are logging responses to STDOUT in a parsed format using `console.log`and `console.debug` (Which in this version of node is an alias for `console.log`). This is exposing sensitive information in log files including, but not limited to:\n\n- Gocardless bearer tokens.\n- Account IBAN and Bank Account numbers.\n- PII of the account holder.\n- Transaction details (Payee bank information, Recipient account numbers, Transaction IDs)...\n\n### Details\n\nWhenever GoCardless responds to a request, the payload is printed to the debug log: \nhttps://github.com/actualbudget/actual/blob/36c40d90d2fe09eb1f25a6e2f77f6dd40638b267/packages/sync-server/src/app-gocardless/banks/integration-bank.js#L25-L27\n\nThis in turn logs the following information to Docker (all values removed here. These fields are possibly dependent on what is returned by each institution so may differ):\n\n```json\n{\n  \"account\": {\n    \"resourceId\": \"\",\n    \"iban\": \"\",\n    \"bban\": \"\",\n    \"currency\": \"\",\n    \"name\": \"<full legal name in the bank>\",\n    \"product\": \"\",\n    \"status\": \"\",\n    \"bic\": \"\",\n    \"usage\": \"\",\n    \"id\": \"\",\n    \"created\": \"\",\n    \"last_accessed\": \"\",\n    \"institution_id\": \"\",\n    \"owner_name\": \"\",\n    \"institution\": {\n      \"id\": \"\",\n      \"name\": \"\",\n      \"bic\": \"\",\n      \"transaction_total_days\": \"\",\n      \"countries\": [\n        \"\"\n      ],\n      \"logo\": \"\",\n      \"max_access_valid_for_days\": \"\",\n      \"supported_features\": [\n        \"\",\n        \"\",\n        \"\"\n      ],\n      \"identification_codes\": []\n    }\n  }\n}\n```\n\nhttps://github.com/actualbudget/actual/blob/36c40d90d2fe09eb1f25a6e2f77f6dd40638b267/packages/sync-server/src/app-gocardless/banks/integration-bank.js#L83-L85\n\nThis is the first of the 10 transactions:\n```json\n{\n  \"top10Transactions\": [{\n    \"transactionId\": \"\",\n    \"entryReference\": \"\",\n    \"bookingDate\": \"\",\n    \"valueDate\": \"\",\n    \"transactionAmount\": {\n      \"amount\": \"\",\n      \"currency\": \"\"\n    },\n    \"creditorName\": \"\",\n    \"creditorAccount\": {\n      \"bban\": \"\"\n    },\n    \"debtorName\": \"\",\n    \"debtorAccount\": {\n      \"bban\": \"\"\n    },\n    \"remittanceInformationUnstructured\": \"\",\n    \"remittanceInformationStructuredArray\": [\n      {\"reference\": \"\", \"referenceType\": \"\"}\n    ],\n    \"additionalInformation\": \"\",\n    \"proprietaryBankTransactionCode\": \"\",\n    \"debtorAgent\": \"\",\n    \"internalTransactionId\": \"\",\n    \"payeeName\": \"\",\n    \"date\": \"\"\n  }]\n}\n```\n\nAdditionally, in the error handling for GoCardless, there is a catch all for unclassified errors that prints the entire stack trace to the console.\n\nhttps://github.com/actualbudget/actual/blob/36c40d90d2fe09eb1f25a6e2f77f6dd40638b267/packages/sync-server/src/app-gocardless/app-gocardless.js#L263-L264\n\nOur bank was offline today for maintenance which threw a 503 error from Gocardless. The entire response payload was dumped to console, which includes the Bearer tokens for accessing GoCardless:\n\n```java\nSomething went wrong ServiceError: Institution service unavailable\n    at handleGoCardlessError (file:///app/src/app-gocardless/services/gocardless-service.js:59:13)\n    at Object.getTransactions (file:///app/src/app-gocardless/services/gocardless-service.js:530:7)\n    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n    at async Object.getNormalizedTransactions (file:///app/src/app-gocardless/services/gocardless-service.js:267:26)\n    at async file:///app/src/app-gocardless/app-gocardless.js:186:13 {\n  details: h [AxiosError]: Request failed with status code 503\n      at te (file:///app/node_modules/nordigen-node/dist/index.esm.js:13:914)\n      at IncomingMessage.<anonymous> (file:///app/node_modules/nordigen-node/dist/index.esm.js:17:16315)\n      at IncomingMessage.emit (node:events:529:35)\n      at endReadableNT (node:internal/streams/readable:1400:12)\n      at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {\n    code: 'ERR_BAD_RESPONSE',\n    config: {\n      transitional: {\n        silentJSONParsing: true,\n        forcedJSONParsing: true,\n        clarifyTimeoutError: false\n      },\n      adapter: [ 'xhr', 'http' ],\n      transformRequest: [ [Function (anonymous)] ],\n      transformResponse: [ [Function (anonymous)] ],\n      timeout: 0,\n      xsrfCookieName: 'XSRF-TOKEN',\n      xsrfHeaderName: 'X-XSRF-TOKEN',\n      maxContentLength: -1,\n      maxBodyLength: -1,\n      env: {\n        FormData: [Function: _] {\n          LINE_BREAK: '\\r\\n',\n          DEFAULT_CONTENT_TYPE: 'application/octet-stream'\n        },\n        Blob: [class Blob]\n      },\n      validateStatus: [Function: validateStatus],\n      headers: T [AxiosHeaders] {\n        Accept: 'application/json',\n        'Content-Type': 'application/json',\n        'User-Agent': 'Nordigen-Node-v2',\n        'Authorization': 'Bearer eyJ0eXAi... (the full token is in the response)',\n        'Accept-Encoding': 'gzip, compress, deflate, br'\n      },\n      method: 'get',\n      url: URL {\n        href: 'https://bankaccountdata.gocardless.com/api/v2/accounts/<Account id Was Here>?date_from=2024-12-22',\n        origin: 'https://bankaccountdata.gocardless.com',\n        protocol: 'https:',\n        username: '',\n        password: '',\n        host: 'bankaccountdata.gocardless.com',\n        hostname: 'bankaccountdata.gocardless.com',\n        port: '',\n        pathname: '/api/v2/accounts/<Account id Was Here>/transactions',\n        search: '?date_from=2024-12-22',\n        searchParams: URLSearchParams { 'date_from' => '2024-12-22' },\n        hash: ''\n      },\n      data: undefined\n    },\n```\nAnd quite a few pages more.\n\n### PoC\n- Setup an Actualbudget server inside of Docker. In this instance I was using the Docker Compose script posted in the repository: https://github.com/actualbudget/actual/blob/master/packages/sync-server/docker-compose.yml\n- Link a gocardless account to Actualbudget and sync a bank account\n- Observe in the container using `docker logs actual-actual_server-1 -f`  that sensitive details are logged to the console and ingested by docker. \n\n### Impact\nInformation disclosure. The services are available both on-premises and in environments that are not under the control of the end user, such as third-party providers who offer this application as a managed solution.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:L/AC:L/PR:H/UI:R/S:U/C:H/I:N/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "npm",
      "name" : "@actual-app/sync-server"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "25.11.0"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 25.10.0"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/actualbudget/actual/security/advisories/GHSA-xvp7-8vm8-xfxx"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/actualbudget/actual/commit/97482a082d502887ef22514b93e35e4c67f4f30f"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/actualbudget/actual"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/actualbudget/actual/blob/36c40d90d2fe09eb1f25a6e2f77f6dd40638b267/packages/sync-server/src/app-gocardless/app-gocardless.js#L263-L264"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/actualbudget/actual/blob/36c40d90d2fe09eb1f25a6e2f77f6dd40638b267/packages/sync-server/src/app-gocardless/banks/integration-bank.js#L25-L27"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/actualbudget/actual/blob/36c40d90d2fe09eb1f25a6e2f77f6dd40638b267/packages/sync-server/src/app-gocardless/banks/integration-bank.js#L83-L85"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-209", "CWE-215", "CWE-219" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2025-10-20T17:55:59Z",
    "nvd_published_at" : null
  }
}