security(offbox): validate host/user/repo before the ssh exec (option-injection guard)
Background commit review flagged command/option injection: operator-provided host/user/ repo_path flow into restic's ssh -s sftp command. Reject leading '-' (ssh option injection, e.g. -oProxyCommand) + metacharacters/traversal; OffboxConfigured fails closed on an invalid target. Companion test covers the injection cases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HxLA1mZurFq9kt8hneFeCs
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/backup"
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/settings"
|
||||
)
|
||||
|
||||
@@ -50,6 +51,12 @@ func (s *Server) offboxConfigHandler(w http.ResponseWriter, r *http.Request) {
|
||||
offboxRedirect(w, r, "A tárhely útvonalának abszolútnak kell lennie (/-rel kezdődjön).", true)
|
||||
return
|
||||
}
|
||||
// Validate BEFORE persisting — host/user/repo flow into the ssh command restic runs; reject anything
|
||||
// that could inject an ssh option (leading '-') or a metacharacter (the security boundary).
|
||||
if err := backup.ValidateOffboxTarget(&settings.OffboxTarget{Host: host, User: user, RepoPath: repoPath, Port: port}); err != nil {
|
||||
offboxRedirect(w, r, "Érvénytelen beállítás: "+err.Error(), true)
|
||||
return
|
||||
}
|
||||
// First-time config requires the SSH key + a pinned known-host line (no blind TOFU).
|
||||
existing := s.backupMgr.OffboxConfigured()
|
||||
if !existing && (strings.TrimSpace(sshKey) == "" || strings.TrimSpace(knownHosts) == "") {
|
||||
|
||||
Reference in New Issue
Block a user