hashicorp/nomad · error

image_path is not in the allowed paths

Error message

image_path is not in the allowed paths

What it means

The QEMU driver validates, at task start, that the VM image path (image_path) is either inside one of the client's configured 'image_paths' allowlist directories or inside the task's allocation directory. If isAllowedImagePath() rejects the path, StartTask refuses to launch the VM. This is a security guard against arbitrary file access by task authors, since QEMU would otherwise run with whatever disk image the task specifies.

Solutions

  1. Add the directory containing the VM image to the client QEMU driver config: plugin "qemu" { driver "qemu" { image_paths = ["/srv/images"] } } and restart the Nomad client.
  2. Place the image inside the task's allocation directory (e.g. download it with an artifact block) which is always allowed.
  3. Verify the image_path in the task's driver config exactly matches a real file under one of the allowed roots (check for typos and symlinks).

Example fix

// task config: before
image_path = "/home/ops/alpine.qcow2"
// after (client hcl: plugin "qemu" { config { image_paths = ["/srv/images"] } })
image_path = "/srv/images/alpine.qcow2"
Defensive patterns

Strategy: validation

Validate before calling

// before submitting, confirm image lives under an allowed root
const allowedRoots = ["/srv/images"]; // must match client config image_paths
function isAllowedImagePath(root, allocDir, p) {
  const abs = require("path").resolve(p);
  return [allocDir, ...root].some
    ? [allocDir, ...allowedRoots].some((r) => abs.startsWith(require("path").resolve(r) + require("path").sep))
    : false;
}

Type guard

function hasAllowedImagePath(cfg) {
  return typeof cfg.image_path === "string" && cfg.image_path.length > 0 &&
    allowedRoots.some((r) => require("path").resolve(cfg.image_path).startsWith(require("path").resolve(r) + require("path").sep));
}

Try / catch

try {
  await nomad.jobs.startTask(cfg);
} catch (e) {
  if (String(e.message).includes("image_path is not in the allowed paths")) {
    console.error(`Move ${cfg.image_path} under an image_paths root or add its dir to client config`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling tasks.start (QEMU driver) with driver config image_path pointing to a file outside config.image_paths allowlist and outside the task's alloc dir; empty or mis-scoped image_paths in the client 'plugin.qemu.driver.image_paths' config; using a relative or symlinked path that resolves outside allowed roots.

Common situations: Operator forgets to add the image directory to image_paths in the Nomad client config; dev setups using images in /home or /tmp while allowlist points elsewhere; images mounted at a different path on the client node than in the allowlist; path typo or symlink chain escaping the allowlist.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/0659df482d117b7e. Report an issue: GitHub.

Appendix: source

Thrown at drivers/qemu/driver.go:489

	handle.Config = cfg

	if err := validateEmulator(driverConfig.Emulator, d.config.EmulatorsAllowList); err != nil {
		return nil, nil, err
	}

	if err := validateArgs(d.config.ArgsAllowList, driverConfig.Args); err != nil {
		return nil, nil, err
	}

	// Get the image source
	vmPath := driverConfig.ImagePath
	if vmPath == "" {
		return nil, nil, fmt.Errorf("image_path must be set")
	}
	vmID := filepath.Base(vmPath)

	if !isAllowedImagePath(d.config.ImagePaths, cfg.AllocDir, vmPath) {
		return nil, nil, fmt.Errorf("image_path is not in the allowed paths")
	}

	// Parse configuration arguments
	// Create the base arguments
	emulator := "x86_64"
	if driverConfig.Emulator != "" {
		// COMPAT: TrimPrefix to support full emulator name
		// which was required in 1.11.1.
		emulator = strings.TrimPrefix(driverConfig.Emulator, "qemu-system-")

	}
	accelerator := "tcg"
	if driverConfig.Accelerator != "" {
		accelerator = driverConfig.Accelerator
	}
	machineType := "pc"
	if driverConfig.MachineType != "" {
		machineType = driverConfig.MachineType

View on GitHub (pinned to 482b49bf1a)