CVE-2021-32700 (Java, published 2021-06-22T20:15Z)
Description: value: Ballerina is an open source programming language and platform for cloud application programmers. Ballerina versions 1.2.x and SL releases up to alpha 3 have a potential for a supply chain attack via MiTM against users. Http connections did not make use of TLS and certificate checking was ignored. The vulnerability allows an attacker to substitute or modify packages retrieved from BC thus allowing to inject malicious code into ballerina executables. This has been patched in Ballerina 1.2.14 and Ballerina SwanLake alpha4.
Severity: MEDIUM (CVSS v3 base score: 7.4)
Weakness: CWE-306 \u2014 Missing Authentication for Critical Function
The product does not perform any authentication for functionality that requires a provable user identity or consumes a significant amount of resources.
Repository: https://github.com/ballerina-platform/ballerina-lang
Files changed:
cli/ballerina-cli-module/src/main/java/org/ballerinalang/cli/module/Pull.java
cli/ballerina-cli-module/src/main/java/org/ballerinalang/cli/module/Push.java
cli/ballerina-cli-module/src/main/java/org/ballerinalang/cli/module/Search.java
cli/ballerina-cli-module/src/main/java/org/ballerinalang/cli/module/TokenUpdater.java
cli/ballerina-cli-module/src/main/java/org/ballerinalang/cli/module/util/Utils.java
cli/ballerina-cli-module/src/test/java/org/ballerinalang/cli/module/UtilsTest.java
compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/packaging/converters/URIDryConverter.java
misc/openapi-ballerina/modules/openapi-to-ballerina-generator/src/main/java/org/ballerinalang/openapi/CodeGenerator.java
tests/jballerina-integration-test/src/test/java/org/ballerinalang/test/packaging/PackagingTestCase.java
Commit message: Fix central connection


Vulnerable code:
import java.net.HttpURLConnection;
import static org.ballerinalang.cli.module.util.Utils.createHttpUrlConnection;
import static org.ballerinalang.cli.module.util.Utils.initializeSsl;
        HttpURLConnection conn = null;
            initializeSsl();
            conn = createHttpUrlConnection(convertToUrl(url + supportedVersionRange), proxyHost, proxyPort,
                    proxyUsername, proxyPassword);
            if (getStatusCode(conn) == HttpURLConnection.HTTP_MOVED_TEMP) {
                conn = createHttpUrlConnection(convertToUrl(newUrl), proxyHost, proxyPort, proxyUsername,
                        proxyPassword);
     * @param conn                  http connection
    private static void createBaloInHomeRepo(HttpURLConnection conn, String modulePathInBaloCache,
     * @param conn             http connection
    private static void writeBaloFile(HttpURLConnection conn, Path baloPath, String fullModuleName,
     * @param conn           http connection
    private static void handleErrorResponse(HttpURLConnection conn, String url, String moduleFullName) {
import java.net.HttpURLConnection;
import static org.ballerinalang.cli.module.util.Utils.createHttpUrlConnection;
import static org.ballerinalang.cli.module.util.Utils.initializeSsl;
        initializeSsl();
        HttpURLConnection conn = createHttpUrlConnection(convertToUrl(url), proxyHost, proxyPort, proxyUsername,
                proxyPassword);
     * @param conn       http connection
    private static void handleResponse(HttpURLConnection conn, String orgName, String moduleName, String version) {
            if (statusCode == HttpURLConnection.HTTP_OK) {
            } else if (statusCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
            } else if (statusCode == HttpURLConnection.HTTP_BAD_REQUEST) {
import java.net.HttpURLConnection;
import static org.ballerinalang.cli.module.util.Utils.createHttpUrlConnection;
import static org.ballerinalang.cli.module.util.Utils.initializeSsl;
        initializeSsl();
        HttpURLConnection conn = createHttpUrlConnection(convertToUrl(url), proxyHost, proxyPort, proxyUsername,
                proxyPassword);
     * @param conn          http connection
    private static void handleResponse(HttpURLConnection conn, int statusCode, String terminalWidth) {
            if (statusCode == HttpURLConnection.HTTP_OK) {
import java.net.HttpURLConnection;
                httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_OK,
                        response.getBytes(StandardCharsets.UTF_8).length);
import java.net.HttpURLConnection;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import static org.ballerinalang.cli.module.util.CliModuleConstants.SSL;
    private static TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return new java.security.cert.X509Certificate[] {};
        }

        public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
            //No need to implement.
        }

        public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
            //No need to implement.
        }
    } };

     * Initialize SSL.
     */
    public static void initializeSsl() {
        try {
            SSLContext sc = SSLContext.getInstance(SSL);
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            throw ErrorUtil.createCommandException("initializing SSL failed: " + e.getMessage());
        }
    }

    /**
     * Create http URL connection.
    public static HttpURLConnection createHttpUrlConnection(URL url, String proxyHost, int proxyPort,
                return (HttpURLConnection) url.openConnection();
                return (HttpURLConnection) url.openConnection(proxy);
     * @param conn   http connection
    public static void setRequestMethod(HttpURLConnection conn, RequestMethod method) {
     * @param conn http connection
    public static int getStatusCode(HttpURLConnection conn) {
import java.net.HttpURLConnection;
import static org.ballerinalang.cli.module.util.Utils.createHttpUrlConnection;
    @Test(description = "Test create http URL connection without proxy")
        HttpURLConnection conn;
        conn = createHttpUrlConnection(convertToUrl(TEST_URL), "", 0, "", "");
        conn = createHttpUrlConnection(convertToUrl(TEST_URL), "http://localhost", 9090, "testUser", "testPassword");
        HttpURLConnection conn = createHttpUrlConnection(convertToUrl(TEST_URL), "", 0, "", "");
import java.net.HttpURLConnection;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
    private static TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return new java.security.cert.X509Certificate[]{};
                }
                public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
                    //No need to implement.
                }
                public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
                    //No need to implement.
                }
            }
    };

        try {
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            proxy = getProxy();
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            // ignore errors
        }
                HttpURLConnection conn;
                    conn = (HttpURLConnection) remoteURI.toURL().openConnection();
                    conn = (HttpURLConnection) remoteURI.toURL().openConnection(this.proxy);

import java.net.HttpURLConnection;
import static org.ballerinalang.cli.module.util.Utils.createHttpUrlConnection;
import static org.ballerinalang.cli.module.util.Utils.initializeSsl;
        initializeSsl();
        HttpURLConnection conn = createHttpUrlConnection(convertToUrl(url), "", 0, "", "");

Fixed code:
import javax.net.ssl.HttpsURLConnection;
import static org.ballerinalang.cli.module.util.Utils.createHttpsUrlConnection;
        HttpsURLConnection conn = null;
            conn = createHttpsUrlConnection(convertToUrl(url + supportedVersionRange), proxyHost, proxyPort,
                                            proxyUsername, proxyPassword);
            if (getStatusCode(conn) == HttpsURLConnection.HTTP_MOVED_TEMP) {
                conn = createHttpsUrlConnection(convertToUrl(newUrl), proxyHost, proxyPort, proxyUsername,
                                                proxyPassword);
     * @param conn                  https connection
    private static void createBaloInHomeRepo(HttpsURLConnection conn, String modulePathInBaloCache,
     * @param conn             https connection
    private static void writeBaloFile(HttpsURLConnection conn, Path baloPath, String fullModuleName,
     * @param conn           https connection
    private static void handleErrorResponse(HttpsURLConnection conn, String url, String moduleFullName) {
import javax.net.ssl.HttpsURLConnection;
import static org.ballerinalang.cli.module.util.Utils.createHttpsUrlConnection;
        HttpsURLConnection conn = createHttpsUrlConnection(convertToUrl(url), proxyHost, proxyPort, proxyUsername,
                                                           proxyPassword);
     * @param conn       https connection
    private static void handleResponse(HttpsURLConnection conn, String orgName, String moduleName, String version) {
            if (statusCode == HttpsURLConnection.HTTP_OK) {
            } else if (statusCode == HttpsURLConnection.HTTP_UNAUTHORIZED) {
            } else if (statusCode == HttpsURLConnection.HTTP_BAD_REQUEST) {
import javax.net.ssl.HttpsURLConnection;

import static org.ballerinalang.cli.module.util.Utils.createHttpsUrlConnection;
        HttpsURLConnection conn = createHttpsUrlConnection(convertToUrl(url), proxyHost, proxyPort, proxyUsername,
                                                           proxyPassword);
     * @param conn          https connection
    private static void handleResponse(HttpsURLConnection conn, int statusCode, String terminalWidth) {
            if (statusCode == HttpsURLConnection.HTTP_OK) {
import javax.net.ssl.HttpsURLConnection;
                httpExchange.sendResponseHeaders(HttpsURLConnection.HTTP_OK,
                                                 response.getBytes(StandardCharsets.UTF_8).length);
     * Create https URL connection.
    public static HttpsURLConnection createHttpsUrlConnection(URL url, String proxyHost, int proxyPort,
                return (HttpsURLConnection) url.openConnection();
                return (HttpsURLConnection) url.openConnection(proxy);
     * @param conn   https connection
    public static void setRequestMethod(HttpsURLConnection conn, RequestMethod method) {
     * @param conn https connection
    public static int getStatusCode(HttpsURLConnection conn) {
import javax.net.ssl.HttpsURLConnection;

import static org.ballerinalang.cli.module.util.Utils.createHttpsUrlConnection;
    @Test(description = "Test create https URL connection without proxy")
        HttpsURLConnection conn;
        conn = createHttpsUrlConnection(convertToUrl(TEST_URL), "", 0, "", "");
        conn = createHttpsUrlConnection(convertToUrl(TEST_URL), "http://localhost", 9090, "testUser", "testPassword");
        HttpsURLConnection conn = createHttpsUrlConnection(convertToUrl(TEST_URL), "", 0, "", "");
        proxy = getProxy();
                HttpsURLConnection conn;
                    conn = (HttpsURLConnection) remoteURI.toURL().openConnection();
                    conn = (HttpsURLConnection) remoteURI.toURL().openConnection(this.proxy);
     * @param serviceName    service name
import javax.net.ssl.HttpsURLConnection;

import static org.ballerinalang.cli.module.util.Utils.createHttpsUrlConnection;
        HttpsURLConnection conn = createHttpsUrlConnection(convertToUrl(url), "", 0, "", "");