Open-Source Security Intelligence

Know every vulnerability
before it knows you.

DevGuard continuously monitors your dependencies and alerts you when CVEs like this one affect your stack — with real-time threat intelligence built for developers.

Search

GHSA-jq8v-rmf6-65jw

HighCVSS 8.9 / 10
Published Jun 22, 2026·Last modified Jun 23, 2026
Affected Components(0)

No affected components available

Description

Summary

Although .ipynb previews are sanitized on the server side via /-/api/sanitize_ipynb, the inserted content is re-rendered on the client side without sanitization using marked() on elements with the .nb-markdown-cell class. During this process, links containing schemes such as javascript: can be regenerated.

As a result, when a victim views an attacker-crafted .ipynb file and clicks the link, arbitrary JavaScript is executed in the Gogs origin, leading to a click-based Stored XSS.

Details

After the rendered output of a .ipynb file is sanitized via /-/api/sanitize_ipynb and inserted into the DOM, only the Markdown cell portions are re-rendered using marked() and overwritten in the DOM. During this process, links with the javascript: scheme can be regenerated.

templates/repo/view_file.tmpl:42–71

{{else if .IsIPythonNotebook}}
  <script>
    $.getJSON("{{.RawFileLink}}", null, function(notebook_json) {
      var notebook = nb.parse(notebook_json);
      var rendered = notebook.render();
      $.ajax({
        type: "POST",
        url: '{{AppSubURL}}/-/api/sanitize_ipynb',
        data: rendered.outerHTML,
        processData: false,
        contentType: false,
      }).done(function(data) {
        $("#ipython-notebook").append(data);
        $("#ipython-notebook code").each(function(i, block) {
          $(block).addClass("py").addClass("python");
          hljs.highlightBlock(block);
        });

        // Overwrite image method to append proper prefix to the source URL
        var renderer = new marked.Renderer();
        var context = '{{.RawFileLink}}';
        context = context.substring(0, context.lastIndexOf("/"));
        renderer.image = function (href, title, text) {
          return `<img src="${context}/${href}"`
        };
        $("#ipython-notebook .nb-markdown-cell").each(function(i, markdown) {
          $(markdown).html(marked($(markdown).html(), {renderer: renderer}));
        });
      });
    });
  </script>

While regular HTML pages (including .ipynb preview pages) are served without a Content Security Policy (CSP), CSP headers are applied only to attachment delivery routes.

internal/cmd/web.go:323

c.Header().Set("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline'; sandbox")

Steps to Reproduce

  1. As the attacker, add and push/commit a .ipynb file containing a javascript: link in a Markdown cell to a repository.

    • Example (PoC):

      {
        "nbformat": 4,
        "nbformat_minor": 2,
        "metadata": {},
        "cells": [
          {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
              "[poc](javascript:alert(document.domain))"
            ]
          }
        ]
      }
      
  2. The victim opens the file on Gogs (e.g., /<user>/<repo>/src/<branch>/poc.ipynb).

    <img width="2386" height="1218" alt="image" src="https://github.com/user-attachments/assets/b0d93fd8-c5ca-4058-8af0-98dee590d3ad" />
  3. When the victim clicks the poc link displayed in the preview, alert(document.domain) is executed in the same Gogs origin.

    <img width="2390" height="1388" alt="image" src="https://github.com/user-attachments/assets/0eb6ebe8-632c-4a41-8a11-46471514b4c4" />

Minimum Required Privileges

  • Attacker: Ability to place a .ipynb file as a regular (non-admin) user

    • For example: a general user who can create a public repository and add files.
    • Or: write access (collaborator, etc.) to an existing repository that the victim will view.
  • Victim: Permission to view the repository (a click is required).

Impact

  • Unauthorized actions performed with the victim’s account privileges (e.g., repository settings changes, Issue operations,誘導 to token creation).
  • Theft of information accessible to the victim (repository/Issue/Wiki contents, tokens exposed in page context).
  • If the victim is an administrator, the impact may escalate to instance-wide configuration changes and user management.
Risk Scores
Base Score
8.9

The vulnerability can be exploited over the network without needing physical access. It is easy for an attacker to exploit this vulnerability. An attacker needs basic access or low-level privileges. The attacker needs the user to perform some action, like clicking a link. The vulnerability can affect other systems as well, not just the initial system. There is a high impact on the confidentiality of the information. There is a high impact on the integrity of the data. There is a low impact on the availability of the system.

Threat Intelligence
8.1

Exploitation activity has been observed. Apply available patches or mitigations urgently.

EPSS
0.30%

The exploit probability is very low. The vulnerability is unlikely to be exploited in the next 30 days.

Exploit
Not available

We did not find any exploit available. Neither in GitHub repositories nor in the Exploit-Database.

Browse More

Scan your project

Continuously monitor your dependencies and get alerted when vulnerabilities like this one affect your stack.

Checkout DevGuard