Dagu has an incomplete fix for CVE-2026-27598: path traversal via %2F-encoded slashes in locateDAG
Date: 2026-03
Affected: go/github.com/dagu-org/dagu
Attack vector: path-traversal
Category: vulnerability-disclosure
Severity: High
CVE: CVE-2026-33344
CWE: CWE-22
CVSS: 8.1 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N)

The fix for CVE-2026-27598 (commit e2ed589, PR #1691) added `ValidateDAGName` to `CreateNewDAG` and rewrote `generateFilePath` to use `filepath.Base`. This patched the CREATE path. The remaining API endpoints - GET, DELETE, RENAME, EXECUTE - all pass the `{fileName}` URL path parameter to `locateDAG` without calling `ValidateDAGName`. `%2F`-encoded forward slashes in the `{fileName}` segment traverse outside the DAGs directory. ### Vulnerable code `internal/persis/filedag/store.go`, lines 508-513: ```go func (store *Storage) locateDAG(nameOrPath string) (string, error) { if strings.Contains(nameOrPath, string(filepath.Separator)) { foundPath, err := findDAGFile(nameOrPath) if err == nil { return foundPath, nil // returns arbitrary resolved path } } // ...safe searchPaths branch follows ``` `findDAGFile` resolves the path with `filepath.Abs` and checks only that the file exists with a YAML extension. No containment check against `baseDir`. Chi v5 routes using `r.URL.RawPath` when set. The pattern `/dags/{fileName}/spec` captures `..%2F..%2Fetc%2Ftarget.yaml` as a single path segment. The oapi-codegen runtime calls `url.PathUnescape`, producing `../../etc/target.yaml`. This decoded string reaches `locateDAG` with the `/` separator intact. Go's `net/http.ServeMux` would normally redirect paths containing `..`, but dagu binds the chi mux directly to `&http.Server{Handler: r}` (server.go:833-834), so no path cleaning fires. #


Mitigations:

Architectural layers (MAESTRO):