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
- Fix the manifest so From is a path inside the extracted archive and To is inside the install directory, with no '..' or leading '/'
- Manually inspect the archive layout and align From with it
- Update/refresh the plugin index in case the entries were corrected upstream
- 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
- Lint manifests for '..' or absolute paths in From/To
- Run IsSubPath checks in plugin index CI
- Investigate out-of-bounds hits as possible malicious manifests
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
- can't move, move target %v is not a subpath from=%q, to=%q
- the fullPath %q does not extend the sub-fullPath %q: %w
- could not get files using a glob string: %w
- no files in the plugin archive matched the glob pattern=%s
- could not find move targets: %w
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/41258e8438e9737a.
Report an issue: GitHub.