Skip to content

Vulnerability Report: Multiple Reachable Entry Points to Vulnerable Base64 API (Apache Commons Codec) #116

@icyriverbreeze-vt

Description

@icyriverbreeze-vt

Vulnerability Report: Multiple Reachable Entry Points to Vulnerable Base64 API (Apache Commons Codec)

Hello maintainers,

We are researchers from Virginia Tech working in software security. As part of our recent study, we analyze open-source projects to identify supply chain vulnerabilities and generate proof-of-vulnerability (PoV) tests to demonstrate impact and suggest fixes or version updates.

We are sharing our findings to initiate discussion and collaborate on addressing the issue.


Summary

This project uses Apache Commons Codec version 1.10, which falls within the vulnerable range [,1.13) (CODEC-134).

More importantly, the vulnerable Base64 decoding APIs (Base64.decode, Base64.decodeBase64) are reachable from multiple public entry points in the codebase, increasing the attack surface.


Affected Dependency

  • Dependency: org.apache.commons:commons-codec
  • Current Version: 1.10
  • Vulnerable Range: [,1.13)
  • Recommended Fixed Version: 1.13+
  • Vulnerability ID: CODEC-134
  • Vulnerable APIs:
    • Base64.decode
    • Base64.decodeBase64

Reachable Public Entry Points

The vulnerable Base64 decoding API is reachable from the following public methods.

(All links point to a fixed commit snapshot to ensure reproducibility of this analysis.)


Impact

Since multiple public-facing methods process input that flows into the vulnerable Base64 decoding API:

  • Malformed Base64 inputs can trigger IllegalArgumentException
  • Repeated triggering may lead to Denial of Service (DoS)
  • Multiple entry points increase the overall attack surface

This aligns with known issues in CODEC-134, where invalid Base64 edge cases are not handled safely.


Suggested Fix

We recommend upgrading Apache Commons Codec to a non-vulnerable version.

Maven

<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-codec</artifactId>
  <version>1.13</version>
</dependency>

Proof of Vulnerability (PoV)

We generated the following JUnit test to demonstrate the issue.

  • When run with the vulnerable version, invalid Base64 inputs may be incorrectly processed and fail later in execution.
  • With a patched version, the inputs are rejected earlier with IllegalArgumentException.

We would appreciate your feedback on whether this PoV is helpful.

Questions

  • Do you find this test useful for validating the issue?
  • Would you consider upgrading the dependency to a non-vulnerable version?
  • If not, could you share your reasoning so we can better understand the design decision?

PoV Test

package com.egzosn.pay.common.util.sign.encrypt;

import org.junit.BeforeClass;
import org.junit.Test;

import java.security.KeyPair;
import java.security.KeyPairGenerator;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public class RSADecryptBase64ImpossibleTest {

    // Vulnerable library/version: Apache Commons Codec [,1.13)
    private static final String[] BASE64_IMPOSSIBLE_CASES = {
            "ZE==",
            "ZmC=",
            "Zm9vYE==",
            "Zm9vYmC=",
    };

    private static String privateKeyBase64;

    @BeforeClass
    public static void setUpKey() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        privateKeyBase64 = Base64.encode(keyPair.getPrivate().getEncoded());
    }

    @Test
    public void testDecryptRejectsImpossibleBase64Samples() {
        // Arrange
        assertNotNull(privateKeyBase64);

        for (String content : BASE64_IMPOSSIBLE_CASES) {
            try {
                // Act
                RSA.decrypt(content, privateKeyBase64, "UTF-8");

                // Assert
                fail("Expected IllegalArgumentException for content: " + content);

            } catch (IllegalArgumentException ex) {
                // Expected behavior (patched version)
                assertTrue(ex instanceof IllegalArgumentException);

            } catch (Exception ex) {
                // Vulnerable behavior: invalid Base64 passes decoding and fails later
                fail("Expected IllegalArgumentException, got: " + ex.getClass().getName());
            }
        }
    }
}

Disclosure

We are sharing this following responsible disclosure practices and are happy to coordinate further, including via private communication if preferred.

Thank you for your time and for maintaining this project.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions