Files
EvoBGP/internal/runtimelogs/safe.go
T
DenozordecandCursor 3f0dd6c234 docs(runtime-logs): implement runtime log management features
Добавлены новые возможности для работы с файловыми логами Docker-сервисов:
- Эндпоинты для получения списка логов и хвоста лог-файла.
- Очистка лог-файлов с возможностью выбора режима (truncate или delete) и запись в аудит очистки.
- Обновлена документация и конфигурация для поддержки новых функций.

Co-authored-by: Cursor <[email protected]>
2026-06-12 19:04:53 +07:00

70 lines
1.5 KiB
Go

package runtimelogs
import (
"os"
"path/filepath"
"regexp"
"strings"
)
var filenamePattern = regexp.MustCompile(`^[a-z0-9][a-z0-9_.-]*\.log$`)
// ValidateFilename checks basename allowlist for runtime log files.
func ValidateFilename(filename string) error {
name := strings.TrimSpace(filename)
if name == "" || len(name) > 128 {
return ErrInvalidFilename
}
if name != filepath.Base(name) {
return ErrInvalidFilename
}
if strings.Contains(name, "..") {
return ErrInvalidFilename
}
if !filenamePattern.MatchString(name) {
return ErrInvalidFilename
}
return nil
}
// ResolveLogPath maps a validated basename to an absolute path under root.
func ResolveLogPath(root, filename string) (string, error) {
if err := ValidateFilename(filename); err != nil {
return "", err
}
rootAbs, err := filepath.Abs(root)
if err != nil {
return "", err
}
rootAbs = filepath.Clean(rootAbs)
candidate := filepath.Join(rootAbs, filename)
resolved, err := filepath.EvalSymlinks(candidate)
if err != nil {
if os.IsNotExist(err) {
resolved = filepath.Clean(candidate)
} else {
return "", err
}
}
resolved = filepath.Clean(resolved)
if !pathUnderRoot(resolved, rootAbs) {
return "", ErrInvalidFilename
}
if st, err := os.Lstat(resolved); err == nil {
if st.IsDir() {
return "", ErrNotAFile
}
}
return resolved, nil
}
func pathUnderRoot(path, root string) bool {
path = filepath.Clean(path)
root = filepath.Clean(root)
if path == root {
return false
}
sep := string(os.PathSeparator)
return strings.HasPrefix(path+sep, root+sep)
}