Skip to content
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 version: v2.0.1 vulnerability class: RCE This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00185.

REPRO-2026-00185 nomad · go RCE Variant found May 28, 2026 CVE entry .txt
Severity HIGH
Confidence HIGH
Reproduced in 48m 9s
Tool calls 337
Spend $3.48
Affected prior to v2.0.1 (confirmed at v2.0.0, v1.10.5, v1.11.2)
Fixed in v2.0.1
$ pruva-verify REPRO-2026-00185
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00185/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
02 · The vulnerability

Nomad's dynamic host volume feature lets operators create volumes on client nodes via external plugins (small executables in a configured plugin directory). When a volume is created, the server RPC HostVolume.Create forwards a ClientHostVolume.Create RPC to the target client. The client's HostVolumeManager.getPlugin passes the attacker-supplied PluginID directly into NewHostVolumePluginExternal in client/hostvolumemanager/host_volume_plugin.go (around line 229 in v2.0.0). There, the code does:

executable := filepath.Join(pluginDir, filename)
f, err := os.Stat(executable)

If filename (the PluginID) contains path-traversal sequences such as ../../../bin/sh, filepath.Join resolves outside the intended plugin directory. The code then checks whether that arbitrary path exists and is executable; if so, it stores the escaped path in HostVolumePluginExternal.Executable. That executable is later invoked via exec.CommandContext during Fingerprint, Create, and Delete operations, yielding arbitrary code execution as the Nomad client user.

Server-side validation is bypassed when the attacker provides an explicit NodeID in the create request: the server's placeHostVolume shortcut skips the feasibility check that would otherwise verify the plugin exists on the node (via the ${attr.plugins.host_volume.<plugin>.version} node attribute). This means a user with host-volume-create ACL capability in a namespace can target any client node and run any binary on its filesystem.

03 · Root cause
Variant analysis
04 · Reproduction transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired. Phases: support triages the advisory · repro reproduces it · vuln_variant confirms the fix blocks it · judge verifies.

Loading session...

05 · Artifacts

Scripts, logs, diffs, and output captured during the reproduction.