Skip to content

Gocardless service is logging sensitive data including bearer tokens, account numbers, etc...

Moderate
MatissJanis published GHSA-xvp7-8vm8-xfxx Oct 18, 2025

Package

gocardless (Actual Server)

Affected versions

<= 25.10.0

Patched versions

>= 25.11.0

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:

console.debug(
'Available account properties for new institution integration',
{ account: JSON.stringify(account) },

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": []
    }
  }
}

console.debug(
'Available (first 10) transactions properties for new integration of institution in sortTransactions function',
{ top10Transactions: JSON.stringify(transactions.slice(0, 10)) },

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.

default:
console.log('Something went wrong', inspect(error, { depth: null }));

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.

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Local
Attack complexity
Low
Privileges required
High
User interaction
Required
Scope
Unchanged
Confidentiality
High
Integrity
None
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:L/AC:L/PR:H/UI:R/S:U/C:H/I:N/A:N

CVE ID

No known CVE

Weaknesses

Generation of Error Message Containing Sensitive Information

The product generates an error message that includes sensitive information about its environment, users, or associated data. Learn more on MITRE.

Insertion of Sensitive Information Into Debugging Code

The product inserts sensitive information into debugging code, which could expose this information if the debugging code is not disabled in production. Learn more on MITRE.

Credits