henrygd/beszel · warning
invalid file path: %q
Error message
invalid file path: %q
What it means
archivePath validates the entry name (here used for the downloaded asset filename) with filepath.IsLocal before joining it into destDir, rejecting absolute paths and anything containing traversal elements like "..". This is a path-traversal defense; if the release metadata contains a non-local name, the library refuses to build a destination path.
Source
Thrown at internal/ghupdate/extract.go:83
outFile, err := os.Create(path)
if err != nil {
return err
}
if _, err := io.Copy(outFile, tr); err != nil {
outFile.Close()
return err
}
outFile.Close()
}
return nil
}
// archivePath returns a path within destDir, rejecting path traversal entries.
func archivePath(destDir, name string) (string, error) {
if !filepath.IsLocal(name) {
return "", fmt.Errorf("invalid file path: %q", name)
}
return filepath.Join(destDir, name), nil
}
// extractZip extracts the zip archive at "src" to "dest".
//
// Note that only dirs and regular files will be extracted.
// Symbolic links, named pipes, sockets, or any other irregular files
// are skipped because they come with too many edge cases and ambiguities.
func extractZip(src, dest string) error {
zr, err := zip.OpenReader(src)
if err != nil {
return err
}
defer zr.Close()
for _, f := range zr.File {
err := extractFile(f, dest)View on GitHub (pinned to b38fb7dafa)
Solutions
- Ensure release assets are named with plain filenames (no slashes, no leading separators).
- Only fetch releases from the trusted owner/repo (henrygd/beszel) or a mirror you control; treat this error as a red flag for a compromised source.
- If this fires unexpectedly, inspect the release JSON's asset names at the API URL shown in the updater output.
Example fix
// before (malicious asset name in release JSON) "name": "../../etc/beszel" // after (valid asset name) "name": "beszel-agent_0.12.0_linux_amd64.tar.gz"
Defensive patterns
Strategy: validation
Validate before calling
if !filepath.IsLocal(asset.Name) {
return fmt.Errorf("refusing release with non-local asset name %q — source may be compromised", asset.Name)
} Try / catch
updated, err := ghupdate.Update(cfg)
if err != nil && strings.Contains(err.Error(), "invalid file path") {
log.Printf("release contains a path-traversal-looking name (%v); inspect release JSON and consider the source compromised", err)
} Prevention
- Only fetch releases from the trusted owner/repo or a mirror you control.
- Name release assets with plain flat filenames.
- Investigate immediately if this fires — it usually indicates a malicious or malformed release source.
When it happens
Trigger: ghupdate.Update -> update -> archivePath when the asset Name from the release JSON is absolute ("/tmp/x"), contains "../", is reserved (".", volume names on Windows), or is otherwise not a local relative path — typically from a hostile or malformed release response.
Common situations: A malicious or spoofed GitHub API response (or compromised mirror) publishing assets with traversal names; test fixtures with unusual names; a fork whose asset names contain directory components.
Related errors
AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31).
Data as JSON: /api/errors/0a73b1528d9cb8a9.
Report an issue: GitHub.