This PR updates security-critical dependencies addressing authentication
and data parsing vulnerabilities.
**Authentication Security:**
- github.com/coreos/go-oidc: v2.3.0 -> v2.5.0
- Security fix: Now verifies token signature BEFORE validating payload
- Prevents potential processing of tampered tokens before cryptographic
verification
- github.com/cyphar/filepath-securejoin: v0.6.0 -> v0.6.1
- Security fix: Fixed seccomp fallback logic - library now properly falls
back to safer O_PATH resolver when openat2(2) is denied by seccomp-bpf
- Fixed file descriptor leak in openat2 wrapper during RESOLVE_IN_ROOT
- cyphar.com/go-pathrs: v0.2.1 -> v0.2.2
- Companion update to filepath-securejoin
**Protobuf Security:**
- google.golang.org/protobuf: v1.36.8 -> v1.36.11
- Security fix: Added recursion limit check in lazy decoding validation
- Prevents potential stack exhaustion attacks via maliciously crafted
protobuf messages
- Also adds support for URL chars in type URLs in text-format
These updates are critical for:
- OIDC authentication in kube-apiserver
- Container filesystem path resolution (used by container runtimes)
- Protobuf message parsing throughout the codebase
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Davanum Srinivas <davanum@gmail.com>
|
||
|---|---|---|
| .. | ||
| internal/consts | ||
| pathrs-lite | ||
| .golangci.yml | ||
| CHANGELOG.md | ||
| codecov.yml | ||
| COPYING.md | ||
| doc.go | ||
| join.go | ||
| LICENSE.BSD | ||
| LICENSE.MPL-2.0 | ||
| README.md | ||
| VERSION | ||
| vfs.go | ||
filepath-securejoin
Old API
This library was originally just an implementation of SecureJoin which was
intended to be included in the Go standard library as a safer
filepath.Join that would restrict the path lookup to be inside a root
directory.
The implementation was based on code that existed in several container
runtimes. Unfortunately, this API is fundamentally unsafe against attackers
that can modify path components after SecureJoin returns and before the
caller uses the path, allowing for some fairly trivial TOCTOU attacks.
SecureJoin (and SecureJoinVFS) are still provided by this library to
support legacy users, but new users are strongly suggested to avoid using
SecureJoin and instead use the new api or switch to
libpathrs.
With the above limitations in mind, this library guarantees the following:
-
If no error is set, the resulting string must be a child path of
rootand 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.Cleanis not called on the input before processing). -
Non-existent path components are unaffected by
SecureJoin(similar tofilepath.EvalSymlinks's semantics). -
The returned path will always be
filepath.Cleaned 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 and is trustworthy):
package securejoin
import (
"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
}
New API
While we recommend users switch to libpathrs as soon as it has a stable release, some methods implemented by libpathrs have been ported to this library to ease the transition. These APIs are only supported on Linux.
These APIs are implemented such that filepath-securejoin will
opportunistically use certain newer kernel APIs that make these operations far
more secure. In particular:
-
All of the lookup operations will use
openat2on new enough kernels (Linux 5.6 or later) to restrict lookups through magic-links and bind-mounts (for certain operations) and to make use ofRESOLVE_IN_ROOTto efficiently resolve symlinks within a rootfs. -
The APIs provide hardening against a malicious
/procmount to either detect or avoid being tricked by a/procthat is not legitimate. This is done usingopenat2for all users, and privileged users will also be further protected by usingfsopenandopen_tree(Linux 5.2 or later).
OpenInRoot
func OpenInRoot(root, unsafePath string) (*os.File, error)
func OpenatInRoot(root *os.File, unsafePath string) (*os.File, error)
func Reopen(handle *os.File, flags int) (*os.File, error)
OpenInRoot is a much safer version of
path, err := securejoin.SecureJoin(root, unsafePath)
file, err := os.OpenFile(path, unix.O_PATH|unix.O_CLOEXEC)
that protects against various race attacks that could lead to serious security
issues, depending on the application. Note that the returned *os.File is an
O_PATH file descriptor, which is quite restricted. Callers will probably need
to use Reopen to get a more usable handle (this split is done to provide
useful features like PTY spawning and to avoid users accidentally opening bad
inodes that could cause a DoS).
Callers need to be careful in how they use the returned *os.File. Usually it
is only safe to operate on the handle directly, and it is very easy to create a
security issue. libpathrs provides far more helpers to make using
these handles safer -- there is currently no plan to port them to
filepath-securejoin.
OpenatInRoot is like OpenInRoot except that the root is provided using an
*os.File. This allows you to ensure that multiple OpenatInRoot (or
MkdirAllHandle) calls are operating on the same rootfs.
NOTE: Unlike
SecureJoin,OpenInRootwill error out as soon as it hits a dangling symlink or non-existent path. This is in contrast toSecureJoinwhich treated non-existent components as though they were real directories, and would allow for partial resolution of dangling symlinks. These behaviours are at odds with how Linux treats non-existent paths and dangling symlinks, and so these are no longer allowed.
MkdirAll
func MkdirAll(root, unsafePath string, mode int) error
func MkdirAllHandle(root *os.File, unsafePath string, mode int) (*os.File, error)
MkdirAll is a much safer version of
path, err := securejoin.SecureJoin(root, unsafePath)
err = os.MkdirAll(path, mode)
that protects against the same kinds of races that OpenInRoot protects
against.
MkdirAllHandle is like MkdirAll except that the root is provided using an
*os.File (the reason for this is the same as with OpenatInRoot) and an
*os.File of the final created directory is returned (this directory is
guaranteed to be effectively identical to the directory created by
MkdirAllHandle, which is not possible to ensure by just using OpenatInRoot
after MkdirAll).
NOTE: Unlike
SecureJoin,MkdirAllwill error out as soon as it hits a dangling symlink or non-existent path. This is in contrast toSecureJoinwhich treated non-existent components as though they were real directories, and would allow for partial resolution of dangling symlinks. These behaviours are at odds with how Linux treats non-existent paths and dangling symlinks, and so these are no longer allowed. This means thatMkdirAllwill not create non-existent directories referenced by a dangling symlink.
License
SPDX-License-Identifier: BSD-3-Clause AND MPL-2.0
Some of the code in this project is derived from Go, and is licensed under a
BSD 3-clause license (available in LICENSE.BSD). Other files (many of which
are derived from libpathrs) are licensed under the Mozilla Public
License version 2.0 (available in LICENSE.MPL-2.0). If you are using the
"New API" described above, you are probably using code from files
released under this license.
Every source file in this project has a copyright header describing its license. Please check the license headers of each file to see what license applies to it.
See COPYING.md for some more details.