CVE-2026-7474: Verified Reproduction
CVE-2026-7474: HashiCorp Nomad: path traversal in host volume plugin loader → client-host RCE
CVE-2026-7474 is verified against nomad · go. Affected versions: prior to v2.0.1 (confirmed at v2.0.0, v1.10.5, v1.11.2). Fixed in v2.0.1. Vulnerability class: RCE. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00185.
What Is CVE-2026-7474?
CVE-2026-7474 (GHSA-hx53-77qj-8663) is a high-severity path traversal vulnerability in HashiCorp Nomad's dynamic host volume plugin loader that allows arbitrary command execution on Nomad client nodes. Pruva reproduced it (reproduction REPRO-2026-00185).
CVE-2026-7474 Severity & CVSS Score
CVE-2026-7474 is rated high severity, with a CVSS base score of 8.8 out of 10.
High — serious impact or readily exploitable. Prioritize remediation.
Affected nomad Versions
nomad · go versions prior to v2.0.1 (confirmed at v2.0.0, v1.10.5, v1.11.2) are affected.
How to Reproduce CVE-2026-7474
pruva-verify REPRO-2026-00185 curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00185/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-7474
- Vulnerable
Prior to v2.0.1 - Fixed
v2.0.1
How the agent worked
Root Cause and Exploit Chain for CVE-2026-7474
CVE-2026-7474 is a path traversal vulnerability in HashiCorp Nomad's dynamic host volume plugin loader that allows arbitrary command execution on Nomad client nodes. When an authenticated user with host-volume-create ACL capability submits a HostVolume.Create request with a malicious PluginID containing directory traversal sequences (e.g., ../../../../bin/ls) and an explicit NodeID, the server bypasses plugin feasibility checks and forwards the request to the target client. The client's NewHostVolumePluginExternal function uses filepath.Join(pluginDir, filename) followed by os.Stat, which resolves the traversal to an arbitrary executable outside the configured plugin directory. That executable is later invoked via exec.CommandContext during volume Create, Fingerprint, or Delete operations.
- Package/component affected:
github.com/hashicorp/nomad/client/hostvolumemanager(host_volume_plugin.go),github.com/hashicorp/nomad/nomad(host_volume_endpoint.go) - Affected versions: Prior to
v2.0.1(confirmed vulnerable inv2.0.0,v1.10.5,v1.11.2) - Fixed versions:
v2.0.1 - Risk level: High (CVSS 3.1: 8.8)
- Consequences: Authenticated attackers with namespace-level
host-volume-createACLs can force any Nomad client node to execute arbitrary binaries from the host filesystem as the Nomad client user, leading to full client-node compromise.
Root Cause
The vulnerability stems from two missing validations in the host volume create workflow:
Client-side path traversal (CWE-22):
NewHostVolumePluginExternalinclient/hostvolumemanager/host_volume_plugin.go(v2.0.0, ~line 224) constructs the plugin executable path withfilepath.Join(pluginDir, filename)and then callsos.Stat(executable). Becausefilepath.Joindoes not reject../sequences, a maliciousPluginIDresolves to any path on the filesystem. If the target file exists and is executable, the client stores the escaped path and later invokes it viaexec.CommandContext.Server-side feasibility bypass: In
nomad/host_volume_endpoint.go, theplaceHostVolumefunction skips the plugin feasibility constraint (${attr.plugins.host_volume.<plugin>.version} is_set) when the user explicitly provides aNodeID. This was intended as an optimization, but it allows an attacker to force placement onto a node that does not legitimately advertise the plugin, bypassing the only server-side guard that could block the malicious request.
The fix commit (cd7240c4099ad33eda279924fb3a9459b162d120, released in v2.0.1) addresses both issues:
- Client-side: Replaces
filepath.Join+os.Statwithos.OpenRoot(pluginDir)androot.Stat(filename). On Go 1.24+,os.Root.Statrejects paths that escape the root directory, returning an error that is mapped toErrPluginNotExists. - Server-side: Moves the plugin feasibility constraint so it is checked even when the request already specifies an explicit
NodeID, preventing traversal payloads from being forwarded to the client.
Reproduction Steps
The reproduction script is repro/reproduction_steps.sh. It performs the following steps:
- Clones the HashiCorp Nomad repository (if not already present) and checks out both
v2.0.0(vulnerable) andv2.0.1(fixed). - Builds the
nomadbinary for each tag (bin/nomad-vulnandbin/nomad-fixed). - Writes a minimal
nomad agent -devconfiguration that enables both server and client roles, binds to127.0.0.1, and sets ahost_volume_plugin_dir. - Starts the vulnerable agent, waits for it to be healthy, and queries its NodeID via
/v1/nodes. - Sends a malicious
PUT /v1/volume/host/createrequest with:PluginID: "../../../../bin/ls"- Explicit
NodeID - Minimal capacity constraints
- Captures the HTTP response body and code into
logs/vulnerable_api.txt. - Stops the vulnerable agent, frees ports, and repeats steps 4–6 with the fixed binary.
- Captures the fixed response into
logs/fixed_api.txt. - Writes
repro/runtime_manifest.jsonwith both results. - Verifies that the vulnerable run shows evidence of
/bin/lsexecution (exit status 2) while the fixed run shows a server-side placement rejection (node ... is not feasible for volume).
Expected evidence
Vulnerable (
v2.0.0): HTTP 500 response containing:HostVolume.Create error: error creating volume "<id>" with plugin "../../../../bin/ls": exit status 2This proves the server forwarded the request, the client resolved the traversal to/bin/ls, and executed/bin/ls create(which exits with code 2 becauselsdoes not understand thecreatesubcommand).Fixed (
v2.0.1): HTTP 500 response containing:could not place volume "cve-test-vol": node <id> is not feasible for volumeThis proves the server now enforces the plugin feasibility constraint even with an explicitNodeID, rejecting the request before it ever reaches the client.
Evidence
logs/vulnerable_api.txt— API response from the vulnerable agent run.logs/fixed_api.txt— API response from the fixed agent run.repro/runtime_manifest.json— Structured manifest with payload, endpoint, and captured HTTP codes for both versions.external/nomad/bin/nomad-vulnandexternal/nomad/bin/nomad-fixed— Compiled Nomad binaries used during reproduction.
Key excerpts
Vulnerable response (logs/vulnerable_api.txt):
HostVolume.Create error: error creating volume "f09840bb-a5d8-0b96-39c6-77deafd35c19" with plugin "../../../../bin/ls": exit status 2
HTTP_CODE:500
Fixed response (logs/fixed_api.txt):
could not place volume "cve-test-vol": node 33225465-afa9-a5c1-2acf-02c0de00879a is not feasible for volume
HTTP_CODE:500
Recommendations / Next Steps
- Upgrade immediately: All Nomad deployments should be upgraded to
v2.0.1or later. The fix includes both client-sideos.OpenRootcontainment and server-side feasibility enforcement. - ACL hardening: Restrict
host-volume-createcapabilities to the smallest set of namespaces and users that genuinely require it. Even with the fix, the capability is powerful. - Network segmentation: Place Nomad client agents on isolated networks so that even a compromised client cannot easily pivot to other infrastructure.
- Monitoring: Alert on host volume create requests that reference unusual
PluginIDvalues (e.g., containing..,/, or absolute paths) as a defense-in-depth measure. - Testing: Add regression tests that verify
os.Root.Statrejects traversal sequences and thatplaceHostVolumealways checks plugin feasibility regardless of whetherNodeIDis explicit.
Additional Notes
- Idempotency: The reproduction script was executed twice consecutively and produced identical differential behavior on both runs (vulnerable →
exit status 2, fixed →not feasible). - Environment: Reproduction performed in an Ubuntu container with Go 1.24.7. A cgroup workaround (
mount -t tmpfsover/sys/fs/cgroup/cpuset) was required because the container lacked thecpuset.memsfile expected by Nomad's cgroup initialization. - Limitations: The reproduction demonstrates the traversal through the actual HTTP API and real agent binaries. The
exit status 2artifact proves command execution of the escaped path. A fully successful volume creation would require a compliant plugin executable; using/bin/lsintentionally produces a failure that still proves the vulnerability.
CVE-2026-7474 Reproduction Transcript
The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.
Full session Replay every step — scrub the timeline or play it back.
Unknown error
Unknown error
Artifacts and Evidence for CVE-2026-7474
Scripts, logs, diffs, and output captured during the reproduction.
How to Fix CVE-2026-7474
Upgrade nomad · go to v2.0.1 or later.
FAQ: CVE-2026-7474
How does the CVE-2026-7474 path-traversal attack work?
Which Nomad versions are affected by CVE-2026-7474, and where is it fixed?
How severe is CVE-2026-7474?
How can I reproduce CVE-2026-7474?
References for CVE-2026-7474
Authoritative sources for CVE-2026-7474 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.