zrok, Reflected XSS, CVE-2026-40302 (Moderate)

Listen to this Post

The vulnerability stems from the `proxyUi` template engine using Go’s `text/template` (which performs no HTML escaping) instead of html/template. The GitHub OAuth callback handlers in both `publicProxy` and `dynamicProxy` embed the attacker-controlled `refreshInterval` query parameter verbatim into an error message when `time.ParseDuration` fails. This error is then rendered unescaped into HTML. An attacker can deliver a crafted login URL to a victim; after the victim completes the GitHub OAuth flow, the callback page executes arbitrary JavaScript in the OAuth server’s origin.
The attack vector is network-based, with low complexity. It requires no privileges and only user interaction (clicking the link and completing OAuth). The scope is changed, as the script executes in the OAuth server’s origin, not the victim’s share origin. Confidentiality and integrity impacts are low, with no availability impact. The CVSS score is 6.1 (Moderate).

Affected components include:

– `endpoints/proxyUi/template.go` — init() / WriteTemplate (lines 8, 18, 99) — `text/template` used for HTML rendering
– `endpoints/proxyUi/template.html` — line 119 — `{{ .Error }}` in HTML without escaping
– `endpoints/publicProxy/providerGithub.go` — login callback closure (lines 93, 128, 130)
– `endpoints/dynamicProxy/providerGithub.go` — loginHandler() (lines 110, 146, 148)
All versions of zrok greater than 1.1.0 and less than 2.0.1 are affected.

dailycve form:

Platform: zrok
Version: 1.1.0-2.0.0
Vulnerability: Reflected XSS
Severity: Moderate (6.1)
date: 2026-04-16

Prediction: 2026-03-31

Analytics under heading What Undercode Say:

The vulnerability can be detected by monitoring logs for unusual `refreshInterval` parameters. A simple bash script to check for the vulnerable pattern:

Check for vulnerable refreshInterval parameter in logs
grep -E 'refreshInterval=.[<>"\x27]' /var/log/zrok/access.log

A more thorough analysis can be done using Go’s `html/template` instead of text/template:

// Vulnerable code using text/template
tmpl := template.Must(template.New("error").Parse(<code><div class="error">{{.Error}}</div></code>))
// Fixed code using html/template
tmpl := template.Must(template.New("error").Parse(<code><div class="error">{{.Error}}</div></code>))

Exploit:

An attacker can craft a URL like:

https://zrok.example.com/auth/github/callback?refreshInterval=1s&code=anything&state=anything

But to trigger the XSS, the `refreshInterval` parameter must contain invalid duration values. For example:

https://zrok.example.com/auth/github/callback?refreshInterval=1s<script>alert('XSS')</script>&code=anything&state=anything

When `time.ParseDuration` fails, the error message will include the unsanitized `refreshInterval` value, which is then rendered in the HTML response, executing the JavaScript.

Protection from this CVE

  • Upgrade to zrok version 2.0.1 or later.
  • If upgrading is not immediately possible, apply a patch that replaces `text/template` with `html/template` in `proxyUi` and sanitizes the `refreshInterval` parameter in the OAuth callback handlers.
  • Implement a Web Application Firewall (WAF) rule to block requests containing `refreshInterval` with HTML tags or JavaScript event handlers.

Impact

The impact is limited due to the low confidentiality and integrity ratings. The injected script executes in the OAuth server’s origin after a failed flow, meaning no session cookie is set at that point. This limits exfiltration to what is visible in the DOM and what can be requested from the OAuth server. The script can initiate new OAuth flows or submit forms on behalf of the victim in the OAuth server origin. No availability impact is present.

🎯Let’s Practice Exploiting & Learn Patching For Free:

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top