fix: final AX audit — 9 remaining violations resolved
- 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 <virgil@lethean.io>
This commit is contained in:
parent
f8e1459bd1
commit
8801e2ea10
5 changed files with 40 additions and 24 deletions
|
|
@ -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}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue