Reject path traversal in deploy log download handler (closes #177)

The deploy-log download handler passed a request-derived path to
http.ServeFile, which gosec flags as G703 (path traversal via taint).
The handler now opens the log through an os.Root confined to the deploy
log directory, so any escaping path is rejected at runtime (404) and the
file is streamed with http.ServeContent. A regression test plants a
sentinel outside the log dir and asserts the traversal is refused and its
contents never served; removing the guard makes that test fail. No
//nolint used.

Model: opus-4-8
This commit was merged in pull request #194.
This commit is contained in:
2026-09-22 11:01:07 +02:00
parent 1d38585431
commit f1dfd382a4
5 changed files with 161 additions and 8 deletions
+6
View File
@@ -294,6 +294,12 @@ func (svc *Service) GetLogFilePath(
return filepath.Join(svc.config.DataDir, "logs", hostname, app.Name, filename)
}
// GetLogDir returns the root directory under which all deployment log
// files live. Paths returned by GetLogFilePath are always inside it.
func (svc *Service) GetLogDir() string {
return filepath.Join(svc.config.DataDir, "logs")
}
// HasActiveDeploy returns true if there is an active deployment for the given app.
func (svc *Service) HasActiveDeploy(appID string) bool {
_, ok := svc.activeDeploys.Load(appID)