fix(auth): harden Windows auth store privacy
This commit is contained in:
@@ -6,7 +6,6 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/aritmolab/thothii/tools/tht/internal/safeio"
|
||||
"github.com/gofrs/flock"
|
||||
@@ -112,26 +111,15 @@ func decodeStrictYAML(contents []byte, destination any) error {
|
||||
}
|
||||
|
||||
func requirePrivateDirectory(directory string) error {
|
||||
if err := safeio.ValidateCanonicalPath(directory); err != nil {
|
||||
return err
|
||||
}
|
||||
info, err := os.Lstat(directory)
|
||||
if err != nil || !info.IsDir() || info.Mode()&os.ModeSymlink != 0 {
|
||||
return safeio.ErrUnsafeFile
|
||||
}
|
||||
resolved, err := filepath.EvalSymlinks(directory)
|
||||
if err != nil || resolved != directory {
|
||||
return safeio.ErrUnsafeFile
|
||||
}
|
||||
if runtime.GOOS != "windows" && info.Mode().Perm() != 0o700 {
|
||||
return safeio.ErrUnsafeFile
|
||||
}
|
||||
return nil
|
||||
return safeio.ValidatePrivateDirectory(directory)
|
||||
}
|
||||
|
||||
func readPrivateFile(path string) ([]byte, error) {
|
||||
if err := safeio.ValidatePrivateRegular(path); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
before, err := os.Lstat(path)
|
||||
if err != nil || !before.Mode().IsRegular() || before.Mode()&os.ModeSymlink != 0 || (runtime.GOOS != "windows" && before.Mode().Perm() != 0o600) {
|
||||
if err != nil {
|
||||
return nil, safeio.ErrUnsafeFile
|
||||
}
|
||||
contents, err := safeio.ReadCanonicalRegular(path, maxYAMLBytes)
|
||||
@@ -139,7 +127,10 @@ func readPrivateFile(path string) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
after, err := os.Lstat(path)
|
||||
if err != nil || !after.Mode().IsRegular() || after.Mode()&os.ModeSymlink != 0 || (runtime.GOOS != "windows" && after.Mode().Perm() != 0o600) || !os.SameFile(before, after) {
|
||||
if err != nil || !os.SameFile(before, after) {
|
||||
return nil, safeio.ErrUnsafeFile
|
||||
}
|
||||
if err := safeio.ValidatePrivateRegular(path); err != nil {
|
||||
return nil, safeio.ErrUnsafeFile
|
||||
}
|
||||
return contents, nil
|
||||
@@ -149,14 +140,18 @@ func acquireLock(directory string) (*flock.Flock, error) {
|
||||
path := filepath.Join(directory, lockFileName)
|
||||
if _, err := os.Lstat(path); errors.Is(err, os.ErrNotExist) {
|
||||
if err := safeio.WriteCanonicalNewFile(path, nil, 0o600); err != nil {
|
||||
info, statErr := os.Lstat(path)
|
||||
if statErr != nil || !info.Mode().IsRegular() || info.Mode()&os.ModeSymlink != 0 || (runtime.GOOS != "windows" && info.Mode().Perm() != 0o600) {
|
||||
// A competing mutation may have created the lock after our Lstat. Accept only
|
||||
// that exact safe/private lock; every other creation failure remains unsafe.
|
||||
if validateErr := safeio.ValidatePrivateRegular(path); validateErr != nil {
|
||||
return nil, safeio.ErrUnsafeFile
|
||||
}
|
||||
}
|
||||
} else if err != nil {
|
||||
return nil, safeio.ErrUnsafeFile
|
||||
}
|
||||
if err := safeio.ValidatePrivateRegular(path); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lock := flock.New(path, flock.SetPermissions(0o600))
|
||||
if err := lock.Lock(); err != nil {
|
||||
return nil, errInvalidAuthenticationConfig
|
||||
|
||||
Reference in New Issue
Block a user