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-65599

CVE-2026-65599: Google Service Account Private Key Leakage via JWT Header Parameter in n8n

Alon Barad
Alon Barad
Software Engineer

Jul 22, 2026·7 min read·30 visits

Executive Summary (TL;DR)

n8n leaked Google Service Account private keys inside the unencrypted 'kid' parameter of outbound JWT headers, permitting complete Google Cloud Platform resource compromise upon network or log exposure.

A credential exposure vulnerability in n8n (CVE-2026-65599) transmits the complete PEM-formatted Google Service Account private key in the 'kid' (Key ID) parameter of outbound JWT headers during Google API authentication. Because JWT headers are encoded in plain Base64URL and not encrypted, any entity that intercepts, logs, or processes these outbound requests can immediately extract the plaintext private key. This enables unauthorized third parties to fully compromise the corresponding Google Cloud Platform (GCP) service account and access any authorized cloud resources.

Vulnerability Overview

The workflow automation platform n8n enables users to design multi-step data integration tasks involving third-party APIs. To interact with Google Cloud Platform (GCP) resources or Google Workspace services, workflows often leverage Google Service Account credentials. These credentials typically rely on a JSON-formatted configuration payload containing metadata, a unique Key ID, and an RSA-2048 private key in PEM format.

When authenticating against Google OAuth endpoints, the application must construct and sign a JSON Web Token (JWT) to obtain an access token. In standard cryptographic protocol design, the JWT header includes a Key ID (kid) parameter, which is a public label helping the verifying system locate the correct public certificate. In affected versions of n8n, a structural design error caused the platform to transmit the entire secret PEM-formatted private key inside this unencrypted header parameter.

Because the JWT header is merely Base64URL-encoded and transmitted as part of the Authorization header in outbound HTTP requests, this behavior violates fundamental security principles associated with cleartext transmission of credentials (CWE-312). The resulting attack surface exposes highly sensitive cloud-infrastructure credentials to intermediate network equipment, internal application logs, corporate HTTP proxies, and monitoring systems.

Root Cause Analysis

To authenticate a Google Service Account, the client application must generate a JWT containing standard OAuth claims (such as the issuer, requested scopes, target audience, and expiration times) and sign it using the service account's private key. The specification for JSON Web Signature (JWS) defines the kid header parameter as a hint indicating which key was used to secure the payload. It is mathematically designed to hold a non-sensitive cryptographic fingerprint, such as a hash or public key ID.

In the affected versions of n8n, the logic responsible for compiling the JWS headers assigned the value of the private_key field from the user's Google Service Account credentials directly to the kid parameter. This mistake caused the application to generate JWS headers similar to the following structured example:

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDhv8g6xU...\n-----END PRIVATE KEY-----\n"
}

When n8n encodes this structure using the standard RFC 7515 Base64URL specification, the plaintext PEM key remains unencrypted. Since the application transmits the resulting serialized JWT directly to the Google OAuth endpoint (https://oauth2.googleapis.com/token) in cleartext form over SSL/TLS, the transport layer security only protects the secret in transit. Any component that has visibility into the application layers of the client or the intermediate gateways will capture the full private key.

Code-Level Flow & Patch Analysis

The vulnerability stems from improper structural mapping during JWT compilation. The following pseudo-code contrasts the vulnerable implementation against the patched implementation introduced in fixed releases:

// VULNERABLE: Direct assignment of the sensitive PEM private key to the JWT 'kid' header field
import * as jwt from 'jsonwebtoken';
 
function generateGoogleJwtVulnerable(credentials: GoogleServiceAccountCreds) {
  const payload = { ... };
  const options: jwt.SignOptions = {
    algorithm: 'RS256',
    header: {
      kid: credentials.privateKey, // SEVERE ERROR: Private key placed in public-facing header
    }
  };
 
  return jwt.sign(payload, credentials.privateKey, options);
}

To correct this exposure, n8n developers updated the JWT construction sequence to map the kid parameter to the unique, non-sensitive public key identifier string (private_key_id) from the Google Cloud credential JSON, as illustrated below:

// PATCHED: Assigning the non-sensitive public key identifier to 'kid'
import * as jwt from 'jsonwebtoken';
 
function generateGoogleJwtPatched(credentials: GoogleServiceAccountCreds) {
  const payload = { ... };
  const options: jwt.SignOptions = {
    algorithm: 'RS256',
    header: {
      kid: credentials.privateKeyId, // FIXED: Correctly uses non-sensitive Key ID
    }
  };
 
  return jwt.sign(payload, credentials.privateKey, options);
}

This structural alteration completely resolves the leak. While the private key is still utilized to sign the JWT, it is strictly kept in memory on the n8n application host and is never written into the serialized header string transmitted over the network.

Exploitation Methodology

Exploitation of CVE-2026-65599 does not require an active exploit payload or complex memory corruption techniques. It relies entirely on passive or active interception of outbound API traffic. An attacker must position themselves to observe either the outbound network request or the application logs generated by the n8n instance.

First, an administrative user or workflow creator must configure a Google Service Account in n8n and execute a workflow that utilizes Google node integrations. Once executed, the application generates the outbound HTTP request. If the organization uses internal HTTP logging, debugging proxies (such as mitmproxy or Fiddler), or security monitoring solutions that record outbound HTTP payloads, the complete JWT header is recorded in plain text.

Once an adversary extracts the JWT from a captured request or system log, extraction of the credential requires only simple Base64URL decoding of the first dot-separated segment:

# Extract the JWS Header (the first dot-separated block)
JWT_TOKEN="eyJhbGciOiJSUzI1NiIsImtpZCI6Ii0tLS0tQkVHSU4gUFJJVkFURSBLRVktLS0tLVxuTUlJRXZnS..."
HEADER_B64=$(echo "$JWT_TOKEN" | cut -d'.' -f1)
 
# Decode and extract the plaintext PEM-formatted Private Key
echo "$HEADER_B64" | tr '_-' '/+' | openssl base64 -d | jq -r '.kid'

The resulting output yields the fully functional, plaintext -----BEGIN PRIVATE KEY----- block, allowing the attacker to construct their own authentication tokens to gain unauthorized access to Google Cloud resources.

Impact Assessment & Threat Analysis

Although the CVSS v4.0 score is designated as 5.1 (Medium) because creating or configuring workflows in n8n typically requires administrative access (PR:H), the downstream impact to the organization's cloud environment is critical. The compromised credential provides full programmatic access under the identity of the targeted Google Service Account.

If the compromised Service Account holds expansive administrative privileges, such as Project Owner, Editor, or specific IAM roles (such as Storage Admin or BigQuery Admin), the attacker can gain full read and write access to enterprise cloud assets. This can lead to database exfiltration, modification of infrastructure-as-code configurations, or deployment of rogue compute instances for crypto-mining or lateral network movement.

Because the key is leaked via normal runtime API client operations, it is highly likely that the credential has been written to local or centralized SIEM logs, intermediate proxy history, or performance monitoring databases. This legacy log footprint means that patching the n8n software alone is insufficient to mitigate the risk; the exposed keys remain active on GCP until manually revoked.

Remediation & Detection Strategies

Remediation of CVE-2026-65599 requires a two-phased approach consisting of software updates to eliminate the programmatic leak and credential rotation to address historical exposure.

First, n8n instances must be upgraded to one of the officially patched versions: 1.123.64, 2.29.8, or 2.30.1. These versions correctly populate the kid parameter with the non-sensitive public Key ID, ensuring that the private key is never transmitted.

Second, administrators must immediately perform Google Service Account key rotation. Because exposed keys may already exist in proxy or application logs, the following actions must be taken in the Google Cloud Console:

  1. Navigate to the IAM & Admin console, select Service Accounts, and identify the affected account.
  2. Click on the Keys tab, locate the older active keys associated with the n8n deployment, and select Delete to revoke them.
  3. Create a New Key (JSON format) and upload the updated configuration file into the patched n8n instance.

To detect historical exploitation, security teams should inspect historical web proxy and application logs for JWT header payloads containing the signature substring -----BEGIN PRIVATE KEY----- or its Base64-encoded equivalents.

Official Patches

n8n-ion8n Version 1.123.64 Release Notes
n8n-ion8n Version 2.29.8 Release Notes
n8n-ion8n Version 2.30.1 Release Notes

Technical Appendix

CVSS Score
5.1/ 10
CVSS:4.0/AV:N/AC:L/AT:P/PR:H/UI:N/VC:L/VI:N/VA:N/SC:H/SI:L/SA:L

Affected Systems

n8n deployments running versions prior to 1.123.64n8n deployments running versions prior to 2.29.8n8n deployments running versions prior to 2.30.1

Affected Versions Detail

Product
Affected Versions
Fixed Version
n8n
n8n-io
< 1.123.641.123.64
n8n
n8n-io
< 2.29.82.29.8
n8n
n8n-io
< 2.30.12.30.1
AttributeDetail
Vulnerability IDCVE-2026-65599
CWE IDCWE-312
Attack VectorNetwork (AV:N)
CVSS v4.0 Score5.1 (Medium)
CVSS VectorCVSS:4.0/AV:N/AC:L/AT:P/PR:H/UI:N/VC:L/VI:N/VA:N/SC:H/SI:L/SA:L
Exploit Statusnone
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1552Unsecured Credentials
Credential Access
CWE-312
Cleartext Storage of Sensitive Information

The application stores or transmits sensitive information (the private key) in cleartext or in a format (Base64) that is easily reversible without a secret key.

Vulnerability Timeline

NVD CVE Published & GitHub Advisory GHSA-9r8p-h6cc-6qhm Disclosed
2026-07-22
VulnCheck Advisory Published
2026-07-22

References & Sources

  • [1]n8n GHSA Security Advisory
  • [2]VulnCheck Vulnerability Advisory

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•2 days ago•CVE-2026-107844
5.3

CVE-2026-107844: Path Traversal Vulnerability in Contao ImagesController

A path traversal vulnerability (CWE-22) in Contao CMS allows unauthenticated remote attackers to bypass directory boundary restrictions in ImagesController and access files within the project directory.

Amit Schendel
Amit Schendel
8 views•5 min read
•2 days ago•CVE-2026-107848
3.5

CVE-2026-107848: Cross-Site Request Forgery (CSRF) in Contao Backend Actions via GET Requests

Contao Open Source CMS versions 4.0.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 contain a Cross-Site Request Forgery (CSRF) vulnerability in backend parameter handling. The `RequestTokenListener` component validates anti-CSRF tokens solely for HTTP POST requests, while GET-based declarative guards run only when an `act` parameter is present in the query string. Consequently, custom backend actions dispatched via alternative parameters such as `key=` can execute without CSRF token verification when triggered by an authenticated user.

Amit Schendel
Amit Schendel
8 views•5 min read
•2 days ago•CVE-2026-107843
5.3

CVE-2026-107843: Unthrottled Activation Email Resend and Account Enumeration in Contao CMS

Contao CMS versions 4.1.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 fail to validate form submission tokens and enforce rate limiting when processing activation email resend requests via HTTP POST, enabling resource exhaustion and account state enumeration.

Amit Schendel
Amit Schendel
9 views•4 min read
•2 days ago•CVE-2026-107842
5.3

CVE-2026-107842: Information Disclosure via Stale Indexing in Contao Search Module

An information disclosure vulnerability in Contao CMS allows unauthenticated site visitors to view protected page titles, URLs, and text excerpts through search queries when protected page indexing is disabled after previously being enabled.

Amit Schendel
Amit Schendel
10 views•4 min read
•2 days ago•GHSA-G38J-7V97-X298
6.5

GHSA-G38J-7V97-X298: Missing Authorization Check in Vikunja CalDAV Task Relation Creation

In Vikunja prior to version 2.6.0, relation creation via the CalDAV endpoint fails to invoke the TaskRelation.CanCreate authorization check. This missing access control allows an authenticated user to establish unauthorized relationships and perform write operations against any task, provided its unique identifier (UID) is known.

Alon Barad
Alon Barad
12 views•5 min read
•2 days ago•GHSA-3HC7-R24J-RPWC
6.8

GHSA-3hc7-r24j-rpwc: Cross-Project Task Disclosure via Subtask Expansion in Vikunja

A cross-project information disclosure vulnerability in Vikunja allows authenticated users with read access to one project to view private task details from unauthorized projects via subtask expansion parameters.

Alon Barad
Alon Barad
9 views•5 min read