Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/cyphar/filepath-securejoin
Proposed filepath.SecureJoin implementation
https://github.com/cyphar/filepath-securejoin
filesystem golang proposal symlink
Last synced: 4 months ago
JSON representation
Proposed filepath.SecureJoin implementation
- Host: GitHub
- URL: https://github.com/cyphar/filepath-securejoin
- Owner: cyphar
- License: bsd-3-clause
- Created: 2017-05-06T04:59:53.000Z (about 7 years ago)
- Default Branch: main
- Last Pushed: 2023-09-06T05:17:42.000Z (10 months ago)
- Last Synced: 2023-12-19T11:02:44.053Z (6 months ago)
- Topics: filesystem, golang, proposal, symlink
- Language: Go
- Homepage:
- Size: 46.9 KB
- Stars: 74
- Watchers: 8
- Forks: 16
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Lists
- my-awesome-golang - ilepath-securejoin
README
## `filepath-securejoin` ##
[![Build Status](https://github.com/cyphar/filepath-securejoin/actions/workflows/ci.yml/badge.svg)](https://github.com/cyphar/filepath-securejoin/actions/workflows/ci.yml)
An implementation of `SecureJoin`, a [candidate for inclusion in the Go
standard library][go#20126]. The purpose of this function is to be a "secure"
alternative to `filepath.Join`, and in particular it provides certain
guarantees that are not provided by `filepath.Join`.> **NOTE**: This code is *only* safe if you are not at risk of other processes
> modifying path components after you've used `SecureJoin`. If it is possible
> for a malicious process to modify path components of the resolved path, then
> you will be vulnerable to some fairly trivial TOCTOU race conditions. [There
> are some Linux kernel patches I'm working on which might allow for a better
> solution.][lwn-obeneath]
>
> In addition, with a slightly modified API it might be possible to use
> `O_PATH` and verify that the opened path is actually the resolved one -- but
> I have not done that yet. I might add it in the future as a helper function
> to help users verify the path (we can't just return `/proc/self/fd/`
> because that doesn't always work transparently for all users).This is the function prototype:
```go
func SecureJoin(root, unsafePath string) (string, error)
```This library **guarantees** the following:
* If no error is set, the resulting string **must** be a child path of
`root` and will not contain any symlink path components (they will all be
expanded).* When expanding symlinks, all symlink path components **must** be resolved
relative to the provided root. In particular, this can be considered a
userspace implementation of how `chroot(2)` operates on file paths. Note that
these symlinks will **not** be expanded lexically (`filepath.Clean` is not
called on the input before processing).* Non-existent path components are unaffected by `SecureJoin` (similar to
`filepath.EvalSymlinks`'s semantics).* The returned path will always be `filepath.Clean`ed and thus not contain any
`..` components.A (trivial) implementation of this function on GNU/Linux systems could be done
with the following (note that this requires root privileges and is far more
opaque than the implementation in this library, and also requires that
`readlink` is inside the `root` path):```go
package securejoinimport (
"os/exec"
"path/filepath"
)func SecureJoin(root, unsafePath string) (string, error) {
unsafePath = string(filepath.Separator) + unsafePath
cmd := exec.Command("chroot", root,
"readlink", "--canonicalize-missing", "--no-newline", unsafePath)
output, err := cmd.CombinedOutput()
if err != nil {
return "", err
}
expanded := string(output)
return filepath.Join(root, expanded), nil
}
```[lwn-obeneath]: https://lwn.net/Articles/767547/
[go#20126]: https://github.com/golang/go/issues/20126### License ###
The license of this project is the same as Go, which is a BSD 3-clause license
available in the `LICENSE` file.