GHSA-xvp7-8vm8-xfxx Actual Sync-server Gocardless service is logging sensitive data including bearer tokens and account numbers

Not scored Published

The Actual Budget sync server logs sensitive banking data, including bearer tokens and account numbers, to standard output, exposing PII and financial details.

Exploited in the wild
Not known
Login needed
Not needed
Attackable
Over the internet
Victim action needed
Not needed
Fix
Available

What is GHSA-xvp7-8vm8-xfxx?

GHSA-xvp7-8vm8-xfxx is a vulnerability in @actual-app/sync-server, published on 20 Oct 2025. An attacker can exploit it over the internet without logging in, with no action from the victim.

Official description

Summary

The GoCardless components in Actualbudget in are logging responses to STDOUT in a parsed format using console.logand 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):

{
  "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:

{
  "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:

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

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.

Which versions are affected by GHSA-xvp7-8vm8-xfxx?

2 open source packages ship an affected version, including @actual-app/sync-server.

PackageAffectedFixed in
@actual-app/sync-server npmAll versions25.11.0
@actual-app/sync-server npmAll versions25.11.0

How do I fix GHSA-xvp7-8vm8-xfxx?

Upgrade @actual-app/sync-server to 25.11.0 or later.

Is GHSA-xvp7-8vm8-xfxx being exploited?

There is no known exploitation of GHSA-xvp7-8vm8-xfxx in the wild and no public exploit code.

Sources

Is GHSA-xvp7-8vm8-xfxx in your software?

Upload an SBOM and sbomify checks it against every vulnerability here, every day.

Check your SBOMs for free