Submitted By:            Douglas R. Reno <renodr at linuxfromscratch dot org>
Date:                    2025-04-14
Initial Package Version: 42.1
Origin:                  Patch submitted to upstream by reporter
Upstream Status:         Pending (Issue #221 in the yelp repository)
Description:             Fixes a security vulnerability that allows for yelp to
                         arbitrary exfiltrate files from a system when loading
                         a help document. This is caused by arbitrary JavaScript
                         execution, and a proof of concept exploit is now public
                         that exfiltrate's a user's OpenSSH private key. The
                         CVE number for this vulnerability is CVE-2025-3155.
                         Upstream has been aware of this for a while and the
                         reporter of the vulnerability provided patches, though
                         the Yelp/yelp-xsl maintainers have not fixed it yet.
                         A GNOME Security Team representative has recommended
                         using the reporter's patches though as it is *not*
                         advisable to skip patching this vulnerability.
                         The patches in yelp-xsl and yelp add a Content Security
                         Policy (CSP) preventing JavaScript execution through
                         help documents.

diff --git a/xslt/common/html.xsl b/xslt/common/html.xsl
index 77aed075..82832fb4 100644
--- a/xslt/common/html.xsl
+++ b/xslt/common/html.xsl
@@ -266,6 +266,16 @@ certain tokens, and you can add your own with {html.sidebar.mode}. See
 -->
 <xsl:param name="html.sidebar.right" select="''"/>
 
+<!--@@==========================================================================
+html.csp.nonce
+An optional CSP nonce string to allow the execution of scripts and styles.
+@revision[version=42.2 date=2025-02-22 status=final]
+
+This parameter takes a string value that will be added to the 'nonce' attribute
+of all 'style' and 'script' tags in the generated HTML output. This paramter is used
+to whitelist script and style tags that are allowed to be executed.
+-->
+<xsl:param name="html.csp.nonce" select="false()"/>
 
 <!--**==========================================================================
 html.output
@@ -1124,6 +1134,11 @@ dimensions. All parameters can be automatically computed if not provided.
     </xsl:call-template>
   </xsl:param>
   <style type="text/css">
+    <xsl:if test="$html.csp.nonce">
+      <xsl:attribute name="nonce">
+        <xsl:value-of select="$html.csp.nonce" />
+      </xsl:attribute>
+    </xsl:if>
     <xsl:call-template name="html.css.content">
       <xsl:with-param name="node" select="$node"/>
       <xsl:with-param name="direction" select="$direction"/>
@@ -1533,6 +1548,11 @@ copy, override this template and provide the necessary files.
   <xsl:param name="node" select="."/>
   <xsl:if test="$node//mml:*[1]">
     <script type="text/javascript">
+      <xsl:if test="$html.csp.nonce">
+        <xsl:attribute name="nonce">
+          <xsl:value-of select="$html.csp.nonce" />
+        </xsl:attribute>
+      </xsl:if>
       <xsl:attribute name="src">
         <xsl:text>http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=MML_HTMLorMML</xsl:text>
       </xsl:attribute>
@@ -1558,6 +1578,11 @@ result of {html.js.content} to that file.
 <xsl:template name="html.js.script">
   <xsl:param name="node" select="."/>
   <script type="text/javascript">
+    <xsl:if test="$html.csp.nonce">
+      <xsl:attribute name="nonce">
+        <xsl:value-of select="$html.csp.nonce" />
+      </xsl:attribute>
+    </xsl:if>
     <xsl:call-template name="html.js.content">
       <xsl:with-param name="node" select="$node"/>
     </xsl:call-template>
@@ -2035,8 +2060,19 @@ on all `code` elements with `"syntax"` in the class value.
 <xsl:template name="html.js.syntax">
   <xsl:param name="node" select="."/>
   <xsl:if test="$html.syntax.highlight">
-  <script type="text/javascript" src="{$html.js.root}highlight.pack.js"></script>
-  <script><![CDATA[
+    <script type="text/javascript" src="{$html.js.root}highlight.pack.js">
+      <xsl:if test="$html.csp.nonce">
+        <xsl:attribute name="nonce">
+          <xsl:value-of select="$html.csp.nonce" />
+        </xsl:attribute>
+      </xsl:if>
+    </script>
+    <script>
+    <xsl:if test="$html.csp.nonce">
+      <xsl:attribute name="nonce">
+        <xsl:value-of select="$html.csp.nonce" />
+      </xsl:attribute>
+    </xsl:if><![CDATA[
 document.addEventListener('DOMContentLoaded', function() {
   var matches = document.querySelectorAll('code.syntax')
   for (var i = 0; i < matches.length; i++) {
