hasura/graphql-engine · error

can't move, move target %v is out of bounds from=%q, to=%q

Error message

can't move, move target %v is out of bounds from=%q, to=%q

What it means

getDirectMove built a direct from→to move for a non-glob FileOperation and isMoveAllowed rejected it: either the source path is not under fromDir or the destination is not under toDir. This guards against manifest entries that read from or write outside the staging/install trees.

Source

Thrown at cli/plugins/move.go:150

	}

	// Build new file name
	toFilePath, err := filepath.Abs(
		filepath.Join(filepath.FromSlash(toDir), filepath.FromSlash(fo.To)),
	)
	if err != nil {
		return m, false, errors.E(
			op,
			fmt.Errorf("could not get the relative path for the move dst: %w", err),
		)
	}

	// Check sane path
	m = move{from: fromFilePath, to: toFilePath}
	if !isMoveAllowed(fromDir, toDir, m) {
		return move{}, false, errors.E(
			op,
			fmt.Errorf(
				"can't move, move target %v is out of bounds from=%q, to=%q",
				m,
				fromDir,
				toDir,
			),
		)
	}

	return m, true, nil
}

func isMoveAllowed(fromBase, toBase string, m move) bool {
	_, okFrom := IsSubPath(fromBase, m.from)
	_, okTo := IsSubPath(toBase, m.to)

	return okFrom && okTo
}

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Fix the manifest so From is a path inside the extracted archive and To is inside the install directory, with no '..' or leading '/'
  2. Manually inspect the archive layout and align From with it
  3. Update/refresh the plugin index in case the entries were corrected upstream
  4. If unsolicited, verify the plugin index source — the entry may be a traversal attack

Example fix

// before
From: "./../../etc/passwd"
// after
From: "bin/plugin"
Defensive patterns

Strategy: validation

Validate before calling

src := filepath.Clean(filepath.Join(fromDir, fo.From))
dst := filepath.Clean(filepath.Join(toDir, fo.To))
if _, ok := plugins.IsSubPath(fromDir, src); !ok { return errors.New("From escapes source dir") }
if _, ok := plugins.IsSubPath(toDir, dst); !ok { return errors.New("To escapes dest dir") }

Try / catch

if err := moveFiles(...); err != nil && strings.Contains(err.Error(), "out of bounds") {
    // reject the manifest entry; never strip the guard
}

Prevention

When it happens

Trigger: A FileOperation.From containing '..' or an absolute path escaping fromDir, or a To that resolves outside toDir, when the entry is treated as a direct file (not a glob).

Common situations: Manifest authored with '..' in From/To; archive extracted somewhere other than expected so joined paths escape the base; malicious/tampered plugin index attempting traversal.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28). Data as JSON: /api/errors/41258e8438e9737a. Report an issue: GitHub.