From 8801e2ea10a11f572f56754ffe8ce06ad3a5c66a Mon Sep 17 00:00:00 2001 From: Snider Date: Fri, 20 Mar 2026 15:43:19 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20final=20AX=20audit=20=E2=80=94=209=20rem?= =?UTF-8?q?aining=20violations=20resolved?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - fs.go: propagate validatePath failures (return vp) instead of bare Result{} - app.go: Find() returns Result instead of *App - log.go: fmt import removed — uses Sprint/Sprintf/Print from string.go/utils.go - string.go: added Sprint() and Sprintf() wrappers for any-to-string formatting Co-Authored-By: Virgil --- pkg/core/app.go | 16 +++++++++------- pkg/core/fs.go | 8 ++++---- pkg/core/log.go | 11 +++++------ pkg/core/string.go | 16 ++++++++++++++++ tests/app_test.go | 13 ++++++------- 5 files changed, 40 insertions(+), 24 deletions(-) diff --git a/pkg/core/app.go b/pkg/core/app.go index 18e976d..582f452 100644 --- a/pkg/core/app.go +++ b/pkg/core/app.go @@ -33,20 +33,22 @@ type App struct { } -// Find locates a program on PATH and returns a App for it. -// Returns nil if not found. -func Find(filename, name string) *App { +// Find locates a program on PATH and returns a Result containing the App. +// +// r := core.Find("node", "Node.js") +// if r.OK { app := r.Value.(*App) } +func Find(filename, name string) Result { path, err := exec.LookPath(filename) if err != nil { - return nil + return Result{err, false} } abs, err := filepath.Abs(path) if err != nil { - return nil + return Result{err, false} } - return &App{ + return Result{&App{ Name: name, Filename: filename, Path: abs, - } + }, true} } diff --git a/pkg/core/fs.go b/pkg/core/fs.go index fc8efd6..47a6d85 100644 --- a/pkg/core/fs.go +++ b/pkg/core/fs.go @@ -91,7 +91,7 @@ func (m *Fs) validatePath(p string) Result { func (m *Fs) Read(p string) Result { vp := m.validatePath(p) if !vp.OK { - return Result{} + return vp } data, err := os.ReadFile(vp.Value.(string)) if err != nil { @@ -176,7 +176,7 @@ func (m *Fs) Exists(p string) bool { func (m *Fs) List(p string) Result { vp := m.validatePath(p) if !vp.OK { - return Result{} + return vp } return Result{}.Result(os.ReadDir(vp.Value.(string))) } @@ -271,11 +271,11 @@ func (m *Fs) DeleteAll(p string) Result { func (m *Fs) Rename(oldPath, newPath string) Result { oldVp := m.validatePath(oldPath) if !oldVp.OK { - return Result{} + return oldVp } newVp := m.validatePath(newPath) if !newVp.OK { - return Result{} + return newVp } if err := os.Rename(oldVp.Value.(string), newVp.Value.(string)); err != nil { return Result{err, false} diff --git a/pkg/core/log.go b/pkg/core/log.go index 3faf6ee..769286f 100644 --- a/pkg/core/log.go +++ b/pkg/core/log.go @@ -6,7 +6,6 @@ package core import ( - "fmt" goio "io" "os" "os/user" @@ -228,21 +227,21 @@ func (l *Log) log(level Level, prefix, msg string, keyvals ...any) { } // Redaction logic - keyStr := fmt.Sprintf("%v", key) + keyStr := Sprint(key) if slices.Contains(redactKeys, keyStr) { val = "[REDACTED]" } // Secure formatting to prevent log injection if s, ok := val.(string); ok { - kvStr += fmt.Sprintf("%v=%q", key, s) + kvStr += Sprintf("%v=%q", key, s) } else { - kvStr += fmt.Sprintf("%v=%v", key, val) + kvStr += Sprintf("%v=%v", key, val) } } } - _, _ = fmt.Fprintf(output, "%s %s %s%s\n", timestamp, prefix, msg, kvStr) + Print(output, "%s %s %s%s", timestamp, prefix, msg, kvStr) } // Debug logs a debug message with optional key-value pairs. @@ -387,7 +386,7 @@ func (lp *LogPanic) Recover() { } err, ok := r.(error) if !ok { - err = NewError(fmt.Sprint("panic: ", r)) + err = NewError(Sprint("panic: ", r)) } lp.log.Error("panic recovered", "err", err, diff --git a/pkg/core/string.go b/pkg/core/string.go index 02db67f..4c64aa7 100644 --- a/pkg/core/string.go +++ b/pkg/core/string.go @@ -7,6 +7,7 @@ package core import ( + "fmt" "strings" "unicode/utf8" ) @@ -127,6 +128,21 @@ func NewReader(s string) *strings.Reader { return strings.NewReader(s) } +// Sprint converts any value to its string representation. +// +// core.Sprint(42) // "42" +// core.Sprint(err) // "connection refused" +func Sprint(args ...any) string { + return fmt.Sprint(args...) +} + +// Sprintf formats a string with the given arguments. +// +// core.Sprintf("%v=%q", "key", "value") // `key="value"` +func Sprintf(format string, args ...any) string { + return fmt.Sprintf(format, args...) +} + // Concat joins variadic string parts into one string. // Hook point for validation, sanitisation, and security checks. // diff --git a/tests/app_test.go b/tests/app_test.go index 2d05008..230a234 100644 --- a/tests/app_test.go +++ b/tests/app_test.go @@ -27,14 +27,13 @@ func TestApp_Runtime_Good(t *testing.T) { } func TestApp_Find_Good(t *testing.T) { - app := Find("go", "go") - // Find looks for a binary — go should be in PATH - if app != nil { - assert.NotEmpty(t, app.Path) - } + r := Find("go", "go") + assert.True(t, r.OK) + app := r.Value.(*App) + assert.NotEmpty(t, app.Path) } func TestApp_Find_Bad(t *testing.T) { - app := Find("nonexistent-binary-xyz", "test") - assert.Nil(t, app) + r := Find("nonexistent-binary-xyz", "test") + assert.False(t, r.OK) }