CVE-2026-53519 - Nezha dashboard path traversal leaks JWT secret

Nezha before 2.0.13 has a pre-auth dashboard fallback path traversal. The fallback treats any raw URL path starting with /dashboard as a dashboard asset request, trims the prefix, joins the result under the admin template directory, and serves local files. Prefix-confusion payloads such as /dashboard../... can escape the intended asset root and disclose files such as data/config.yaml.

In default deployments that file can contain the HS256 jwt_secret_key, which enables forged dashboard sessions and administrative account takeover.

When to use it

Use this recipe when a repository builds, forks, vendors, deploys, or customizes Nezha dashboard runtimes and dashboard routes may be reachable by untrusted users. It is especially important when Nezha config, SQLite databases, JWT secrets, agent secrets, OAuth secrets, API keys, or logs live near the dashboard working directory or static-serving roots.

Use it to upgrade Nezha and verify static-file containment with local fixtures. Do not use it to request secret-bearing paths from live dashboards.

Inputs

  • Go modules, forks, vendored code, Dockerfiles, images, Compose/Helm/Kubernetes manifests, SBOMs, generated dependency reports, and deployment docs that may include github.com/nezhahq/nezha.
  • Dashboard route handlers, NoRoute fallback logic, HasPrefix, TrimPrefix, path.Join, http.ServeFile, template roots, static roots, and user-template fallback paths.
  • Reachability evidence for dashboard routes: internet, VPN, partner network, tenant users, internal operators, reverse proxies, CDNs, or private-only networks.
  • Sensitive file placement: data/config.yaml, SQLite DBs, JWT secret keys, agent secrets, OAuth/API credentials, logs, and mounted config directories.
  • Operator rotation/invalidation ownership for JWT signing keys, dashboard sessions, agent secrets, OAuth clients, API keys, and admin credentials.

Affected versions

  • Vulnerable: github.com/nezhahq/nezha <2.0.13
  • Fixed: 2.0.13+
  • Affected surface: dashboard NoRoute static fallback and local filesystem serving

Indicator-of-exposure

  • The repository deploys, vendors, forks, or builds Nezha <2.0.13.
  • Dashboard routes are internet reachable or reachable by untrusted users.
  • Static fallback logic uses raw string prefix checks and path.Join() before filesystem reads.
  • Configuration files, SQLite databases, JWT secrets, agent secrets, OAuth secrets, or API keys live near the dashboard working directory.

Quick checks:

rg -n "nezhahq/nezha|fallbackToFrontend|NoRoute|HasPrefix\\(|TrimPrefix\\(|ServeFile|AdminTemplate|JWTSecretKey" .
go list -m all | rg "nezhahq/nezha"

Windows:

rg -n "nezhahq/nezha|fallbackToFrontend|NoRoute|HasPrefix\\(|TrimPrefix\\(|ServeFile|AdminTemplate|JWTSecretKey" .
go list -m all | rg "nezhahq/nezha"

Remediation strategy

  • Upgrade Nezha to 2.0.13+.
  • Make dashboard path matching segment-aware: /dashboard and /dashboard/ are valid, but /dashboard.. is not.
  • Resolve static file paths under a fixed root and reject any final path that escapes that root before calling os.Stat() or http.ServeFile().
  • Move sensitive config and database files outside any static-serving working tree.
  • Rotate JWT, agent, OAuth, API, and dashboard credentials if the vulnerable dashboard was reachable.

The prompt

Model context: this prompt was generated by GPT 5.5 Extra High reasoning.

You are remediating CVE-2026-53519 / GHSA-5c25-7vpj-9mqh in Nezha. A pre-auth
dashboard path traversal can disclose config files and JWT signing secrets.
Produce exactly one output:

- A reviewer-ready PR/change request that upgrades Nezha, hardens static file
  containment, adds regression tests, and documents credential rotation, or
- TRIAGE.md if this repository does not control an affected Nezha runtime,
  fork, image, or deployment.

## Rules

- Scope only CVE-2026-53519 and directly related dashboard static fallback
  behavior.
- Treat config files, SQLite databases, JWT secrets, agent secrets, OAuth
  secrets, API keys, and logs as sensitive.
- Do not request live secret-bearing paths from shared or production systems.
- Do not print recovered secrets in logs, PRs, tests, or screenshots.
- Do not auto-merge.

## Steps

1. Inventory every Nezha module, fork, image, manifest, SBOM, and deployment
   artifact controlled by this repository.
2. Confirm whether any resolved version is `<2.0.13`.
3. Trace dashboard `NoRoute` fallback handlers, static file serving, template
   roots, and filesystem path joins.
4. If this repository does not control an affected Nezha runtime, stop with
   `TRIAGE.md` naming the owner and required fixed version `2.0.13+`.
5. Upgrade to `2.0.13+` and refresh `go.sum`, images, SBOMs, deployment
   manifests, and dependency reports.
6. Add or verify static file containment:
   - match dashboard paths by segment, not raw prefix;
   - normalize and resolve final paths;
   - reject absolute paths and traversal segments from untrusted input;
   - verify the final path remains under the intended static root before any
     filesystem call;
   - apply equivalent protection to user-template fallback paths.
7. Add regression tests proving `/dashboard../data/config.yaml`,
   encoded-dot variants, and encoded-slash variants do not disclose files.
8. Add a PR body section named `CVE-2026-53519 operator actions` covering:
   - Nezha versions before and after;
   - dashboard exposure boundary;
   - config/database locations reviewed;
   - JWT, agent, OAuth, API, and dashboard credential rotation guidance;
   - validation that passed.
9. Run available validation: `go test`, build, image build, deployment render,
   and dependency/security scans.
10. Use PR title:
    `fix(sec): remediate Nezha dashboard path traversal`.

## Stop conditions

- No affected Nezha runtime, fork, image, or deployment is controlled here.
- Verification would require reading secret-bearing files from a live system.
- Sensitive file placement is owned by another platform team.
- Validation fails for unrelated pre-existing reasons; document those failures.

Verification - what the reviewer looks for

  • No controlled Nezha deployment resolves <2.0.13.
  • Static fallback handlers cannot escape their intended roots.
  • Regression tests cover prefix-confusion and encoded traversal variants.
  • Operator notes cover secret rotation and session invalidation if exposure existed.

Watch for

  • Fixing only /dashboard/../ while /dashboard../ still passes a prefix check.
  • Calling os.Stat() before proving the final path is contained.
  • Rotating dashboard sessions but not the underlying HS256 signing secret.

Output contract

Return one of:

  • A reviewer-ready PR/change request that upgrades Nezha to 2.0.13+, enforces segment-aware dashboard path matching, proves final static paths remain under intended roots before filesystem access, adds encoded traversal regression tests, refreshes generated artifacts, and documents credential rotation.
  • TRIAGE.md when no controlled affected Nezha runtime, fork, image, module, deployment, or dashboard static fallback exists.

The output must list versions before/after, dashboard exposure boundary, static roots reviewed, config/database locations, traversal variants tested, validation commands, and JWT/agent/OAuth/API/session rotation guidance. It must not read live secret-bearing paths, print recovered secrets, capture production config files, or call filesystem APIs before containment checks in patched code.

References