high · 8.9CVE-2026-52798Jun 26, 2026

CVE-2026-52798: Gogs Stored XSS in .ipynb Notebook Preview

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

A stored XSS flaw in Gogs lets any user with repository write access embed a javascript: link inside a Jupyter notebook file, which executes arbitrary JavaScript in a viewer's browser when they click

Packagegogs.io/gogs
Ecosystemgo
Affected<= 0.14.2
Fixed in0.14.3

The problem

Gogs versions up to and including 0.14.2 sanitize .ipynb notebook output on the server via POST /-/api/sanitize_ipynb, but then immediately re-render every .nb-markdown-cell element on the client side using the marked() Markdown library with no further sanitization.

This second render pass reconstructs javascript: scheme hyperlinks that the server-side sanitizer had removed. No Content Security Policy is applied to repository file views, so the reconstructed link executes freely when clicked. Any user who can push a .ipynb file to a repository (even a public one) can target any viewer, including admins.

Proof of concept

json
{
  "nbformat": 4,
  "nbformat_minor": 2,
  "metadata": {},
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "[poc](javascript:alert(document.domain))"
      ]
    }
  ]
}

The root cause is a double-render architecture flaw (CWE-79). The server sanitizer runs once and strips dangerous URLs, but view_file.tmpl then calls $(markdown).html(marked($(markdown).html(), {renderer: renderer})) for every .nb-markdown-cell, handing raw HTML back to marked() which faithfully regenerates the javascript: href from the Markdown source text that survived sanitization.

The patch (commit 17b168b) removes this unsanitized client-side re-render pass, or rewrites it to strip dangerous URL schemes before writing back to the DOM, closing the bypass. No CSP was present on file view pages to provide a safety net.

The fix

Upgrade Gogs to version 0.14.3 or later. The patch commit 17b168b11ca759a7550e1f4bbd68bbde14db7785 (PR #8319) removes the unsafe client-side marked() re-render of .nb-markdown-cell content. No configuration workaround exists for older versions.

Reporter not attributed.

References: [1][2][3][4][5]