Refactor installation and runner scripts for enhanced usability and security

- Updated the installation script to clarify that production wrappers do not include fixed test secrets, improving user guidance for local testing.
- Modified the jiggablend-manager and jiggablend-runner scripts to remove fixed test configurations, emphasizing the use of local test credentials via `make init-test`.
- Enhanced error handling in the runner script to ensure that an API key is provided, improving security and user feedback.
- Added new flags and options for the runner, including sandboxing capabilities and GPU ray tracing control, enhancing flexibility for users.
- Improved README documentation to reflect changes in usage and configuration, ensuring users have clear instructions for setup and execution.
This commit is contained in:
2026-07-12 10:01:15 -05:00
parent a3defe5cf6
commit 1a69fcfd04
47 changed files with 2718 additions and 402 deletions
+59 -1
View File
@@ -80,10 +80,54 @@ func (s *Storage) JobPath(jobID int64) string {
return filepath.Join(s.basePath, "jobs", fmt.Sprintf("%d", jobID))
}
// SanitizeFilename returns a safe basename for client-supplied names.
// Rejects empty, ".", "..", and root-like basenames.
func SanitizeFilename(name string) (string, error) {
cleaned := filepath.Clean(strings.ReplaceAll(name, "\\", "/"))
base := filepath.Base(cleaned)
// filepath.Base("..") is ".." ; Clean("/../..") style inputs can yield "/" or "."
if base == "" || base == "." || base == ".." || base == "/" || base == string(os.PathSeparator) {
return "", fmt.Errorf("invalid filename: %q", name)
}
// Reject if the cleaned path still has parent references after basenaming was skipped
if strings.Contains(cleaned, "..") && base == cleaned {
return "", fmt.Errorf("invalid filename: %q", name)
}
return base, nil
}
// SafePathUnderRoot joins root and a relative path and ensures the result stays under root.
func SafePathUnderRoot(root, rel string) (string, error) {
if rel == "" {
return "", fmt.Errorf("empty path")
}
// Normalize to forward slashes then clean
rel = filepath.ToSlash(rel)
if filepath.IsAbs(rel) || strings.HasPrefix(rel, "/") {
return "", fmt.Errorf("absolute path not allowed: %q", rel)
}
cleanRel := filepath.Clean(rel)
if cleanRel == ".." || strings.HasPrefix(cleanRel, ".."+string(os.PathSeparator)) {
return "", fmt.Errorf("path escapes root: %q", rel)
}
cleanRoot := filepath.Clean(root)
full := filepath.Join(cleanRoot, cleanRel)
cleanFull := filepath.Clean(full)
sep := string(os.PathSeparator)
if cleanFull != cleanRoot && !strings.HasPrefix(cleanFull, cleanRoot+sep) {
return "", fmt.Errorf("path escapes root: %q", rel)
}
return cleanFull, nil
}
// SaveUpload saves an uploaded file
func (s *Storage) SaveUpload(jobID int64, filename string, reader io.Reader) (string, error) {
// Sanitize filename to prevent path traversal
filename = filepath.Base(filename)
var err error
filename, err = SanitizeFilename(filename)
if err != nil {
return "", err
}
jobPath := s.JobPath(jobID)
if err := os.MkdirAll(jobPath, 0755); err != nil {
@@ -106,12 +150,26 @@ func (s *Storage) SaveUpload(jobID int64, filename string, reader io.Reader) (st
// SaveOutput saves an output file
func (s *Storage) SaveOutput(jobID int64, filename string, reader io.Reader) (string, error) {
// Sanitize filename to prevent path traversal (parity with SaveUpload)
var err error
filename, err = SanitizeFilename(filename)
if err != nil {
return "", err
}
outputPath := filepath.Join(s.outputsPath(), fmt.Sprintf("%d", jobID))
if err := os.MkdirAll(outputPath, 0755); err != nil {
return "", fmt.Errorf("failed to create output directory: %w", err)
}
filePath := filepath.Join(outputPath, filename)
// Defense in depth: ensure resolved path stays under output dir
if resolved, err := SafePathUnderRoot(outputPath, filename); err != nil {
return "", err
} else {
filePath = resolved
}
file, err := os.Create(filePath)
if err != nil {
return "", fmt.Errorf("failed to create file: %w", err)