Repository navigation
Defense-in-depth: 13 path-injection findings in backup code (CodeQL/GHAS) #2
Description
Kontext
GitHub Advanced Security (CodeQL) hat in #1 13 path-injection-Findings (high severity) im Backup-Code gemeldet. Build/Test (5 Matrix-Jobs) und unser eigener Analyze (go, autobuild)-Workflow sind sauber durchgelaufen — das hier ist ein separater GHAS-Scan-Befund, der die PR-Diff gegen develop analysiert.
Risiko-Einschätzung
Aktuell nicht akut ausnutzbar. Alle betroffenen Pfade werden aus dem Backup-Identifier (UUID) gebildet, der vom Panel via JWT signiert übergeben wird. Solange der Panel-Auth-Pfad hält, ist der Identifier kontrolliert. Aber: Defense in depth fehlt — kein explizites filepath.Clean + Prefix-Containment-Check vor os.Stat / os.Remove / os.ReadDir, daher kann CodeQL die Sicherheit nicht beweisen.
Ursprung (git blame)
| Findings | Eingeführt durch |
|---|---|
| 12 | Rene-Roscher Fork-Commits 2025-09 (Backup-Restore-Erweiterungen dieses Forks) |
| 1 | backup_local.go:91 os.Remove(b.Path()) — Dane Everitt 2020-04-17 (reines Upstream-Pterodactyl-Code) |
→ Das Pattern existiert auch im pterodactyl-Upstream, ist dort nur nie von einem CodeQL-Run gesehen worden.
Liste der Findings
-
server/server.go:475—os.ReadDir(backupDir) -
server/server.go:529—os.Remove(filePath) -
server/backup.go:775—os.Stat(backupPath) -
server/backup.go:786—os.Open(backupPath) -
server/backup.go:846—os.Open(backupPath) -
server/backup.go:937—os.Open(backupPath) -
server/backup.go:1044—os.Stat(b.Path()) -
server/backup/backup_s3.go:98—os.Stat(s.Path()) -
server/backup/backup_local.go:64—os.Stat(backupPath) -
server/backup/backup_local.go:91—os.Remove(b.Path())(upstream-Code) -
server/backup/backup_local.go:177—os.ReadDir(backupDir) -
server/backup/backup_local.go:231—os.Remove(filePath) -
router/router_server_backup.go:453—os.Stat(s3Backup.Path())
Alle Rule: go/path-injection, Severity: high.
Empfohlene Lösung
Zentrale Helper-Funktion einziehen, die für Backup-Pfade folgendes erzwingt:
func safeBackupPath(identifier string) (string, error) {
if !validBackupIdentifier(identifier) { // z.B. UUID-Regex
return "", errors.New("invalid backup identifier")
}
clean := filepath.Clean(filepath.Join(config.BackupDirectory, identifier))
if !strings.HasPrefix(clean, config.BackupDirectory+string(os.PathSeparator)) {
return "", errors.New("path escapes backup directory")
}
return clean, nil
}Anwenden überall wo b.Path() / backupPath direkt in os.*-Calls fließt. Erfüllt CodeQL UND liefert echte Defense-in-depth, falls jemals der JWT-Layer kompromittiert wird.
Referenzen
- PR mit Erstmeldung: Sync emeraldhost/wings with Rene-Roscher fork features #1
- CodeQL-Alerts: https://github.com/emeraldhost/wings/security/code-scanning?query=pr%3A1+tool%3ACodeQL+is%3Aopen
- Rule: https://codeql.github.com/codeql-query-help/go/go-path-injection/
Priorität
Niedrig (P3) — kein akut ausnutzbarer Pfad bekannt. Adressieren wenn das Backup-Modul ohnehin angefasst wird, oder im Rahmen eines defensiven Security-Sweeps.
Activity