Direct answer: CVE-2026-115731 lets any holder of a Puppet agentAI agentAn AI program that performs work steps by itself, for example reading a message, drafting a reply, and recording the result.Open the glossary certificate run code on the Puppet server through an agent report. CVE-2026-115732 lets 1 node pose as another node through a similar certificate name. Today, check the version, update to OpenVox 8.18.0, Puppet Core 8.22.2, or PE 2025.12.1, then restart the server.
Perforce gives CVSS 4.0 9.4 to CVE-2026-115731 and 9.0 to CVE-2026-115732. OpenVox gives 9.4 and 9.5. Both CVEs have the critical label.
Main condition: You run a Puppet, OpenVox, or Puppet Enterprise server yourself. Limit: This article has no request contents, payloads, or attack sequence.
We read the Perforce advisory Report Deserialization Code Execution, the Perforce advisory Certificate Name Authorization Bypass, the OpenVox advisory GHSA-ffr6-rwpm-p5wq, the OpenVox advisory GHSA-q4hm-33rc-572g, the CVE-2026-115731 record, the CVE-2026-115732 record, the Vox Pupuli blog of 3 November 2026, the Neodyme research, and CISA KEV on 4 November 2026, from 13.35 to 13.55 WIB. We tested 3 check scripts in podman containers with the official openvoxserver:8.17.0 (vulnerable) and 8.18.0 (safe) images, and with official OpenVox packages on Ubuntu 24.04. We did not test Puppet Enterprise, Puppet Core, or an attack.
The problem: 1 Puppet server holds the keys to all your servers
The Puppet server decides the contents of every managed server, so a flaw in the Puppet server is a flaw in all of them.
Puppet is a configuration management tool. DevOps teams use it to install packages, users, and configuration on tens to thousands of servers from 1 place. OpenVox is the community fork of Puppet that Vox Pupuli maintains.
Every managed server runs an agent. The agent holds a certificate from the CA on the Puppet server, then asks for a catalog and sends a report. Catalogs often hold database passwords, APIAPIThe official door 2 systems use to exchange data, without anybody copying it by hand.Open the glossary tokens, and other keys.
On 3 November 2026, Perforce and OpenVox released patches together for 2 flaws in the Puppet server. Neodyme, the team that found the flaws, published its research on the same day.

The OpenVox releases of 29 October do not close these flaws. So a server that you updated last week is still vulnerable.
How it works: agent reports and certificate names
The 2 flaws are in 2 paths that every agent uses every 30 minutes: send a report and check access.
This section uses the official advisory summaries. Its purpose is to help you choose the right steps, not to explain an attack.
Summary of CVE-2026-115731 (agent report)
According to the CVE-2026-115731 record, the report-processing code in Puppet Server reads report data without a safe type limit. A client with an agent certificate that the CA signed can run code on the server as the Puppet service user.
The CVE record also gives an important condition: when the CA autosigns without strong verification, an attacker with no account can get that certificate. The Neodyme research says that this access can expose the CA key and the catalogs of all nodes.
Summary of CVE-2026-115732 (certificate name)
According to the CVE-2026-115732 record, the certificate name check in the trapperkeeper-authorization component accepts a name that is longer or shorter than the allowed host name. Example from the OpenVox advisory GHSA-q4hm-33rc-572g: a certificate for a name that extends the name of a node passes as that node.
As a result, 1 node can read the catalog of another node, including the secrets in it, and send false facts. For Puppet Enterprise, Perforce says that this flaw also opens CA administration and remote commands on nodes.
Scores of the 2 CVEs and 1 image advisory
The scores differ per source, so this table shows both. The OpenVox advisory scores CVE-2026-115732 with no login condition, so its score is higher.
| ID | Area | CVSS 4.0 Perforce | CVSS 4.0 OpenVox | Access | Safe in |
|---|---|---|---|---|---|
| CVE-2026-115731 | Agent report: report data runs code on the Puppet server | 9.4 | 9.4 | A valid agent certificate | OpenVox 8.18.0, 9.2.0, Puppet Core 8.22.2, 9.1.3 |
| CVE-2026-115732 | Certificate name: 1 node is allowed as another node | 9.0 | 9.5 | A certificate with a similar name | The same releases |
| GHSA-c4wc-g5pp-7wfp | openvoxdb 8.15.0 image: ALLOWLIST not applied | - | 9.9 | Network access to OpenVoxDB | Image 8.17.0, Vox Pupuli advises 8.18.0 |

GHSA-c4wc-g5pp-7wfp came out on 21 October 2026 for the container-openvoxdb 8.15.0 image. It is not one of the 2 CVEs above, but the Vox Pupuli blog of 3 November 2026 lists it in the same list.
Exploitation status on 4 November 2026
We found no attack reports and no CISA KEV entry for the 2 CVEs. But the OpenVox advisory GHSA-ffr6-rwpm-p5wq already has a proof of concept. Rama Digital analysis: treat the attack code as public, and update today.
Who has the highest risk
The risk depends on who can get a certificate and what your catalogs hold, not only on the version.
In our test, the official OpenVox 8.17.0 and 8.18.0 container images use AUTOSIGN=true by default. So a server in a container with the default value signs every certificate request.
| Puppet server condition | Risk | Reason |
|---|---|---|
Autosign true or an autosign list with a wildcard | Highest | Anyone who reaches port 8140 can get a certificate |
| Port 8140 open to the internet | High | An outside attacker can request a certificate and call the API |
| Catalogs or Hiera hold passwords and tokens | High | A node that poses as another node can read those secrets |
| Hundreds of nodes, short-lived VMs, or autoscaling | Check | Every node has a valid certificate. 1 broken node is enough for CVE-2026-115731 |
| Open source Puppet or OpenVox 7 | No patch | No fix release exists. Plan a line move |
| Safe version, autosign off, port 8140 limited | Low | Still look for signs from the time before the update |

Puppet servers often run on VMs that also need kernel patches, for example for the Linux kernel TCP flaw CVE-2026-98432. Teams that use Rancher for Kubernetes should also read the Rancher CVE-2026-94290 warning.
Vulnerable and safe versions
The vulnerable code is in 2 packages on the server machine: the server package and the agent package. The server loads Ruby code from the agent package, so update both.
| Product | Vulnerable versions | Status on 4 November 2026 | Action |
|---|---|---|---|
| OpenVox Server | 8.17.1 and below, 9.0.0 to 9.1.1 | Vulnerable | Update to 8.18.0 or 9.2.0 |
| OpenVox Agent on the server machine | 8.31.2 and below, 9.0.0 to 9.2.1 | Vulnerable | Update to 8.32.0 or 9.3.0 |
| Puppet Core | 8.11.0 to 8.22.1, 9.0.0 to 9.1.2 | Vulnerable | Update to 8.22.2 or 9.1.3 |
| Puppet Enterprise | 2023.8.0 to 2023.8.12, 2025.0.0 to 2025.12.0, 2026.0.0 | Vulnerable | Update to 2023.8.13, 2025.12.1, or 2026.0.1 |
| Open source Puppet | 8.10.0 and below, 7.x, 6.x | No patch | Move to OpenVox 8 or Puppet Core |
| OpenVox 7 | 7.x | No patch | Move to OpenVox 8.18.0 |

The version data comes from the Perforce advisory Report Deserialization Code Execution, the OpenVox advisory GHSA-ffr6-rwpm-p5wq, and the OpenVox Server 8.18.0 release. Rama Digital analysis: the OpenVox advisory lists vulnerable versions up to 8.17.0 and 8.31.1, but the 8.17.1 and 8.31.2 releases of 29 October came out before the patch. We treat every version below the safe version as vulnerable.
Open source builds from Perforce stopped at version 8.10.x. The Vox Pupuli blog of 3 November 2026 says that open source Puppet gets no more updates.
Before you start
sudoaccess to the Puppet or OpenVox server that holds the CA.- A list of the managed servers (inventory), to compare certificate names.
- A backup of the
/etc/puppetlabsfolder, especially the CA folder. - Access to the firewall in front of port 8140.
- A maintenance window of 15 to 30 minutes. Agents cannot reach the server during the restart, then try again at the next run.
Step 1: Check the server and agent package versions
Save this script as check-version-puppet.sh. The script reads the openvox-server, openvox-agent, puppetserver, and puppet-agent packages, and the Puppet Enterprise version.
#!/usr/bin/env bash
# Check the version of Puppet Server, OpenVox Server, Puppet Core, and Puppet Enterprise for CVE-2026-115731 and CVE-2026-115732.
# Data: the Perforce advisories and the OpenVox GitHub advisories, 3 November 2026.
# Use on the Puppet server: sudo bash check-version-puppet.sh
# Use for versions that you copied from other servers: bash check-version-puppet.sh openvox-server=8.17.0 pe=2025.12.0
# Product names: openvox-server, openvox-agent, puppet-agent, puppetserver, pe.
# The script only reads. It changes nothing.
# lower A B: true when version A is below version B.
lower() { [ "$1" != "$2" ] && [ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]; }
say() { printf '%-15s %-11s %s\n' "$1" "$2" "$3"; }
check() {
local p="$1" v="$2" safe=""
v=${v%%-*}
if ! [[ $v =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?$ ]]; then
say "$p" "$v" "UNKNOWN, compare it by hand with the safe version table"
return
fi
[[ $v =~ ^[0-9]+\.[0-9]+$ ]] && v="$v.0"
case "$p" in
openvox-server)
case ${v%%.*} in 8) safe=8.18.0 ;; 9) safe=9.2.0 ;; esac ;;
openvox-agent)
case ${v%%.*} in 8) safe=8.32.0 ;; 9) safe=9.3.0 ;; esac ;;
puppet-agent)
# Perforce: open source builds stopped at 8.10.x. Builds 8.11.0 and later are Puppet Core.
if lower "$v" 8.11.0; then
say "$p" "$v" "NO PATCH (open source Puppet) -> move to OpenVox 8.32.0 or Puppet Core 8.22.2"
return
fi
case ${v%%.*} in 8) safe=8.22.2 ;; 9) safe=9.1.3 ;; esac ;;
puppetserver)
say "$p" "$v" "CHECK: the Perforce patch ships with Puppet Core 8.22.2 or 9.1.3, see the puppet-agent line"
return ;;
pe)
case $v in
2023.8.*) safe=2023.8.13 ;;
2025.*) safe=2025.12.1 ;;
2026.0.*) safe=2026.0.1 ;;
*) if lower "$v" 2023.8.0; then
say "$p" "$v" "NO PATCH (old line) -> move to 2023.8.13 or 2025.12.1"
return
fi ;;
esac ;;
*)
say "$p" "$v" "UNKNOWN PRODUCT, use openvox-server, openvox-agent, puppet-agent, puppetserver, or pe"
return ;;
esac
if [ -z "$safe" ]; then
say "$p" "$v" "NO PATCH -> move to a line that still gets patches"
elif lower "$v" "$safe"; then
say "$p" "$v" "VULNERABLE to CVE-2026-115731/115732 -> update to $safe"
else
say "$p" "$v" "SAFE for these 2 CVEs (safe from $safe)"
fi
}
if (( $# > 0 )); then
for x in "$@"; do
if [[ $x == *=* ]]; then check "${x%%=*}" "${x#*=}"; else say "?" "$x" "Write it as product=version, for example openvox-server=8.17.0"; fi
done
exit 0
fi
found=0
package_version() {
if command -v dpkg-query >/dev/null 2>&1; then
dpkg-query -W -f='${Status} ${Version}\n' "$1" 2>/dev/null | awk '/install ok installed/ {print $4}'
elif command -v rpm >/dev/null 2>&1; then
rpm -q --qf '%{VERSION}\n' "$1" 2>/dev/null | grep -v 'not installed'
fi
}
if [ -r /opt/puppetlabs/server/pe_version ]; then
check pe "$(cat /opt/puppetlabs/server/pe_version)"; found=1
fi
for p in openvox-server openvox-agent puppetserver puppet-agent; do
v=$(package_version "$p")
if [ -n "$v" ]; then check "$p" "$v"; found=1; fi
done
# Container install: OpenVox is installed as a gem, without packages.
if [ $found = 0 ] && command -v gem >/dev/null 2>&1; then
g=$(gem list --exact openvox 2>/dev/null | sed -nE 's/^openvox \(([0-9.]+).*/\1/p')
if [ -n "$g" ]; then
s=$(puppetserver --version 2>/dev/null | sed -nE 's/.*version: *([0-9.]+).*/\1/p')
[ -n "$s" ] && check openvox-server "$s"
check openvox-agent "$g"
found=1
fi
fi
if [ $found = 0 ]; then
echo "No Puppet or OpenVox package found on this server."
echo "Write the versions by hand, for example: bash check-version-puppet.sh openvox-server=8.17.0"
exit 1
fi
pid=$(pgrep -f puppet-server-release.jar | head -n1)
if [ -n "$pid" ]; then
echo "Server process running since: $(ps -o lstart= -p "$pid")"
echo "Restart the server after the update, so that it loads the new code."
fi
# On the Puppet or OpenVox server
sudo bash check-version-puppet.sh
# Check versions that you copied from other servers
bash check-version-puppet.sh openvox-server=8.17.1 puppet-agent=8.22.1 pe=2025.12.0
# Manual check without the script
puppetserver --version
puppet --version
cat /opt/puppetlabs/server/pe_version

In the OpenVox container, the code is installed as a gem, not as a package. The script reads that gem version when no package exists.
Check the result: "VULNERABLE" or "NO PATCH" means go to steps 2 and 3 today. "SAFE" still means run step 5, because the flaws existed before you updated.
Step 2: Check autosign, auth.conf, and port 8140
These 3 settings decide who can use the 2 flaws on your server.
Save this script as check-exposure-puppet.sh. The script reads the autosign setting, the auth.conf rules that compare certificate names, the port 8140 address, and the number of certificates.
#!/usr/bin/env bash
# Check the exposure of a Puppet or OpenVox server for CVE-2026-115731 and CVE-2026-115732:
# autosign, auth.conf rules that compare certificate names, port 8140, and the number of certificates.
# Use on the Puppet server: sudo bash check-exposure-puppet.sh
# The script only reads. It changes nothing.
CONF=/etc/puppetlabs/puppetserver/conf.d
command -v puppet >/dev/null 2>&1 || PATH="$PATH:/opt/puppetlabs/bin"
echo "== 1. Autosign (can anyone get a certificate?)"
a=$(puppet config print autosign --section server 2>/dev/null)
case "$a" in
true)
echo "OPEN autosign = true. The CA signs every certificate request automatically." ;;
false|"")
echo "SAFE autosign = false. An admin approves every certificate." ;;
*)
if [ -x "$a" ]; then
echo "CHECK autosign uses the policy script $a. Make sure that it refuses names outside your inventory."
elif [ -r "$a" ]; then
n=$(grep -cvE '^\s*(#|$)' "$a")
echo "CHECK autosign uses the list $a ($n lines)."
grep -vE '^\s*(#|$)' "$a" | while read -r line; do
if [[ $line == *'*'* ]]; then echo "OPEN wildcard pattern: $line"; else echo "CHECK fixed name: $line"; fi
done
else
echo "SAFE autosign points to $a, but that file does not exist."
fi ;;
esac
echo
echo "== 2. auth.conf rules that compare the certificate name with the name in the URL"
if [ -r "$CONF/auth.conf" ]; then
awk '/allow: *"\$1"/ {f=1} /name: *"/ && f {sub(/^[ \t]*name: */, ""); print " " $0; f=0}' "$CONF/auth.conf"
echo "Total: $(grep -cE 'allow: *"\$1"' "$CONF/auth.conf") rules. Vulnerable versions can match these names wrongly."
other=$(grep -nE '^\s*allow: *"[^"$*]+\.[^"]+"' "$CONF/auth.conf")
if [ -n "$other" ]; then
echo "CHECK custom rules with a fixed host name (check them again after the update):"
printf '%s\n' "$other" | sed 's/^/ /'
fi
else
echo "CHECK $CONF/auth.conf is not readable."
fi
echo
echo "== 3. Port 8140"
if command -v ss >/dev/null 2>&1; then
addr=$(ss -ltnH 'sport = :8140' | awk '{print $4}' | sort -u | tr '\n' ' ')
else
# Without ss: read the kernel socket table. 1FCC is port 8140, 0A is LISTEN.
addr=$(awk 'FNR > 1 && $4 == "0A" && $2 ~ /:1FCC$/ {split($2, x, ":"); print (x[1] ~ /^0+$/ ? "*" : x[1]) ":8140"}' /proc/net/tcp /proc/net/tcp6 2>/dev/null | sort -u | tr '\n' ' ')
fi
if [ -z "$addr" ]; then
echo "CHECK No process listens on port 8140."
elif [[ $addr == *'*'* || $addr == *0.0.0.0* || $addr == *'[::]'* ]]; then
echo "CHECK The server listens on all addresses: $addr"
echo " Limit port 8140 in the firewall to the agent networks only."
else
echo "INFO The server listens on: $addr"
fi
echo
echo "== 4. Certificates"
cadir=$(puppet config print cadir --section server 2>/dev/null)
if [ -d "$cadir/signed" ]; then
echo "Signed : $(find "$cadir/signed" -name '*.pem' | wc -l)"
echo "Waiting: $(find "$cadir/requests" -name '*.pem' 2>/dev/null | wc -l)"
else
echo "CHECK CA folder not found. Run this script on the server that holds the CA."
fi
sudo bash check-exposure-puppet.sh

In our test, 4 default rules use allow: "$1": catalog, node, report, and facts. These rules allow a node only for its own name, and vulnerable versions can match that name wrongly.
Check the result: write down the autosign status, the number of custom rules with a fixed host name, and the port 8140 address. "OPEN" in part 1 means run step 4a today.
Step 3: Update and restart the server
Only the update and the restart close these 2 flaws. The server reads the new code only after a restart.
# OpenVox on Ubuntu or Debian (tested on Ubuntu 24.04)
sudo apt-get update && sudo apt-get install --only-upgrade openvox-server openvox-agent
# OpenVox on RHEL, Rocky, or AlmaLinux
sudo dnf upgrade openvox-server openvox-agent
# Load the new code. Without a restart, the server keeps running the old code.
sudo systemctl restart puppetserver
# Check again
sudo bash check-version-puppet.sh
# OpenVox in a container: change the image tag, then create the container again
# ghcr.io/openvoxproject/openvoxserver:8.18.0 or :9.2.0

The openvox-server 8.18.0 package in the Ubuntu 24.04 repo needs openvox-agent 8.32.0 or later. So the apt command above moves both packages up. We did not test the dnf command or the restart through systemd.
- Puppet Core: update the
puppet-agentpackage to 8.22.2 or 9.1.3 and thepuppetserverpackage from the same release, then restart. - Puppet Enterprise: run the 2023.8.13, 2025.12.1, or 2026.0.1 installer on the primary server, then upgrade the compilers and replicas.
- Open source Puppet or OpenVox 7: no patch exists. Use the migration guides in the Vox Pupuli blog of 3 November 2026 to move to OpenVox 8.
- Run
check-version-puppet.shagain. The correct result: "SAFE for these 2 CVEs" for the server and the agent.
3b. Check custom auth.conf rules after the update
The Vox Pupuli blog of 3 November 2026 asks admins to check custom auth.conf rules. Some rules may depend on the wrong name match of the old versions, so those rules can refuse nodes after the update.
Run check-exposure-puppet.sh again and read the "custom rules with a fixed host name" lines. Then run puppet agent -t on 1 node of each group, and make sure that the catalog arrives.

Rama Digital analysis: the main patch is on the server machine. Also update the agent package on the other nodes in the next window, so that all machines use the same version.
Check the result: the version script prints "SAFE", the server process started after the update, and every node group receives its catalog.
Step 4: Reduce the impact until the update is done
This step reduces the impact, but it does not close the flaws.
Rama Digital analysis: we chose 2 steps from the workaround list in the Vox Pupuli blog of 3 November 2026. Condition: the update cannot run today. Limit: every managed node has a valid certificate, so 1 broken node can still use CVE-2026-115731.
4a. Turn off autosign and approve certificates by hand
# 4a. Turn off autosign, then reload the server
sudo puppet config set autosign false --section server
sudo systemctl reload puppetserver
sudo bash check-exposure-puppet.sh | head -n 2
# List new requests, check each name in your inventory, then approve them one by one
sudo puppetserver ca list
sudo puppetserver ca sign --certname app-01.example.com
# Revoke an unknown certificate
sudo puppetserver ca clean --certname x.web-01.example.com
# OpenVox container: set the env AUTOSIGN=false, then create the container again

The systemd unit from the OpenVox package uses puppetserver reload for systemctl reload. We tested the reload, list, and clean commands. We did not test the ca sign command.
When you need autosign for autoscaling, use a policy script that refuses names outside your inventory. Do not use a wildcard in autosign.conf.
4b. Limit port 8140 to the agent networks
# 4b. ufw example: allow port 8140 only from the agent network 198.51.100.0/24
sudo ufw allow from 198.51.100.0/24 to any port 8140 proto tcp
sudo ufw deny 8140/tcp
sudo ufw status numbered
Replace 198.51.100.0/24 with your server network. We did not test this ufw example. In the cloud, use a security group with the same rules.
Check the result: the exposure script prints "SAFE" in part 1, and port 8140 does not answer from networks outside the list.
Step 5: Look for signs of misuse
These flaws existed before you updated, so also look for signs from the time before the update.
Save this script as check-signs-puppet.sh. The script reads the certificate names in the CA, new certificates, the access log, child processes of the server process, and new files of the service user in temporary folders.
#!/usr/bin/env bash
# Look for signs of misuse of CVE-2026-115731 and CVE-2026-115732 on a Puppet or OpenVox server.
# Use: sudo bash check-signs-puppet.sh [START-DATE] [ACCESS-LOG]
# Example: sudo bash check-signs-puppet.sh 2026-10-01 /var/log/puppetlabs/puppetserver/puppetserver-access.log
# The script only reads. It changes nothing.
FROM=${1:-2026-10-01}
LOG=${2:-/var/log/puppetlabs/puppetserver/puppetserver-access.log}
command -v puppet >/dev/null 2>&1 || PATH="$PATH:/opt/puppetlabs/bin"
cadir=$(puppet config print cadir --section server 2>/dev/null)
signs=0; checks=0
echo "== 1. Certificate names that extend the name of another node (CVE-2026-115732)"
if [ -d "$cadir/signed" ]; then
mapfile -t names < <(find "$cadir/signed" -name '*.pem' -printf '%f\n' | sed 's/\.pem$//' | sort)
for a in "${names[@]}"; do
for b in "${names[@]}"; do
if [[ $a == *".$b" ]]; then
echo "SIGN $a extends the name $b"
signs=$((signs + 1))
fi
done
done
(( signs == 0 )) && echo "None."
else
echo "CHECK CA folder not found."
fi
echo
echo "== 2. Certificates signed since $FROM"
if [ -d "$cadir/signed" ]; then
# File time, not notBefore. The CA moves notBefore back by 1 day.
lines=$(find "$cadir/signed" -name '*.pem' -newermt "$FROM" -printf '%TY-%Tm-%Td %TH:%TM %f\n' | sed 's/\.pem$//' | sort)
if [ -n "$lines" ]; then
printf '%s\n' "$lines" | sed 's/^/CHECK /'
checks=$((checks + $(printf '%s\n' "$lines" | wc -l)))
echo "Compare every name with your server inventory."
else
echo "None."
fi
fi
echo
echo "== 3. One node name from more than 1 IP address (access log)"
if [ -r "$LOG" ]; then
result=$(grep -E '"(GET /puppet/v3/catalog/|PUT /puppet/v3/report/)' "$LOG" |
sed -nE 's#^([^ ]+) .*"(GET|PUT) /puppet/v3/(catalog|report)/([^?/ ]+).*#\4 \1#p' | sort -u |
awk '{ip[$1] = ip[$1] " " $2; n[$1]++} END {for (k in n) if (n[k] > 1) print k " from" ip[k]}')
if [ -n "$result" ]; then
printf '%s\n' "$result" | sed 's/^/CHECK /'
checks=$((checks + $(printf '%s\n' "$result" | wc -l)))
else
echo "None."
fi
else
echo "CHECK Access log is not readable: $LOG"
fi
echo
echo "== 4. Child processes of the server process"
pid=$(pgrep -f puppet-server-release.jar | head -n1)
if [ -n "$pid" ]; then
kids=$(ps --ppid "$pid" -o pid=,user=,etime=,args= 2>/dev/null)
if [ -n "$kids" ]; then
printf '%s\n' "$kids" | sed 's/^ */CHECK /'
checks=$((checks + $(printf '%s\n' "$kids" | wc -l)))
else
echo "None."
fi
user=$(ps -o user= -p "$pid" | tr -d ' ')
else
echo "CHECK The server process is not running."
user=puppet
fi
echo
echo "== 5. New files owned by user $user in temporary folders since $FROM"
# The hsperfdata and jruby-* folders are normal Java and JRuby work files.
files=$(find /tmp /var/tmp /dev/shm -xdev -type f -user "$user" -newermt "$FROM" \
-not -path '/tmp/hsperfdata_*' -not -path '/tmp/jruby-*' 2>/dev/null)
if [ -n "$files" ]; then
printf '%s\n' "$files" | sed 's/^/CHECK /'
checks=$((checks + $(printf '%s\n' "$files" | wc -l)))
else
echo "None."
fi
echo
echo "Result: SIGN $signs, CHECK $checks"
if (( signs > 0 )); then
echo "A sign exists. Revoke that certificate, then follow the response steps in the article."
fi
sudo bash check-signs-puppet.sh 2026-10-01 /var/log/puppetlabs/puppetserver/puppetserver-access.log


The access log does not record the client certificate name. So the script looks for 1 node name in a catalog or report URL that comes from more than 1 IP. An IP change from DHCP also shows up, so the result is CHECK, not SIGN.
Check the result: the script prints "SIGN 0", and every CHECK has an explanation. An attacker can delete logs, so no sign does not mean safe.
When you find even 1 sign, keep the logs and the CA folder as evidence. Revoke the unknown certificates, then replace every password and token in the catalogs of the affected nodes.
When you find a sign in the server processes, treat the CA key as exposed. Make a new CA and new certificates for all nodes with the certificate regeneration guide in the OpenVox or Puppet documentation. Check every node, because the Puppet server controls all of them.
When the servers hold customer data, Indonesian Law 27/2022 on Personal Data Protection requires a written notice within 3 times 24 hours after a personal data breach. Also read the pgAdmin 4 CVE-2026-116241 warning.
Example: 1 morning of response for 3 Puppet servers
This simulation uses dummy data. The server names, times, and results are not customer data.
| Time (WIB) | Dummy server | Checked | Result | Action |
|---|---|---|---|---|
| 08.00 | puppet-prod (OpenVox 8.17.1, 400 nodes) | Steps 1 and 2 | VULNERABLE, autosign with a wildcard | Step 4a now, update this afternoon |
| 08.30 | puppet-k8s (container 8.17.0) | Steps 1 and 2 | VULNERABLE, default AUTOSIGN=true | Tag 8.18.0 and AUTOSIGN=false |
| 09.00 | puppet-old (Puppet 7.34.0) | Step 1 | NO PATCH | Step 4, plan a move to OpenVox 8 |
| 09.30 | puppet-prod | Step 5 | SIGN 1: a certificate name extends db-01 | Revoke the certificate, replace the database password |
Lesson from the simulation: a safe version does not prove a clean server. Step 5 is still necessary on every server.
Who installs the patch
The patch duty differs per service type, so this table helps you know who acts today.
| Service type | Patch owner | What you do |
|---|---|---|
| OpenVox or Puppet Core that you install yourself | Your team | Steps 1 to 5 |
| Puppet Enterprise with Perforce support | Your team, with help from Perforce | Open a Perforce ticket when the upgrade fails, then steps 3b and 5 |
| A Puppet server managed by a vendor or MSP | The vendor, per the contract | Ask for written version proof, then replace the secrets in your catalogs |
| OpenVox in a container or Kubernetes | Your team | Change the image tag, set AUTOSIGN=false, then step 5 |
Rama Digital recommendation: treat the Puppet server as the master key of all servers. Keep secrets in a secret manager, not in catalogs, and update other panels in the same pipeline, for example for the GitLab CVE-2026-97229 warning. Teams that use system containers should also read the LXD and Incus certificate flaw CVE-2026-112816.
Checklist for today
- List all Puppet servers, compilers, and replicas. Owner: platform team. Evidence: a list of names and versions.
- Check the version with step 1. Owner: Puppet admin. Evidence: script output.
- Check the exposure with step 2. Owner: Puppet admin. Evidence: script output.
- Apply step 4 on every server that cannot update today. Owner: Puppet admin and network team. Evidence: script output and firewall rules.
- Back up, update, then restart. Owner: Puppet admin. Evidence: script output after the update.
- Check custom auth.conf rules and 1 node per group. Owner: Puppet admin. Evidence: puppet agent -t results.
- Look for signs with step 5. Owner: Puppet admin and security team. Evidence: script output.
Questions and answers
Has anyone used these flaws in an attack?
On 4 November 2026, we found no attack reports, and the 2 CVEs are not on CISA KEV. But the OpenVox advisory already has a proof of concept, so update today.
My autosign is already off. Am I safe?
No. CVE-2026-115731 needs only 1 valid agent certificate, and every managed node has one. Autosign off only closes the path for an attacker with no node.
Must I also update the agent on every node?
The main patch is on the server machine: the server package and the agent package on that machine. Update the agents on other nodes in the next window.
I still use open source Puppet. What do I do?
Open source Puppet gets no patch. Apply step 4 today, then move to OpenVox 8 or Puppet Core as soon as possible.
Is the OpenVox 8.18.0 container image safe?
Its version is safe for these 2 CVEs. But the 8.18.0 image still uses AUTOSIGN=true by default, so set AUTOSIGN=false or a policy script.
Can a firewall on port 8140 replace the update?
No. Nodes in the allowed networks can still use these flaws. The firewall only reduces who can try.
Do the check scripts change anything on my server?
No. The 3 scripts only read. The commands that change something are only in steps 3 and 4, and each command is written separately.
Next step
The limits that still apply: step 4 does not close the flaws, and the update does not remove access that an attacker already used. When your Puppet server shows signs in step 5, or you need help with an audit and recovery, use Vibe Code Rescue. For 1 urgent problem today, book a 30-minute session.
Sources
- Perforce advisory Report Deserialization Code Execution and Perforce advisory Certificate Name Authorization Bypass: summaries, CVSS 4.0 scores 9.4 and 9.0, and the safe Puppet Core and PE versions.
- CVE-2026-115731 record and CVE-2026-115732 record: the official descriptions, CWEs, and the publication date of 3 November 2026.
- OpenVox advisory GHSA-ffr6-rwpm-p5wq and OpenVox advisory GHSA-q4hm-33rc-572g: the vulnerable and safe OpenVox versions, scores 9.4 and 9.5.
- GHSA-c4wc-g5pp-7wfp: the ALLOWLIST flaw in the openvoxdb 8.15.0 image.
- Vox Pupuli blog of 3 November 2026: safe versions, workarounds, auth.conf, and the open source Puppet status.
- Neodyme research: the finders, release time, mitigation advice, and detection hints.
- OpenVox Server 8.18.0 release: the release date of 3 November 2026.
- CISA KEV: status on 4 November 2026.
- Indonesian Law 27/2022 on Personal Data Protection: the duty to report a personal data breach.




