CVE-2026-8804
Executive Summary
CVE-2026-8804 is a vulnerability in Puppet’s resource_api module (shipped with Puppet Core 8.x and Puppet Enterprise 2023.8.x/2025.x) that fails to preserve the sensitive flag on parameters defined via the Resource API. This causes values such as passwords, secret keys, and tokens to be stored in cleartext in the agent’s local transaction state cache (state.yaml). An attacker with local access to a Puppet agent node can read this cache and extract sensitive credentials.
The vulnerability affects all versions of the resource_api module from 1.5.0 through 1.9.1, and version 2.0.0. The fix was released in resource_api 1.9.2 and 2.0.1, which are included in Puppet Core 8.20.0, Puppet Enterprise 2023.8.10, and Puppet Enterprise 2025.11.0.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability is in the Puppet ecosystem, specifically the resource_api Ruby gem. Puppet is a configuration management tool widely used in enterprise environments. The flaw exists in the core agent software, meaning any Puppet-managed node running an affected version is at risk. The supply chain risk is high because Puppet agents are typically deployed across hundreds or thousands of servers, and the sensitive data exposed (passwords, API keys) can lead to lateral movement and privilege escalation.
CVSS Breakdown & Threat Level
CVSS Vector: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
- Attack Vector (AV): Local (L) – The attacker must have local access to the Puppet agent node.
- Attack Complexity (AC): Low (L) – No special conditions are required; the cache file is readable by the puppet user.
- Privileges Required (PR): Low (L) – The attacker needs a low-privileged account on the node (e.g., the
puppetuser or any user who can read the cache). - User Interaction (UI): None (N) – No user action is required.
- Scope (S): Unchanged (U) – The vulnerability does not cross trust boundaries.
- Confidentiality (C): High (H) – Sensitive credentials are exposed in cleartext.
- Integrity (I): None (N) – No data integrity impact.
- Availability (A): None (N) – No availability impact.
Base Score: 5.5 (Medium)
Threat Level: Medium. While the CVSS score is moderate, the real-world impact is significant because Puppet agents often run on critical infrastructure, and exposed credentials can be used for lateral movement.
Deep Dive & Mechanics
The Puppet Resource API allows module authors to define custom resource types with parameters that can be marked as sensitive (e.g., String, sensitive: true). When a resource is applied, Puppet stores the transaction state in a local cache file (state.yaml) on the agent. The vulnerability arises because the resource_api module does not propagate the sensitive flag to the state cache. Instead, the value is stored as a plain string.
Root Cause: In the resource_api code, when serializing resource parameters for the state cache, the sensitive metadata is ignored. The code uses a generic to_s or inspect method that does not mask or omit sensitive values.
Attack Scenario:
- An administrator defines a Puppet resource (e.g.,
mysql_user) with a sensitive password parameter. - The Puppet agent applies the catalog and writes the transaction state to
/opt/puppetlabs/puppet/cache/state/state.yaml. - An attacker with local access (e.g., via a compromised low-privileged account) reads the
state.yamlfile. - The attacker extracts the cleartext password and uses it to access the MySQL database or other services.
Vulnerable vs. Patched Code
Vulnerable Code (resource_api 1.9.1):
# In resource_api/transport.rb or similar
def state_hash(resource)
resource.to_hash # This does not preserve sensitive flag
end
Patched Code (resource_api 1.9.2):
# In resource_api/transport.rb
def state_hash(resource)
hash = resource.to_hash
# Mask sensitive parameters
resource.class.attributes.each do |attr_name, attr|
if attr[:sensitive]
hash[attr_name] = '***' # or use Puppet::Pops::Types::PSensitiveType
end
end
hash
end
The patch explicitly checks each attribute for the sensitive flag and replaces the value with a placeholder (***) before writing to the state cache.
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- Local access to a Puppet agent node running an affected version.
- The
puppetuser or a user with read access to the Puppet cache directory.
Steps:
- Identify the state cache file:
ls -la /opt/puppetlabs/puppet/cache/state/state.yaml - Read the file:
cat /opt/puppetlabs/puppet/cache/state/state.yaml - Search for sensitive parameters (e.g.,
password,secret,token):grep -E '(password|secret|token|api_key)' /opt/puppetlabs/puppet/cache/state/state.yaml - Extract the cleartext values and use them for lateral movement.
Example Output:
---
mysql_user:
- name: 'app_user'
password: 'SuperSecretP@ssw0rd!' # Cleartext!
ensure: 'present'
Blue Team (Detection & Forensics)
Detection:
- Monitor file access to
/opt/puppetlabs/puppet/cache/state/state.yamlby non-puppet processes. - Alert on
greporcatcommands targeting the state cache. - Use file integrity monitoring (FIM) to detect unauthorized reads.
Forensics:
- Check the
state.yamlfile for cleartext sensitive values. - Review audit logs for access to the cache directory.
- Identify which Puppet resources are exposing sensitive data.
Indicators of Compromise (IOCs)
- File Path:
/opt/puppetlabs/puppet/cache/state/state.yaml - File Content: Presence of cleartext passwords, secrets, or tokens in the YAML file.
- Process: Unauthorized
cat,grep, orlesscommands on the state cache file. - Network: Lateral movement using credentials extracted from the cache.
Detection Engineering
YARA Rule
rule CVE_2026_8804_Puppet_Sensitive_Data_Exposure {
meta:
description = "Detects cleartext sensitive data in Puppet state cache"
author = "Valters IT"
date = "2026-01-01"
reference = "CVE-2026-8804"
strings:
$sensitive_key = /(password|secret|token|api_key|private_key):\s*[^\s*]/
$state_cache_header = "---" nocase
$puppet_resource = /^\s*-\s*name:/ nocase
condition:
$state_cache_header at 0 and #sensitive_key > 0 and #puppet_resource > 0
}
Sigma Rule
title: Puppet State Cache Sensitive Data Access
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects attempts to read Puppet state cache file containing cleartext sensitive data
author: Valters IT
date: 2026/01/01
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-8804
logsource:
category: process_creation
product: linux
detection:
selection:
Image|endswith: '/cat' or '/grep' or '/less' or '/more' or '/head' or '/tail'
CommandLine|contains: '/opt/puppetlabs/puppet/cache/state/state.yaml'
condition: selection
falsepositives:
- Legitimate Puppet operations (e.g., puppet agent runs)
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2026-8804 Puppet Sensitive Data Exfiltration"; flow:to_server; content:"state.yaml"; http_uri; classtype:attempted-recon; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade Puppet Core to version 8.20.0 or later.
- Upgrade Puppet Enterprise to version 2023.8.10 or 2025.11.0.
- If upgrade is not possible, manually update the
resource_apimodule to version 1.9.2 or 2.0.1:puppet module install puppetlabs-resource_api --version 1.9.2
Long-Term Mitigations:
- Restrict access to the Puppet cache directory using file permissions (e.g.,
chmod 700 /opt/puppetlabs/puppet/cache/state). - Implement file integrity monitoring (FIM) on the state cache file.
- Use Puppet’s built-in
Sensitivedata type in manifests to ensure values are masked in logs and reports. - Rotate any credentials that may have been exposed.
Workaround:
- If upgrade is delayed, consider disabling the transaction state cache by setting
storeconfigs = falseinpuppet.conf(note: this may impact PuppetDB functionality).
Valters IT