NIST deprecates RSA-2048 from 2030. Find every one of them before attackers do.
🐹
🐹 Go
Not in CISA KEV
MEDIUM severity

CVE-2026-102943 — dagu

MEDIUMFix: dagucloud/dagu@c15c540

CVE-2026-102943 is a medium-severity (CVSS 6.5) Path Traversal vulnerability in github.com/dagu-org/dagu/v2. A fix is available for github.com/dagu-org/dagu/v2 — see the affected versions and patch details below.

Dagu MCP DAG specification read bypasses path containment and workspace isolation

Also known asGHSA-5m6c-38r8-5w76
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Nov 11, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

No confirmed exploitation observed yet

  • CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-102943.

EPSS Exploitation Probability

via FIRST.org ↗
0.4%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs36th percentile — riskier than 36% of all scored CVEsHighest risk

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

Where this sits among everything scored

Real-World Exposure

1 pkg affected
🐹github.com/dagu-org/dagu/v2

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.

Description

Summary

The traversal fix for CVE-2026-33344 was implemented as HTTP middleware installed only in the chi handler chain, but the MCP service calls the same API method in process, so arbitrary YAML file read is reachable again through the MCP tool surface with a viewer-role key. Read-only, limited to .yaml/.yml targets. Confirmed at HEAD f6c039f (post v2.10.7).

The defect

The fix for CVE-2026-33344 is a reflection-based HTTP middleware (internal/frontend/.../api.go, roughly lines 553-597) that inspects a request field named FileName and rejects anything that is not a plain name. It is installed in exactly one place: the chi strict-handler chain (api.go around line 419).

The MCP service does not go through that chain. internal/service/mcp/server.go calls the API method directly as an in-process Go call:

func (svc *Service) getDAGSpec(ctx context.Context, name string) (map[string]any, error) {   // line 307
    resp, err := svc.api.GetDAGSpec(ctx, daguapi.GetDAGSpecRequestObject{
        FileName: daguapi.DAGFileName(name),                                                 // line 309
    })

No HTTP request is constructed, so no middleware executes, and the underlying resolver is still uncontained:

func (store *Storage) locateDAG(nameOrPath string) (string, error) {                 // line 1041
    if strings.Contains(nameOrPath, string(filepath.Separator)) {                    // line 1042
        foundPath, err := findDAGFile(nameOrPath)
        if err == nil {
            return foundPath, nil                                                    // line 1045, no containment check
        }
    }

An absolute path contains a separator, so it takes the first branch and is returned as-is, with no check that it falls under store.baseDir or any entry in store.searchPaths.

Verification

Verified end to end using the project's own conformance/mcptest harness against a real running HTTP server, not by source reading:

dagu_read {"target":"dag_spec","name":"/abs/outside/secret.yaml"}
-> HTTP 200, full file contents returned in data.spec

This also succeeded with a viewer-role API key on an auth-enabled server (auth.mode: builtin), so it is not admin-only. Control test that makes this a residual: the equivalent REST request is correctly blocked (400, "name must only contain alphanumeric characters..."). The HTTP lane is fixed; the MCP lane is not.

Bounded impact: read only (dagu_change and dagu_execute are both blocked by spec-level name validation; I tested both); only .yaml/.yml targets. Secondary: GetDAGSpec skips the requireWorkspaceVisible check its sibling handlers run, so this also crosses workspace isolation.

Suggested fix

Move the containment check out of HTTP middleware and into locateDAG itself, rejecting any resolved path that does not fall under baseDir or a configured search path. A middleware that runs on only one of two transports into the same API cannot hold the boundary; the resolver is the correct chokepoint since both transports converge there. Separately, add requireWorkspaceVisible to GetDAGSpec to match its siblings.

Tooling

AI assistance was used while investigating. The traversal was reproduced against a real running server through the project's own MCP conformance harness, including with a viewer-role API key, and the REST control test confirms the HTTP lane is blocked. Confirmed in the uncontained locateDAG branch and the direct in-process GetDAGSpec call at HEAD.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐹Gogithub.com/dagu-org/dagu/v2all versions2.11.0go get github.com/dagu-org/dagu/v2@v2.11.0

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/dagu-org/dagu/v2, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update github.com/dagu-org/dagu/v2 to 2.11.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-102943 is resolved across your whole dependency graph.

  3. Workarounds

    Resolve every user-supplied path to its canonical form and reject anything that escapes the intended directory, and run the component under an account that has no read or write access outside the directory it legitimately serves.

Frequently Asked Questions

## Summary The traversal fix for CVE-2026-33344 was implemented as HTTP middleware installed only in the chi handler chain, but the MCP service calls the same API method in process, so arbitrary YAML file read is reachable again through the MCP tool surface with a viewer-role key. Read-only, limited to .yaml/.yml targets. Confirmed at HEAD f6c039f (post v2.10.7). ## The defect The fix for CVE-2026-33344 is a reflection-based HTTP middleware (internal/frontend/.../api.go, roughly lines 553-597) that inspects a request field named FileName and rejects anything that is not a plain name. It is
O3 Security · Impact-Aware SCA

Is CVE-2026-102943 in your dependencies?

Find it across Go, including transitive dependencies.

CVE-2026-102943: dagu — Fixed in 2.11.0