VYPR
Moderate severityNVD Advisory· Published Feb 6, 2019· Updated Aug 5, 2024

CVE-2019-1003013

CVE-2019-1003013

Description

Jenkins Blue Ocean Plugins 1.10.1 and earlier are vulnerable to stored XSS via user description, allowing arbitrary HTML rendering.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Jenkins Blue Ocean Plugins 1.10.1 and earlier are vulnerable to stored XSS via user description, allowing arbitrary HTML rendering.

Vulnerability

A stored cross-site scripting (XSS) vulnerability exists in Jenkins Blue Ocean Plugins versions 1.10.1 and earlier. The flaw resides in multiple source files including blueocean-commons/src/main/java/io/jenkins/blueocean/commons/stapler/Export.java, ExportConfig.java, JSONDataWriter.java, UserStatePreloader.java, and header.jelly. User-controlled data, specifically a user's description, is not properly escaped before being rendered in Blue Ocean's user interface. This allows an attacker with the ability to edit a user's description to inject arbitrary HTML or JavaScript [2][3].

Exploitation

An attacker requires permission to edit a user's description in Jenkins (typically users can edit their own description, or administrators can edit others). The attacker sets the description field to contain malicious HTML/JavaScript. When Blue Ocean loads the page for that user, the injected script or HTML is rendered without proper escaping. No additional user interaction is required beyond viewing the affected user's data in Blue Ocean [2][3].

Impact

Successful exploitation allows the attacker to execute arbitrary HTML/JavaScript in the context of the Blue Ocean interface. This could lead to theft of session cookies, defacement, or redirection to malicious sites. The attack is limited to the Blue Ocean UI and requires the victim to view the page where the tainted description is displayed [2][3].

Mitigation

The vulnerability is fixed in Blue Ocean Plugins version 1.10.2, released on 2019-01-28. Users should upgrade to this version or later. The fix, introduced in commit 62775e78532b756826bb237775b64a5052624b57, applies proper XSS escaping when writing values in the JSON writer and CDATA-wraps scripts to prevent tag breakout [4]. Red Hat also included the fix in OpenShift Container Platform 3.11.82 via advisory RHBA-2019:0326 [1]. There is no workaround other than upgrading.

AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
io.jenkins.blueocean:blueoceanMaven
< 1.10.21.10.2

Affected products

2

Patches

1
62775e78532b

[SECURITY-1204] XSS escape beforce outputting the value in json writer

https://github.com/jenkinsci/blueocean-pluginGavin MoganDec 4, 2018via ghsa
6 files changed · +71 5
  • blueocean-commons/src/main/java/io/jenkins/blueocean/commons/stapler/export/ExportConfig.java+17 0 modified
    @@ -20,6 +20,8 @@ public class ExportConfig {
     
         private Flavor flavor = Flavor.JSON;
     
    +    private boolean htmlEncode = false;
    +
         /**
          * If true, output will be indented to make it easier for humans to understand.
          */
    @@ -83,4 +85,19 @@ public ExportConfig withFlavor(Flavor flavor){
             this.flavor = flavor;
             return this;
         }
    +
    +    /**
    +     * If true, output will escaped to be embedded into html
    +     */
    +    public boolean isHtmlEncode() {
    +        return htmlEncode;
    +    }
    +
    +    /**
    +     * If true, output will escaped to be embedded into html
    +     */
    +    public ExportConfig withHtmlEncode(boolean htmlEncode) {
    +        this.htmlEncode = htmlEncode;
    +        return this;
    +    }
     }
    
  • blueocean-commons/src/main/java/io/jenkins/blueocean/commons/stapler/Export.java+30 2 modified
    @@ -43,8 +43,20 @@ public class Export {
          */
         @Nonnull
         public static String toJson(@Nonnull Object object) throws IOException {
    +        return toJson(object, false);
    +    }
    +
    +    /**
    +     * Serialize the supplied object to JSON and return as a {@link String}.
    +     * @param object The object to serialize.
    +     * @param boolean enable html encoding so its safe to output to html
    +     * @return The JSON as a {@link String}.
    +     * @throws IOException Error serializing model object.
    +     */
    +    @Nonnull
    +    public static String toJson(@Nonnull Object object, boolean htmlEncoded) throws IOException {
             try (StringWriter writer = new StringWriter()) {
    -            toJson(object, writer);
    +            toJson(object, writer, htmlEncoded);
                 return writer.toString();
             }
         }
    @@ -57,8 +69,24 @@ public static String toJson(@Nonnull Object object) throws IOException {
          */
         @SuppressWarnings("unchecked")
         public static void toJson(@Nonnull Object object, @Nonnull Writer writer) throws IOException {
    +        toJson(object, writer, false);
    +    }
    +
    +
    +    /**
    +     * Serialize the supplied object to JSON and write to the supplied {@link Writer}.
    +     * @param object The object to serialize.
    +     * @param writer The writer to output to.
    +     * @throws IOException Error serializing model object.
    +     */
    +    @SuppressWarnings("unchecked")
    +    public static void toJson(@Nonnull Object object, @Nonnull Writer writer, boolean htmlEncoded) throws IOException {
             Model model = new ModelBuilder().get(object.getClass());
    -        model.writeTo(object, Flavor.JSON.createDataWriter(object, writer, createExportConfig()));
    +        ExportConfig exportConfig = createExportConfig();
    +        if (htmlEncoded) {
    +            exportConfig.withHtmlEncode(true);
    +        }
    +        model.writeTo(object, Flavor.JSON.createDataWriter(object, writer, exportConfig));
             writer.flush();
         }
     
    
  • blueocean-commons/src/main/java/io/jenkins/blueocean/commons/stapler/export/JSONDataWriter.java+6 1 modified
    @@ -24,6 +24,7 @@
     package io.jenkins.blueocean.commons.stapler.export;
     
     import com.fasterxml.jackson.core.io.JsonStringEncoder;
    +import org.apache.commons.lang.StringEscapeUtils;
     
     import javax.annotation.Nonnull;
     import java.io.IOException;
    @@ -109,7 +110,11 @@ public void value(String v) throws IOException {
             StringBuilder buf = new StringBuilder(v.length());
             buf.append('\"');
             // TODO: remove when JENKINS-45099 has been fixed correctly in upstream stapler
    -        jsonEncoder.quoteAsString(v, buf);
    +        if (config.isHtmlEncode()) {
    +            jsonEncoder.quoteAsString(StringEscapeUtils.escapeHtml(v), buf);
    +        } else {
    +            jsonEncoder.quoteAsString(v, buf);
    +        }
             buf.append('\"');
             data(buf.toString());
         }
    
  • blueocean-commons/src/test/java/io/jenkins/blueocean/commons/stapler/export/JSONDataWriterTest.java+15 0 modified
    @@ -12,8 +12,13 @@
     
     public class JSONDataWriterTest {
         private ExportConfig config = new ExportConfig().withFlavor(Flavor.JSON).withClassAttribute(ClassAttributeBehaviour.IF_NEEDED.simple());
    +    private ExportConfig configWithHtmlEncode = new ExportConfig().withFlavor(Flavor.JSON).withClassAttribute(ClassAttributeBehaviour.IF_NEEDED.simple()).withHtmlEncode(true);
     
         private <T> String serialize(T bean, Class<T> clazz) throws IOException {
    +        return serialize(bean, clazz, config);
    +    }
    +
    +    private <T> String serialize(T bean, Class<T> clazz, ExportConfig config) throws IOException {
             StringWriter w = new StringWriter();
             Model<T> model = new ModelBuilder().get(clazz);
             model.writeTo(bean, Flavor.JSON.createDataWriter(bean, w, config));
    @@ -78,4 +83,14 @@ public Supers(Super... elements) {
             }
         }
     
    +    @ExportedBean public static class Escaping {
    +        @Exported public String specific() {return "<script>alert('hi')</script>";}
    +    }
    +
    +    @Test
    +    public void testEscaping() throws Exception {
    +        assertEquals("{\"_class\":\"Escaping\",\"specific\":\"&lt;script&gt;alert('hi')&lt;/script&gt;\"}",
    +                serialize(new Escaping(), Escaping.class, configWithHtmlEncode));
    +    }
    +
     }
    
  • blueocean-rest-impl/src/main/java/io/jenkins/blueocean/service/embedded/UserStatePreloader.java+1 1 modified
    @@ -70,7 +70,7 @@ public String getStateJson() {
             try {
                 User currentUser = User.current();
                 if (currentUser != null && organization != null) {
    -                return Export.toJson(new UserImpl(organization, currentUser));
    +                return Export.toJson(new UserImpl(organization, currentUser), true);
                 } else {
                     return ANONYMOUS;
                 }
    
  • blueocean-web/src/main/resources/io/jenkins/blueocean/PageStatePreloadDecorator/header.jelly+2 1 modified
    @@ -1,6 +1,6 @@
     <?jelly escape-by-default='false'?>
     <j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler">
    -  <script>
    +  <script>//&lt;![CDATA[
         // construct the state object parent path inside window.$blueocean.
         var stateRoot = window.$blueocean = (window.$blueocean || {});
         (function () {
    @@ -37,5 +37,6 @@
             </j:if>
           </j:forEach>
         })();
    +    //]]&gt;
       </script>
     </j:jelly>
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.