Home/ Blog/ Security news/ Article
Blog · Security news

Puppet stored the passwords it was told to hide in cleartext on every managed node

CVE-2026-8804: Puppet's Resource API stopped honoring the sensitive flag, writing passwords in cleartext to each agent's state cache. Upgrade, then rotate.

Grid of frosted glass panels on a dark wall, several turned fully transparent

The whole point of marking a parameter sensitive in Puppet is that Puppet keeps the value out of its logs, reports, and saved state. On affected versions, that promise quietly broke. Passwords and other secrets pushed through the Resource API, the framework module authors use to build custom resource types, were written in the clear into the state record Puppet saves on every managed node's local disk. The flaw is CVE-2026-8804, disclosed on July 3, 2026 by Perforce, which owns Puppet.

It carries a CVSS 4.0 score of 6.7 (medium), and no exploitation or public proof-of-concept has been reported. That label describes how hard the data is to reach, not how many places the secret ended up. Read it as an at-rest exposure problem rather than a remote-takeover bug, and the priority gets clearer.

What broke: Puppet stopped masking the secrets it was told to hide

Puppet lets a module tag a parameter as sensitive so the value never shows up in cleartext in logs, reports, or saved run data. The Resource API is the modern way to author custom resource types, and on the affected releases it dropped that tag. A value the module meant to protect, a database password, an API token, a service credential, then landed in plaintext inside the state record each agent writes to local disk after a run, rather than being masked. Puppet files this under two weakness classes, CWE-312 and CWE-313, for keeping a secret unencrypted on disk.

The exposure sits on the node, not the primary server. Every machine running an affected agent that applied such a type now holds the plaintext value in its state cache. Per the CVSS vector, reading it costs an attacker local access with high privileges (AV:L, PR:H), which is why the score lands at medium. But the entire value of a masking control is that it shrinks where a secret can be found. When it silently fails, the opposite happens: the secret spreads to node backups, golden images, and any log or forensic collection that sweeps up the state directory. A masking control that fails quietly is worse than none, because teams built their secret handling on the assumption that it worked.

Which versions are affected

The bug lives in the Puppet resource_api module versions 1.5.0 through 1.9.1 and version 2.0.0. It shipped inside Puppet Core 8.0.0 through 8.19.0, and Puppet Enterprise 2023.8.0 through 2023.8.9 and 2025.0.0 through 2025.10.0. It is fixed in resource_api 1.9.2 and 2.0.1, which ship with Puppet Core 8.20.0, Puppet Enterprise 2023.8.10, and Puppet Enterprise 2025.11.0.

ComponentAffectedFixed in
Puppet resource_api module1.5.0 - 1.9.1 and 2.0.01.9.2 and 2.0.1
Puppet Core8.0.0 - 8.19.08.20.0
Puppet Enterprise 2023.82023.8.0 - 2023.8.92023.8.10
Puppet Enterprise 20252025.0.0 - 2025.10.02025.11.0
Affected and fixed versions for CVE-2026-8804. Source: Perforce/Puppet advisory and the CVE record.

Patch is step one. Rotating the exposed secrets is step two.

Upgrading closes the leak going forward: fixed agents stop writing sensitive values in cleartext. It does nothing about the values already sitting in state caches across your fleet, and it cannot un-expose a credential that has already been copied off a node in a backup or an image. Treat this as a secret-exposure incident scoped to the window an affected version was running, not a patch-and-forget CVE. We made the same argument when Gravity SMTP leaked live email API keys: the fix stops new exposure, but a secret that has already leaked stays compromised until you rotate it. Concretely:

  1. Upgrade to a fixed release: resource_api 1.9.2 or 2.0.1, or the Puppet Core / Enterprise version that bundles it (8.20.0, 2023.8.10, or 2025.11.0).
  2. Inventory your exposure. You are affected only if you run custom types built on the Resource API that define sensitive parameters. If you do not write or use such types, the plaintext-in-state problem does not apply to you.
  3. Find the state directory on each node with puppet config print statedir, then clear the stale transaction state cache so the plaintext values are not left behind after the upgrade.
  4. Rotate every credential that flowed through a sensitive Resource API parameter while an affected version ran. Assume it was exposed at rest, because it was.
  5. Check the blast radius beyond live nodes: backups, snapshots, and golden images taken during the affected window carry the same plaintext and need the same rotation decision.

The severity math is honest, but it hides the operational point. This is not a bug an attacker fires across the internet. It is a control you relied on that stopped working, on every node you manage, without an error. The patch is easy. Knowing which secrets to rotate is the actual work, and only you can scope it.

Frequently asked questions

What is CVE-2026-8804?

CVE-2026-8804 is a cleartext-storage flaw in Puppet's Resource API. In affected versions it fails to preserve the sensitive flag on parameters, so values like passwords are written in plaintext to the Puppet agent's local transaction state cache on each managed node.

Which Puppet versions are affected and where is the fix?

It affects the resource_api module 1.5.0 to 1.9.1 and 2.0.0, shipped in Puppet Core 8.0.0 to 8.19.0 and Puppet Enterprise 2023.8.0 to 2023.8.9 and 2025.0.0 to 2025.10.0. Fixes ship in resource_api 1.9.2 and 2.0.1, Puppet Core 8.20.0, PE 2023.8.10, and PE 2025.11.0.

Is CVE-2026-8804 being exploited?

No public exploit or in-the-wild exploitation has been reported as of disclosure on July 3, 2026. The CVSS 4.0 score is 6.7 (medium) because reading the cached secrets requires local access with high privileges on the affected node.

Is upgrading Puppet enough to fix it?

No. Upgrading stops the agent from writing new secrets in cleartext, but it does not remove secrets already cached on disk, in backups, or in node images. Rotate any credential handled by a sensitive Resource API parameter while an affected version ran.

How do I find the Puppet state cache on a node?

Run puppet config print statedir on the node to print the agent's state directory. That directory holds the transaction state cache where the affected versions wrote sensitive values in cleartext, and it is what to clean after upgrading.

Ready to meet the Guardians?

Deploys fast - agentless for monitoring and cloud, a lightweight agent for deep endpoint security. Just Suriq, standing watch.