Spring Cloud Config CVE-2026-40981: Brief Summary of Cross Project Secret Exposure via GCP Secret Manager Backend

A brief summary of CVE-2026-40981, a high severity authorization bypass in Spring Cloud Config's Google Secret Manager backend that allows unauthenticated clients to retrieve secrets from unintended GCP projects. Includes patch analysis and affected version details.

CVE Analysis

8 min read

ZeroPath CVE Analysis
ZeroPath CVE Analysis

2026-05-06

Spring Cloud Config CVE-2026-40981: Brief Summary of Cross Project Secret Exposure via GCP Secret Manager Backend
Experimental AI-Generated Content

This CVE analysis is an experimental publication that is completely AI-generated. The content may contain errors or inaccuracies and is subject to change as more information becomes available. We are continuously refining our process.

If you have feedback, questions, or notice any errors, please reach out to us.

[email protected]

Introduction

A crafted HTTP request to a Spring Cloud Config Server backed by Google Secrets Manager can silently return secrets from GCP projects the caller was never intended to access. For any organization relying on Spring Cloud Config to distribute application secrets across microservices, CVE-2026-40981 represents a direct path from an unauthenticated network position to reading credentials stored in arbitrary GCP projects, limited only by the breadth of the Config Server's own service account permissions.

Spring Cloud Config is a central component in the Spring ecosystem for externalized configuration management. It is widely deployed in Java enterprise environments and cloud native architectures to serve configuration properties, including secrets, to distributed applications at scale.

Technical Information

Root Cause: Unvalidated Client Controlled Project ID

The vulnerability exists in the GoogleSecretManagerV1AccessStrategy class, which handles secret retrieval from GCP Secret Manager on behalf of Config Server clients. Prior to the fix, when a Config Client sent an X-Project-ID HTTP header to the Config Server, the getProjectId() method accepted the header value without any validation or authorization check:

// OLD (vulnerable) — blindly accepted header result = configProvider.getValue(HttpHeaderGoogleConfigProvider.PROJECT_ID_HEADER, true);

This is a textbook instance of CWE-639: Authorization Bypass Through User Controlled Key. The system's authorization functionality did not prevent one client from gaining access to another project's secrets by simply modifying the key value (the project ID) in the request. The authorization process failed to verify whether the requesting client had any entitlement to the specified project's secrets.

CVSS Breakdown

The CVSS v3.1 vector is AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N, scoring 7.5 (High). Breaking this down:

  • Attack Vector: Network and Privileges Required: None confirm that any unauthenticated network client can attempt exploitation.
  • Attack Complexity: Low means no special conditions or race windows are needed.
  • Confidentiality Impact: High reflects the direct exposure of sensitive secrets.
  • Integrity and Availability: None since the flaw is read only.

Attack Flow

An attacker exploiting this vulnerability would follow these steps:

  1. Identify a Spring Cloud Config Server instance that uses Google Secrets Manager as its backend. This can sometimes be inferred from error messages, response patterns, or knowledge of the target's infrastructure.
  2. Craft an HTTP request to the Config Server that includes an X-Project-ID header set to the GCP project ID of a different project. The attacker would need to know or guess valid GCP project IDs, but these are often predictable (e.g., company-production, company-staging).
  3. If the Config Server's service account has IAM permissions on the targeted GCP project (a common scenario in organizations that share service accounts or grant broad cross project access), the server retrieves and returns secrets from that unintended project.
  4. The attacker receives secrets they were never authorized to access, potentially including database credentials, API keys, encryption keys, and other sensitive configuration data.

The blast radius is bounded by the IAM permissions of the Config Server's service account. In organizations with permissive cross project IAM policies, a single Config Server could expose secrets across dozens of GCP projects.

Patch Information

The Spring team addressed CVE-2026-40981 in commit 4e93ce5, authored by Ryan Baxter on April 21, 2026, and merged into both the v5.0.3 and v4.3.3 releases on May 6, 2026. The commit is titled "Add allowed-project-ids property" and totals 391 additions and 35 deletions across seven files.

What the Patch Changes

The fix introduces a new class, GcpProjectResolutionSupport, which encapsulates and secures all project ID resolution logic. This class replaces the old inline resolution code in GoogleSecretManagerV1AccessStrategy.

The new resolution follows a strict waterfall:

  1. X-Project-ID header: If the client supplies this header and token-mandatory is true (the new default), the value is accepted because access is still gated by the downstream checkRemotePermissions() IAM check. If token-mandatory is false, the header value is checked against a new allowed-project-ids allow list. If the list is empty, all client supplied project IDs are rejected.
  2. GCE Metadata endpoint: If no header is present, the server queries the metadata server. The allow list does not apply here since this path cannot be steered by the client.
  3. project-id property fallback: A new server admin only config property serves as a last resort (e.g., for local development). This is also not subject to the allow list.
  4. If nothing resolves: getSecrets() returns an empty list and checkRemotePermissions() returns false, so no Secret Manager backed property sources are contributed for that request.

The key code change in GoogleSecretManagerV1AccessStrategy:

// NEW (fixed) — delegates to allow-list-aware resolver if (projectResolutionSupport != null) { String project = projectResolutionSupport.resolve(configProvider, rest); if (project != null) { return project; } } return null; // no GSM data for this request

The allow list enforcement inside GcpProjectResolutionSupport.resolve() for the token-mandatory=false case:

private boolean isProjectAllowed(String projectId) { List<String> allowed = properties.getAllowedProjectIds(); if (allowed == null || allowed.isEmpty()) { return false; // empty list = reject all client-supplied IDs } for (String candidate : allowed) { if (candidate != null && projectId.equals(candidate.trim())) { return true; } } return false; }

New Configuration Properties

Two new properties were added to GoogleSecretManagerEnvironmentProperties:

  • allowed-project-ids (List<String>, default empty): The explicit allow list for client supplied X-Project-ID values when token-mandatory=false.
  • project-id (String): A server side fallback project when the metadata server is unreachable.

The old constructors of GoogleSecretManagerV1AccessStrategy that did not accept GcpProjectResolutionSupport have been marked @Deprecated(forRemoval = true), and the factory class GoogleSecretManagerAccessStrategyFactory now injects GcpProjectResolutionSupport into every strategy it creates.

The commit includes comprehensive unit tests in GcpProjectResolutionSupportTests covering five scenarios: header denied when the allow list is empty, header allowed when in the list, header allowed when token-mandatory=true regardless of list, metadata fallback, configured project-id fallback, and null when no resolution is possible.

Immediate Containment

If you cannot upgrade immediately, set the following property to require client token verification, which blocks unauthorized cross project access:

spring.cloud.config.server.gcp-secret-manager.token-mandatory=true

Fixed Releases (Published May 6, 2026)

BranchFixed VersionAvailability
5.0.x5.0.3OSS
4.3.x4.3.3OSS
4.2.x4.2.7Enterprise Support Only
4.1.x4.1.10Enterprise Support Only
3.1.x3.1.14Enterprise Support Only

Older unsupported versions are also affected. Organizations on older branches must either procure enterprise support or migrate to a supported open source branch.

Affected Systems and Versions

This vulnerability affects Spring Cloud Config Server instances that use Google Secrets Manager as a backend. The following version ranges are confirmed affected:

  • Spring Cloud Config 3.1.x: versions 3.1.0 through 3.1.13 (inclusive)
  • Spring Cloud Config 4.1.x: versions 4.1.0 through 4.1.9 (inclusive)
  • Spring Cloud Config 4.2.x: versions 4.2.0 through 4.2.6 (inclusive)
  • Spring Cloud Config 4.3.x: versions 4.3.0 through 4.3.2 (inclusive)
  • Spring Cloud Config 5.0.x: versions 5.0.0 through 5.0.2 (inclusive)

The vulnerable configuration specifically requires:

  • Spring Cloud Config Server deployed with Google Secrets Manager as the configuration backend
  • The Config Server's GCP service account having IAM access to more than one GCP project
  • Network accessibility to the Config Server endpoint

Older, unsupported versions of Spring Cloud Config are also affected but will not receive patches.

References

Detect & fix
what others miss

Security magnifying glass visualization