CVE-2021-43288 (Java, published 2022-04-14T13:15Z)
Description: value: An issue was discovered in ThoughtWorks GoCD before 21.3.0. An attacker in control of a GoCD Agent can plant malicious JavaScript into a failed Job Report.
Severity: LOW (CVSS v3 base score: 5.4)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/gocd/gocd
Files changed:
common/build.gradle
common/src/main/java/com/thoughtworks/go/domain/DirectoryEntries.java
common/src/main/java/com/thoughtworks/go/domain/FileDirectoryEntry.java
common/src/main/java/com/thoughtworks/go/domain/FolderDirectoryEntry.java
common/src/main/java/com/thoughtworks/go/server/presentation/html/HtmlElement.java
common/src/test/java/com/thoughtworks/go/domain/FileDirectoryEntryTest.java
common/src/test/java/com/thoughtworks/go/domain/FolderDirectoryEntryTest.java
common/src/test/java/com/thoughtworks/go/server/presentation/html/HtmlElementTest.java
dependencies.gradle
server/build.gradle
Commit message: #000 - Escape filenames in artifact tab


Vulnerable code:
            HtmlElement element = p().content("Artifacts for this job instance are unavailable as they may have been <a href='" +
                        .content(getFileName())
                                .content(getFileName())
    public HtmlElement content(String body) {

import static org.hamcrest.Matchers.hasItem;

Fixed code:
  api project.deps.commonsText
            HtmlElement element = p().unsafecontent("Artifacts for this job instance are unavailable as they may have been <a href='" +
                        .safecontent(getFileName())
                                .safecontent(getFileName())
import org.apache.commons.text.StringEscapeUtils;
    public HtmlElement unsafecontent(String body) {
    public HtmlElement safecontent(String body) {
        return content(new TextElement(StringEscapeUtils.escapeHtml4(body)));
    }

/*
 * Copyright 2021 ThoughtWorks, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.thoughtworks.go.domain;

import com.thoughtworks.go.server.presentation.models.HtmlRenderer;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class FileDirectoryEntryTest {
    @Test
    void shouldEscapeFilename() {
        FileDirectoryEntry entry = new FileDirectoryEntry("<div>Hello</div>", "https://www.example.com");
        HtmlRenderer renderer = new HtmlRenderer("");
        entry.htmlBody().render(renderer);

        assertTrue(renderer.asString().contains("&lt;div&gt;Hello&lt;/div&gt;"));
        assertFalse(renderer.asString().contains("<div>Hello</div>"));
    }
}
import com.thoughtworks.go.server.presentation.models.HtmlRenderer;
import static org.hamcrest.Matchers.*;

    @Test
    public void shouldEscapeFolderName() throws Exception {
        DirectoryEntries subDirectory = new DirectoryEntries();
        FolderDirectoryEntry entry = new FolderDirectoryEntry("<div>Hello</div>", "url", subDirectory);

        HtmlRenderer renderer = new HtmlRenderer("");
        entry.htmlBody().render(renderer);

        assertThat(renderer.asString(), containsString("&lt;div&gt;Hello&lt;/div&gt;"));
        assertThat(renderer.asString(), not(containsString("<div>Hello</div>")));
    }
/*
 * Copyright 2021 ThoughtWorks, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.thoughtworks.go.server.presentation.html;

import com.thoughtworks.go.server.presentation.models.HtmlRenderer;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class HtmlElementTest {
    @Test
    void shouldEscapeContent() {
        HtmlElement element = HtmlElement.span().safecontent("<div>Hello</div>");
        HtmlRenderer renderer = new HtmlRenderer("");

        element.render(renderer);

        assertEquals("<span>\n&lt;div&gt;Hello&lt;/div&gt;\n</span>\n", renderer.asString());
    }
}
  commonsText         : 'org.apache.commons:commons-text:1.8',
  commonsText         : versionOf(libraries.commonsText),
        "commons-text-${project.versions.commonsText}.jar",