Release Notes v0.8.0¶
Released: 2026-10-22
Highlights¶
Path checks that give the same answer on every platform. fs.ValidatePath no
longer depends on filepath.IsAbs, fs.IsAbsAny reports a path that is
absolute or rooted anywhere, and fs.ValidateSlashPath checks paths that use
forward slashes everywhere, such as paths inside a repository.
New Features¶
fs.IsAbsAny¶
Problem solved: filepath.IsAbs answers for the platform it runs on. A
path read from a document, an archive or a configuration file must stay inside
its root on every platform, and the platforms disagree:
| Path | filepath.IsAbs on Unix |
on Windows | fs.IsAbsAny |
|---|---|---|---|
/etc/passwd |
true | false | true |
\etc\passwd |
false | false | true |
\\server\share |
false | true | true |
C:\x, C:/x |
false | true | true |
C:x |
false | false | true |
docs/a.md |
false | false | false |
Solution:
import "github.com/grokify/oscompat/fs"
if fs.IsAbsAny(entry.Name) {
return fmt.Errorf("%s: absolute path in archive", entry.Name)
}
For a path on this machine, such as a command-line argument, keep
filepath.IsAbs: there the platform's own rules are the right ones.
fs.ValidateSlashPath¶
Problem solved: a path inside a repository, an archive or a URL uses forward slashes on every platform. Checking it with OS path functions lets a backslash or a drive letter through on one platform and not another.
Solution:
if err := fs.ValidateSlashPath(src.Path); err != nil {
return fmt.Errorf("source path %q: %w", src.Path, err)
}
data, err := os.ReadFile(filepath.Join(checkout, filepath.FromSlash(src.Path)))
| Path | Result |
|---|---|
examples/a_test.go, a..b.go, .github/x.yaml |
nil |
"" |
ErrEmptyPath |
/etc/passwd, \etc\passwd, C:/x.go |
ErrAbsolutePath |
.., ../x.go, a/../../x.go |
ErrPathTraversal |
examples\x.go, ab:c.go, ./x.go, a//b.go, a/ |
ErrInvalidPath (new) |
Bug Fixes¶
fs.ValidatePathusedfilepath.IsAbs, so it rejected/etc/passwdonly off Windows, and accepted\etc\passwdand\\server\shareoff Windows. It now rejects every path thatfs.IsAbsAnyreports, on every platform.fs.SafeJoin, which calls it, gains the same fix.
Tests¶
The path tests run every case on every platform. The absolute-path cases had been kept to the platform where each passed, which hid the difference.
Documentation¶
- The fs guide explains which check to use for a path on this machine, a path from elsewhere, and a forward-slash path.
- The portable tests guide warns against
checking such paths with
filepath.IsAbs, and against keeping path cases inruntime.GOOSbranches.
Installation¶
Compatibility¶
fs.ValidatePath and fs.SafeJoin now return ErrAbsolutePath for rooted,
UNC and drive-relative paths that they accepted before on some platforms. Such
a path would have been read outside the intended root, so code that relied on
it being accepted had a traversal bug. Everything else is unchanged, and the
module still has no dependencies outside the standard library.