CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Dashboard
  • 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-27465
4.30.05%

Fleet's Open Secret: The Google Calendar Key Leak

Alon Barad
Alon Barad
Software Engineer

Feb 26, 2026·7 min read·12 visits

No Known Exploit

Executive Summary (TL;DR)

Fleet versions prior to 4.80.1 return unmasked Google Service Account credentials in the global configuration API. Authenticated users, even those with the restricted 'Observer' role, can retrieve the full private key, allowing them to impersonate the service account in Google Cloud.

A deep dive into CVE-2026-27465, where Fleet Device Management inadvertently exposed Google Calendar Service Account private keys to low-privileged users via the application configuration API. This vulnerability highlights the dangers of implicit serialization in Go and the risks of treating configuration data as a 'catch-all' bucket.

The Hook: Who's Watching the Observers?

Fleet (formerly FleetDM) is the heavy hitter in the open-source device management world. It wraps osquery in a nice enterprise UI, effectively acting as the 'Control Plane' for your entire endpoint infrastructure. When you compromise the control plane, you usually win the game. But today, we aren't looking at a complex RCE or a SQL injection. We are looking at a classic case of 'oversharing'.

In most enterprise RBAC (Role-Based Access Control) models, there is a role usually called 'Observer' or 'Auditor'. The assumption is simple: these users can look, but they can't touch. They are the digital window shoppers of your infrastructure. Security teams often hand these roles out like candy to managers or compliance auditors because, theoretically, they can't break anything.

But what if looking is breaking? CVE-2026-27465 is a logic flaw that turns these passive observers into active threats. By simply asking the Fleet API for the current configuration, an observer gets more than just settings—they get the keys to the kingdom. Specifically, the Google Calendar Service Account private keys used for integrations. It's akin to a bank letting you look at the vault, but also accidentally leaving the combination written on a sticky note on the door.

The Flaw: The Perils of Go Serialization

To understand this bug, you have to understand how Go (Golang) handles JSON serialization. Go is a typed, compiled language that prides itself on simplicity. When you want to turn a struct into JSON, you usually use json.Marshal. This function looks at your struct tags and, unless you explicitly tell it not to, it converts everything it sees into a JSON string.

In Fleet, there is an AppConfig struct. This massive object holds the global configuration for the instance. It includes mundane things like the server URL or the organization name. However, it also includes an Integrations field. Inside that field lived the GoogleCalendar configuration.

When an administrator sets up the Google Calendar integration, they upload a Google Service Account JSON blob. This blob contains the private_key, client_email, and other sensitive metadata. The flaw was fundamentally lazy data modeling. The API endpoint /api/v1/fleet/config was designed to return the application configuration to the frontend so the UI knows how to behave. However, the backend blindly serialized the entire integration map, including the secrets, without masking them first.

This is a textbook CWE-201 (Insertion of Sensitive Information Into Sent Data). The developers likely assumed that since the endpoint requires authentication, it was 'safe enough'. But they forgot the cardinal rule of API design: Frontend clients should only receive data they actually need to render the UI. The frontend needs to know if the integration is active; it does not need the private key to do its job.

The Code: Explicit vs. Implicit Trust

Let's look at the fix to understand the breakage. The vulnerability existed because the GoogleCalendar integration was likely just a generic map or struct that got marshaled directly. The fix, introduced in commit 23fc6804, forces the code to acknowledge the sensitivity of the data.

The developers introduced a new type, GoogleCalendarApiKey, with a custom MarshalJSON method. This is the 'Go way' of handling secrets during serialization.

// The new struct wrapper
type GoogleCalendarApiKey struct {
    Values map[string]string
    masked bool
}
 
// Custom Marshaler - The Gatekeeper
func (k GoogleCalendarApiKey) MarshalJSON() ([]byte, error) {
    // If the masked flag is true, return stars instead of the key
    if k.masked {
        return json.Marshal("********")
    }
    // Otherwise, return the raw values (for internal use)
    return json.Marshal(k.Values)
}

They also updated the AppConfig.Obfuscate() method. This method is called specifically before sending data out to the API response writer. It iterates through the integrations and flips the masked bit to true.

// server/fleet/integrations.go
for _, gcIntegration := range c.Integrations.GoogleCalendar {
    // This sets the internal bool, triggering the "********" return above
    gcIntegration.ApiKey.SetMasked()
}

Before this patch, the Obfuscate method simply didn't touch the Google Calendar integration, so json.Marshal did what it was told: it dumped the raw private key in cleartext.

The Exploit: Grab and Go

Exploiting this is trivially easy if you have a foothold. You don't need memory corruption; you just need curl and a valid session token.

The Attack Chain:

  1. Access: Obtain credentials for a Fleet user. This could be a legitimate "Observer" account you've compromised via phishing, or perhaps you are a rogue insider.
  2. Request: Query the config endpoint.
  3. Extraction: Parse the JSON response for the private_key.

Here is a visual representation of the flow:

Nuclei Detection Template:

If you are hunting for this in your own environment (internally, of course), the detection logic is simple. You authenticate, hit the endpoint, and look for the specific private key header.

id: fleet-google-calendar-leak
requests:
  - method: GET
    path:
      - "{{BaseURL}}/api/v1/fleet/config"
    matchers:
      - type: regex
        part: body
        regex:
          - "-----BEGIN PRIVATE KEY-----"

Once the attacker has the key, they are no longer bound by Fleet's RBAC. They are now an authenticated Google Cloud Service Account. Depending on the IAM permissions granted to that service account (often overly permissive "Editor" roles), they could access calendars, drive files, or even spin up resources.

The Impact: Persistent Access

Why is this a big deal? Because Service Account keys don't rotate automatically. Unlike a user session cookie that expires in 24 hours, a Google Service Account key is valid until someone explicitly deletes it.

An attacker who dumps this config today can come back in six months and use that key, provided the administrator hasn't rotated it. The access allows the attacker to bypass Fleet entirely and interact directly with Google APIs.

Furthermore, because this integration is for Google Calendar, the immediate impact often involves corporate espionage. Attackers can read meeting invites, see who is meeting with whom (M&A activity?), and find Zoom links. In a worst-case scenario where the Service Account was created with Owner privileges on the GCP project (a common mistake by lazy sysadmins), this is a full cloud environment compromise.

The Fix: Rotate, Don't Just Patch

If you are running Fleet, you need to upgrade to v4.80.1 immediately. This stops the bleeding by ensuring the API no longer returns the key.

HOWEVER—and this is critical—patching the code does not fix the breach.

If you ever ran a vulnerable version with a Google Calendar integration configured, you must assume that key is compromised. The patch only hides the key from future requests. It does not invalidate the key that was already exposed.

Remediation Steps:

  1. Patch: Upgrade Fleet to >= 4.80.1.
  2. Revoke: Go to the Google Cloud Console > IAM & Admin > Service Accounts.
  3. Rotate: Create a new key for the service account and upload it to Fleet.
  4. Delete: Delete the old key immediately.

Do not skip the rotation step. If you do, you are locking the front door while the burglar is already sitting on your couch.

Official Patches

FleetFleet v4.80.1 Release Notes

Fix Analysis (1)

Technical Appendix

CVSS Score
4.3/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
EPSS Probability
0.05%
Top 85% most exploited

Affected Systems

Fleet Device Management (fleetdm) < 4.80.1

Affected Versions Detail

Product
Affected Versions
Fixed Version
Fleet
Fleet Device Management
< 4.80.14.80.1
AttributeDetail
CWECWE-201 (Insertion of Sensitive Information Into Sent Data)
CVSS v3.14.3 (Medium)
Attack VectorNetwork (Authenticated)
Privileges RequiredLow (Observer)
ImpactInformation Disclosure (High Confidentiality)
Fixed Version4.80.1

MITRE ATT&CK Mapping

T1552.001Unsecured Credentials: Private Keys
Credential Access
T1078Valid Accounts
Defense Evasion
CWE-201
Insertion of Sensitive Information Into Sent Data

Insertion of Sensitive Information Into Sent Data

Known Exploits & Detection

InternalStandard API request (GET /api/v1/fleet/config) by authenticated user returns plain text credentials.
NucleiDetection Template Available

Vulnerability Timeline

Fix committed to main branch
2026-01-26
Fleet v4.80.1 released
2026-02-26
CVE-2026-27465 Published
2026-02-26

References & Sources

  • [1]GHSA-2v6m-6xw3-6467

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.