Severity by source
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:H/SI:H/SA:N/E:P/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Network endpoint requiring a registered account (PR:L) and victim browser interaction (UI:R) for stored XSS; scope changes as JavaScript executes in victim's browser session (S:C), with low confidentiality and integrity impact.
Primary rating from Vendor (https://github.com/gogs/gogs).
CVSS VectorVendor: https://github.com/gogs/gogs
Lifecycle Timeline
3DescriptionCVE.org
Summary
The Jupyter Notebook (ipynb) sanitizer endpoint at POST /-/api/sanitize_ipynb allows arbitrary data: URIs without proper restrictions, potentially leading to Cross-Site Scripting (XSS). The endpoint uses bluemonday.UGCPolicy() with p.AllowURLSchemes("data") which permits all data URI schemes including data:text/html, enabling attackers to inject malicious HTML/JavaScript. Additionally, the endpoint has no authentication middleware, allowing any registered user to exploit this vulnerability.
Severity
High
Affected Versions
All versions using the vulnerable endpoint
Vulnerability Details
- CVE ID: (To be assigned)
- Entry Point:
POST /-/api/sanitize_ipynb - Attack Vector: Network
- Authentication Required: No (only needs a registered user account)
Impact
An attacker with a registered user account can:
- Send malicious HTML containing
data:text/htmlURIs to the sanitization endpoint - Receive sanitized but attacker-controlled HTML in the response
- Execute arbitrary JavaScript in the attacker's browser context through XSS
- Potentially exploit other users if the sanitized output is rendered in their context
The vulnerability has higher severity because:
- No authentication required (only needs a registered user account)
- Unlike the safer pattern in
internal/markup/sanitizer.go:39which usesisSafeDataURIto only allow safe image MIME types, this endpoint allows ALL data URIs including HTML - The returned HTML can be used to craft XSS attacks
Proof of Concept
Attacker sends a POST request to the sanitization endpoint:
POST /-/api/sanitize_ipynb HTTP/1.1
Host: target.gogs.instance
Content-Type: text/plain
<a href="data:text/html,<script>alert(document.cookie)</script>">click</a>The server returns the sanitized HTML with the data URI preserved:
<a href="data:text/html,<script>alert(document.cookie)</script>">click</a>When this HTML is rendered in a browser, the JavaScript within the data URI will execute, leading to XSS.
Affected Component
File: internal/app/api.go:10-16
func ipynbSanitizer() *bluemonday.Policy {
p := bluemonday.UGCPolicy()
p.AllowAttrs("class", "data-prompt-number").OnElements("div")
p.AllowAttrs("class").OnElements("img")
p.AllowURLSchemes("data") // <-- VULNERABLE: allows all data URIs
return p
}File: cmd/gogs/web.go:681-683 - No authentication middleware
m.Group("/-", func() {
m.Get("/metrics", app.MetricsFilter(), promhttp.Handler())
m.Group("/api", func() {
m.Post("/sanitize_ipynb", app.SanitizeIpynb()) // <-- No auth middleware
})
})Root Cause
- Unrestricted data URI scheme: The code at
internal/app/api.go:14usesp.AllowURLSchemes("data")without any restriction, unlike the safer implementation ininternal/markup/sanitizer.go:39which usesAllowURLSchemeWithCustomPolicy("data", isSafeDataURI)to only allow safe image MIME types. - No authentication: The endpoint at
cmd/gogs/web.go:682does not have any authentication middleware applied, making it accessible to any registered user. - Insufficient validation: The sanitization only removes dangerous tags/attributes but preserves data URIs, allowing
data:text/htmlpayloads to pass through.
Suggested Fix
Option 1: Use the same safe pattern as internal/markup/sanitizer.go
Replace p.AllowURLSchemes("data") with:
p.AllowURLSchemeWithCustomPolicy("data", isSafeDataURI)Where isSafeDataURI is a function that only allows safe image MIME types (image/png, image/jpeg, image/gif, etc.).
Option 2: Add authentication middleware
Apply appropriate authentication to the endpoint:
m.Post("/sanitize_ipynb", middleware.signIn, app.SanitizeIpynb())Option 3: Disable data URI scheme entirely
If data URIs are not required for ipynb sanitization:
// Remove this line entirely:
// p.AllowURLSchemes("data")AnalysisAI
Stored XSS in Gogs's Jupyter notebook (.ipynb) preview allows any registered user to inject arbitrary JavaScript via data:text/html URIs that survive the bluemonday sanitization pipeline, affecting all versions prior to 0.14.3. The POST /-/api/sanitize_ipynb endpoint uses p.AllowURLSchemes("data") without MIME-type gating, unlike the safer IsSafeDataURI validator used elsewhere in the codebase, and carries no authentication middleware - making it reachable by any account holder. A proof-of-concept is publicly documented in GHSA-3w28-36p9-w929; no CISA KEV listing or EPSS data is available at time of analysis.
Technical ContextAI
Gogs (gogs.io/gogs, pkg:go/gogs.io_gogs) is a self-hosted Git service written in Go. The vulnerability (CWE-79, Improper Neutralization of Input During Web Page Generation) lives in internal/app/api.go, where ipynbSanitizer() constructs a bluemonday HTML policy via UGCPolicy() and then calls p.AllowURLSchemes("data"), whitelisting the entire data: URI scheme with no MIME-type restriction. Browsers treat data:text/html URIs as fully functional HTML documents and will execute embedded <script> tags or event handlers within them. The codebase already contained a correct pattern - AllowURLSchemeWithCustomPolicy("data", IsSafeDataURI) in internal/markup/sanitizer.go:39 - that restricts data URIs to safe image MIME types, but this was not applied to the ipynb sanitizer. The endpoint route at cmd/gogs/web.go:682 is also grouped outside any authentication middleware, so the HTTP session check is entirely absent at the framework routing layer.
RemediationAI
Upgrade Gogs to version 0.14.3 or later; this release replaces the unsafe p.AllowURLSchemes("data") call in internal/app/api.go with p.AllowURLSchemeWithCustomPolicy("data", markup.IsSafeDataURI), restricting data URIs to safe image MIME types. The patch is available at https://github.com/gogs/gogs/pull/8326 (commit dd1bd9837aa196b3ed3a8ee21e5727b5d7a986a3). If immediate upgrade is not feasible, apply a reverse proxy or WAF rule to block all POST requests to the path /-/api/sanitize_ipynb - this disables Jupyter notebook rendering as a side effect. A second compensating control is to add authentication middleware to the endpoint route in cmd/gogs/web.go, which limits exploitation to authenticated users but does not fix the underlying MIME-type bypass and requires a code change. Disabling data: URI support entirely by removing the AllowURLSchemes("data") call is viable if inline images in notebooks are not required by the deployment.
Same weakness CWE-79 – Cross-site Scripting (XSS)
View allVendor StatusVendor
SUSE
Severity: Moderate| Product | Status |
|---|---|
| SUSE Linux Enterprise Server 16.1 | Affected |
| SUSE Linux Enterprise Server for SAP applications 16.1 | Affected |
| SUSE Linux Enterprise Module for Package Hub 15 SP5 | Affected |
| SUSE Linux Enterprise Module for Package Hub 15 SP6 | Affected |
| openSUSE Leap 15.5 | Affected |
| openSUSE Leap 15.6 | Affected |
Share
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-39076
GHSA-3w28-36p9-w929