fix: fail closed thothctl secret sources

This commit is contained in:
2026-08-04 17:17:39 +02:00
parent 4158990c10
commit 35a000222c
7 changed files with 366 additions and 49 deletions
+3 -12
View File
@@ -3,11 +3,11 @@ package output
import (
"errors"
"io"
"os"
"regexp"
"sort"
"strings"
"github.com/aritmolab/thothii/tools/thothctl/internal/safeio"
)
var credentialField = regexp.MustCompile(`(?im)(\b[\w.-]*(?:password|token|key)[\w.-]*\s*[:=]\s*)(?:"[^"\r\n]*"|'[^'\r\n]*'|[^\s,;]+)`)
@@ -48,18 +48,9 @@ func SecretValuesFromFiles(paths []string) ([]string, error) {
}
func readSecretFile(path string) (string, error) {
info, err := os.Lstat(path)
if err != nil || !info.Mode().IsRegular() || info.Size() > maxSecretFileBytes {
return "", errors.New("declared secret file could not be read")
}
file, err := os.Open(path)
contents, err := safeio.ReadCanonicalRegular(path, maxSecretFileBytes)
if err != nil {
return "", errors.New("declared secret file could not be read")
}
defer file.Close()
contents, err := io.ReadAll(io.LimitReader(file, maxSecretFileBytes+1))
if err != nil || len(contents) > maxSecretFileBytes {
return "", errors.New("declared secret file could not be read")
}
return strings.TrimRight(string(contents), "\r\n"), nil
}
@@ -19,7 +19,7 @@ func TestSanitizeRedactsPasswordTokenAndKeyFields(t *testing.T) {
func TestSanitizeRedactsSecretFileContents(t *testing.T) {
t.Parallel()
secretFile := filepath.Join(t.TempDir(), "provider-token")
secretFile := filepath.Join(physicalTempDir(t), "provider-token")
if err := os.WriteFile(secretFile, []byte("top-secret-value\n"), 0o600); err != nil {
t.Fatal(err)
}
@@ -37,7 +37,7 @@ func TestSanitizeRedactsSecretFileContents(t *testing.T) {
func TestSecretValuesFromFilesRejectsOversizedFiles(t *testing.T) {
t.Parallel()
secretFile := filepath.Join(t.TempDir(), "oversized-token")
secretFile := filepath.Join(physicalTempDir(t), "oversized-token")
if err := os.WriteFile(secretFile, make([]byte, 64*1024+1), 0o600); err != nil {
t.Fatal(err)
}
@@ -46,3 +46,17 @@ func TestSecretValuesFromFilesRejectsOversizedFiles(t *testing.T) {
t.Fatal("SecretValuesFromFiles() error = nil, want oversized-file error")
}
}
func physicalTempDir(t *testing.T) string {
t.Helper()
root, err := filepath.EvalSymlinks(os.TempDir())
if err != nil {
t.Fatal(err)
}
directory, err := os.MkdirTemp(root, "thothctl-output-test-")
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { _ = os.RemoveAll(directory) })
return directory
}