mirror of
https://github.com/lukaszraczylo/gohoarder.git
synced 2026-10-12 00:45:16 +00:00
chore(deps): bump google.golang.org/grpc from 1.78.0 to 1.79.3 in the go_modules group across 1 directory (#36)
* chore(deps): bump google.golang.org/grpc Bumps the go_modules group with 1 update in the / directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go). Updates `google.golang.org/grpc` from 1.78.0 to 1.79.3 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.78.0...v1.79.3) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-version: 1.79.3 dependency-type: indirect dependency-group: go_modules ... Signed-off-by: dependabot[bot] <[email protected]> * Resolve merge conflicts and harden storage paths Co-authored-by: lukaszraczylo <[email protected]> --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: lukaszraczylo <[email protected]>
This commit is contained in:
co-authored by
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
copilot-swe-agent[bot] <198982749+[email protected]>
lukaszraczylo
parent
7fb596aafd
commit
edeb2eca0c
@@ -126,6 +126,6 @@ require (
|
|||||||
go.yaml.in/yaml/v3 v3.0.5 // indirect
|
go.yaml.in/yaml/v3 v3.0.5 // indirect
|
||||||
golang.org/x/sys v0.47.0 // indirect
|
golang.org/x/sys v0.47.0 // indirect
|
||||||
golang.org/x/text v0.41.0 // indirect
|
golang.org/x/text v0.41.0 // indirect
|
||||||
google.golang.org/grpc v1.78.0 // indirect
|
google.golang.org/grpc v1.79.3 // indirect
|
||||||
google.golang.org/protobuf v1.36.12 // indirect
|
google.golang.org/protobuf v1.36.12 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -298,8 +298,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b h1:
|
|||||||
google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:Xa7le7qx2vmqB/SzWUBa7KdMjpdpAHlh5QCSnjessQk=
|
google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:Xa7le7qx2vmqB/SzWUBa7KdMjpdpAHlh5QCSnjessQk=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b h1:Mv8VFug0MP9e5vUxfBcE3vUkV6CImK3cMNMIDFjmzxU=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b h1:Mv8VFug0MP9e5vUxfBcE3vUkV6CImK3cMNMIDFjmzxU=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||||
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=
|
||||||
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
|
||||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||||
google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|||||||
@@ -91,17 +91,30 @@ func (fs *FilesystemStorage) Put(ctx context.Context, key string, data io.Reader
|
|||||||
metrics.RecordStorageOperation("filesystem", "put", "error")
|
metrics.RecordStorageOperation("filesystem", "put", "error")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
dir := filepath.Dir(path)
|
relPath, err := fs.relativeToBase(path)
|
||||||
|
if err != nil {
|
||||||
|
metrics.RecordStorageOperation("filesystem", "put", "error")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dir := filepath.Dir(relPath)
|
||||||
|
root, err := os.OpenRoot(fs.basePath)
|
||||||
|
if err != nil {
|
||||||
|
metrics.RecordStorageOperation("filesystem", "put", "error")
|
||||||
|
return errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to open storage root")
|
||||||
|
}
|
||||||
|
defer root.Close() // #nosec G307 -- Best-effort cleanup of opened storage root
|
||||||
|
|
||||||
// Create directory
|
// Create directory
|
||||||
if mkErr := os.MkdirAll(dir, 0750); mkErr != nil {
|
if dir != "." {
|
||||||
metrics.RecordStorageOperation("filesystem", "put", "error")
|
if mkErr := root.MkdirAll(dir, 0750); mkErr != nil {
|
||||||
return errors.Wrap(mkErr, errors.ErrCodeStorageFailure, "failed to create directory")
|
metrics.RecordStorageOperation("filesystem", "put", "error")
|
||||||
|
return errors.Wrap(mkErr, errors.ErrCodeStorageFailure, "failed to create directory")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create temp file for atomic write
|
// Create temp file for atomic write
|
||||||
tempPath := path + ".tmp"
|
tempPath := relPath + ".tmp"
|
||||||
tempFile, err := os.Create(tempPath) // #nosec G304 -- Temp path is constructed from sanitized storage key
|
tempFile, err := root.Create(tempPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
metrics.RecordStorageOperation("filesystem", "put", "error")
|
metrics.RecordStorageOperation("filesystem", "put", "error")
|
||||||
return errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to create temp file")
|
return errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to create temp file")
|
||||||
@@ -115,14 +128,14 @@ func (fs *FilesystemStorage) Put(ctx context.Context, key string, data io.Reader
|
|||||||
|
|
||||||
written, err := io.Copy(multiWriter, data)
|
written, err := io.Copy(multiWriter, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = tempFile.Close() // #nosec G104 -- Cleanup, error not critical
|
_ = tempFile.Close() // #nosec G104 -- Cleanup, error not critical
|
||||||
_ = os.Remove(tempPath) // #nosec G104 -- Cleanup, error not critical
|
_ = root.Remove(tempPath)
|
||||||
metrics.RecordStorageOperation("filesystem", "put", "error")
|
metrics.RecordStorageOperation("filesystem", "put", "error")
|
||||||
return errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to write data")
|
return errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to write data")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tempFile.Close(); err != nil {
|
if err := tempFile.Close(); err != nil {
|
||||||
_ = os.Remove(tempPath) // #nosec G104 -- Cleanup, error not critical
|
_ = root.Remove(tempPath)
|
||||||
metrics.RecordStorageOperation("filesystem", "put", "error")
|
metrics.RecordStorageOperation("filesystem", "put", "error")
|
||||||
return errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to close temp file")
|
return errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to close temp file")
|
||||||
}
|
}
|
||||||
@@ -133,13 +146,13 @@ func (fs *FilesystemStorage) Put(ctx context.Context, key string, data io.Reader
|
|||||||
sha256Sum := hex.EncodeToString(sha256Hash.Sum(nil))
|
sha256Sum := hex.EncodeToString(sha256Hash.Sum(nil))
|
||||||
|
|
||||||
if opts.ChecksumMD5 != "" && opts.ChecksumMD5 != md5Sum {
|
if opts.ChecksumMD5 != "" && opts.ChecksumMD5 != md5Sum {
|
||||||
_ = os.Remove(tempPath) // #nosec G104 -- Cleanup, error not critical
|
_ = root.Remove(tempPath)
|
||||||
metrics.RecordStorageOperation("filesystem", "put", "checksum_error")
|
metrics.RecordStorageOperation("filesystem", "put", "checksum_error")
|
||||||
return errors.New(errors.ErrCodeChecksumMismatch, "MD5 checksum mismatch")
|
return errors.New(errors.ErrCodeChecksumMismatch, "MD5 checksum mismatch")
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.ChecksumSHA256 != "" && opts.ChecksumSHA256 != sha256Sum {
|
if opts.ChecksumSHA256 != "" && opts.ChecksumSHA256 != sha256Sum {
|
||||||
_ = os.Remove(tempPath) // #nosec G104 -- Cleanup, error not critical
|
_ = root.Remove(tempPath)
|
||||||
metrics.RecordStorageOperation("filesystem", "put", "checksum_error")
|
metrics.RecordStorageOperation("filesystem", "put", "checksum_error")
|
||||||
return errors.New(errors.ErrCodeChecksumMismatch, "SHA256 checksum mismatch")
|
return errors.New(errors.ErrCodeChecksumMismatch, "SHA256 checksum mismatch")
|
||||||
}
|
}
|
||||||
@@ -151,13 +164,13 @@ func (fs *FilesystemStorage) Put(ctx context.Context, key string, data io.Reader
|
|||||||
fs.mu.Lock()
|
fs.mu.Lock()
|
||||||
if fs.quota > 0 && fs.used+written > fs.quota {
|
if fs.quota > 0 && fs.used+written > fs.quota {
|
||||||
fs.mu.Unlock()
|
fs.mu.Unlock()
|
||||||
_ = os.Remove(tempPath) // #nosec G104 -- Cleanup, error not critical
|
_ = root.Remove(tempPath)
|
||||||
metrics.RecordStorageOperation("filesystem", "put", "quota_exceeded")
|
metrics.RecordStorageOperation("filesystem", "put", "quota_exceeded")
|
||||||
return errors.QuotaExceeded(fs.quota)
|
return errors.QuotaExceeded(fs.quota)
|
||||||
}
|
}
|
||||||
if err := os.Rename(tempPath, path); err != nil {
|
if err := root.Rename(tempPath, relPath); err != nil {
|
||||||
fs.mu.Unlock()
|
fs.mu.Unlock()
|
||||||
_ = os.Remove(tempPath) // #nosec G104 -- Cleanup, error not critical
|
_ = root.Remove(tempPath)
|
||||||
metrics.RecordStorageOperation("filesystem", "put", "error")
|
metrics.RecordStorageOperation("filesystem", "put", "error")
|
||||||
return errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to rename temp file")
|
return errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to rename temp file")
|
||||||
}
|
}
|
||||||
@@ -408,22 +421,42 @@ func (fs *FilesystemStorage) keyToPath(key string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
target := filepath.Join(fs.basePath, cleaned)
|
target := filepath.Join(fs.basePath, cleaned)
|
||||||
|
|
||||||
// Defense-in-depth: verify the resolved absolute path is contained
|
|
||||||
// within the base directory.
|
|
||||||
targetAbs, err := filepath.Abs(target)
|
targetAbs, err := filepath.Abs(target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to resolve path")
|
return "", errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to resolve path")
|
||||||
}
|
}
|
||||||
|
if err := fs.ensureWithinBase(targetAbs); err != nil {
|
||||||
|
return "", errors.New(errors.ErrCodeStorageFailure, fmt.Sprintf("path traversal rejected: %s", key))
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetAbs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *FilesystemStorage) ensureWithinBase(path string) error {
|
||||||
|
rel, err := fs.relativeToBase(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if rel == ".." || strings.HasPrefix(rel, ".."+string(os.PathSeparator)) {
|
||||||
|
return errors.New(errors.ErrCodeStorageFailure, fmt.Sprintf("path traversal rejected: %s", path))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *FilesystemStorage) relativeToBase(path string) (string, error) {
|
||||||
baseAbs, err := filepath.Abs(fs.basePath)
|
baseAbs, err := filepath.Abs(fs.basePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to resolve base path")
|
return "", errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to resolve base path")
|
||||||
}
|
}
|
||||||
if targetAbs != baseAbs && !strings.HasPrefix(targetAbs, baseAbs+string(os.PathSeparator)) {
|
pathAbs, err := filepath.Abs(path)
|
||||||
return "", errors.New(errors.ErrCodeStorageFailure, fmt.Sprintf("path traversal rejected: %s", key))
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to resolve path")
|
||||||
}
|
}
|
||||||
|
rel, err := filepath.Rel(baseAbs, pathAbs)
|
||||||
return target, nil
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to compare path")
|
||||||
|
}
|
||||||
|
return rel, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculateUsage calculates current storage usage
|
// calculateUsage calculates current storage usage
|
||||||
|
|||||||
+28
-1
@@ -130,7 +130,18 @@ func (s *Storage) Put(ctx context.Context, key string, data io.Reader, opts *sto
|
|||||||
s.logger.Warn().Err(err).Str("key", key).Msg("nfs: post-put path lookup failed; skipping fsync")
|
s.logger.Warn().Err(err).Str("key", key).Msg("nfs: post-put path lookup failed; skipping fsync")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
f, err := os.OpenFile(path, os.O_RDWR, 0) // #nosec G304 -- path resolved by sanitizing backend
|
relPath, err := relativeToBase(s.path, path)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Warn().Err(err).Str("key", key).Msg("nfs: post-put path escaped configured base; skipping fsync")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
root, err := os.OpenRoot(s.path)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Warn().Err(err).Str("path", s.path).Msg("nfs: failed to open configured base; skipping fsync")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer root.Close() // #nosec G307 -- Best-effort cleanup of opened NFS root
|
||||||
|
f, err := root.OpenFile(relPath, os.O_RDWR, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Warn().Err(err).Str("key", key).Msg("nfs: post-put open failed; skipping fsync")
|
s.logger.Warn().Err(err).Str("key", key).Msg("nfs: post-put open failed; skipping fsync")
|
||||||
return nil
|
return nil
|
||||||
@@ -226,6 +237,22 @@ func (s *Storage) GetLocalPath(ctx context.Context, key string) (string, error)
|
|||||||
return s.fs.GetLocalPath(ctx, key)
|
return s.fs.GetLocalPath(ctx, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func relativeToBase(basePath, path string) (string, error) {
|
||||||
|
baseAbs, err := filepath.Abs(basePath)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, errors.ErrCodeStorageFailure, "nfs: failed to resolve base path")
|
||||||
|
}
|
||||||
|
pathAbs, err := filepath.Abs(path)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, errors.ErrCodeStorageFailure, "nfs: failed to resolve path")
|
||||||
|
}
|
||||||
|
rel, err := filepath.Rel(baseAbs, pathAbs)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, errors.ErrCodeStorageFailure, "nfs: failed to compare path")
|
||||||
|
}
|
||||||
|
return rel, nil
|
||||||
|
}
|
||||||
|
|
||||||
// detectMountType returns the filesystem type backing path. Linux-only: on
|
// detectMountType returns the filesystem type backing path. Linux-only: on
|
||||||
// other platforms the second return value is false. Implementation walks
|
// other platforms the second return value is false. Implementation walks
|
||||||
// /proc/mounts and selects the longest matching mount point, which is the
|
// /proc/mounts and selects the longest matching mount point, which is the
|
||||||
|
|||||||
Reference in New Issue
Block a user