VAITP Dataset

← Back to the dataset

CVE-2025-12781

Python's base64 decode accepts +/ regardless of the altchars parameter.

  • CVSS 6.3
  • CWE-704
  • Input Validation and Sanitization
  • Remote

When passing data to the b64decode(), standard_b64decode(), and urlsafe_b64decode() functions in the "base64" module the characters "+/" will always be accepted, regardless of the value of "altchars" parameter, typically used to establish an "alternative base64 alphabet" such as the URL safe alphabet. This behavior matches what is recommended in earlier base64 RFCs, but newer RFCs now recommend either dropping characters outside the specified base64 alphabet or raising an error. The old behavior has the possibility of causing data integrity issues. This behavior can only be insecure if your application uses an alternate base64 alphabet (without "+/"). If your application does not use the "altchars" parameter or the urlsafe_b64decode() function, then your application does not use an alternative base64 alphabet. The attached patches DOES NOT make the base64-decode behavior raise an error, as this would be a change in behavior and break existing programs. Instead, the patch deprecates the behavior which will be replaced with the newly recommended behavior in a future version of Python. Users are recommended to mitigate by verifying user-controlled inputs match the base64 alphabet they are expecting or verify that their application would not be affected if the b64decode() functions accepted "+" or "/" outside of altchars.

CVSS base score
6.3
Published
2026-01-21
OWASP
A08 Software and Data Integrity Failures
Orthogonal defect classification
Checking
Code defect classification
Incorrect Algorithm
Category
Input Validation and Sanitization
Subcategory
Insecure Parsing or Deserialization
Accessibility scope
Remote
Impact
Unauthorized Access
Affected component
Python
Fixed by upgrading
Yes

Solution

Upgrade to Python version 3.11.1, 3.10.9, 3.9.16, 3.8.16, or 3.7.16 and later.

Vulnerable code sample

import base64

# This is a standard base64 encoded string. It is not compliant with the
# URL-safe alphabet because it contains '+' and '/'.
# The byte sequence b'\xfb\xff\xbf' encodes to b'++/+' in standard base64.
standard_b64_string = b'++/+'

# Define an "alternative alphabet" (the URL-safe one) that does not include '+' or '/'.
# The characters for the alternative alphabet are '-' and '_'.
alt_chars = b'-_'

# --- VULNERABILITY DEMONSTRATION ---

# 1. Using b64decode() with the 'altchars' parameter.
# An application providing 'altchars' expects that only characters from the
# main alphabet (A-Z, a-z, 0-9) and the altchars alphabet are processed.
# However, the vulnerable version accepts '+' and '/' regardless of the 'altchars' value.
# This line will execute without error in a vulnerable version.
decoded_with_altchars = base64.b64decode(standard_b64_string, altchars=alt_chars)

# 2. Using urlsafe_b64decode().
# This function is specifically intended for the URL-safe alphabet and should
# reject strings containing '+' or '/'.
# In the vulnerable version, it incorrectly accepts and decodes them.
# This line will also execute without error in a vulnerable version.
decoded_with_urlsafe = base64.urlsafe_b64decode(standard_b64_string)

# If the script runs to this point without raising a `binascii.Error`,
# it confirms the vulnerable behavior. The output shows that the non-compliant
# string was successfully decoded by functions that should have rejected it.
print(f"Vulnerable behavior confirmed: Script executed without error.")
print(f"Result from b64decode with altchars='-_': {decoded_with_altchars}")
print(f"Result from urlsafe_b64decode: {decoded_with_urlsafe}")
print(f"Both results are identical: {decoded_with_altchars == decoded_with_urlsafe}")

Patched code sample

import base64
import warnings

def patched_b64decode(s, altchars=None):
    """
    A function demonstrating the patched behavior for CVE-2025-12781.

    This function simulates the fix applied to Python's base64 module.
    The vulnerability is that `b64decode` accepts standard alphabet
    characters ('+' and '/') even when an alternative alphabet (`altchars`)
    is specified, which can lead to silent data integrity issues.

    The described patch does not immediately break behavior by raising an error.
    Instead, it introduces a `DeprecationWarning` to alert developers that this
    permissive behavior will be removed in a future version. This function
    replicates that "warn-first" fix strategy.

    Args:
        s (bytes or str): The base64-encoded data.
        altchars (bytes or None): A 2-character byte string specifying the
            alternative characters for '+' and '/'.

    Returns:
        bytes: The decoded bytes.
    """
    # The vulnerability is only relevant when an alternative alphabet is used.
    if altchars is not None:
        # The check needs to handle both bytes and string input for 's'.
        input_is_bytes = isinstance(s, bytes)
        plus = b'+' if input_is_bytes else '+'
        slash = b'/' if input_is_bytes else '/'

        # If the input contains standard alphabet characters ('+' or '/')
        # while altchars are specified, the patched behavior is to warn the user.
        if plus in s or slash in s:
            warnings.warn(
                "Decoding a base64-encoded string that contains standard "
                "alphabet characters ('+' or '/') while 'altchars' is specified "
                "is deprecated. This behavior will raise an error in a future "
                "version of Python.",
                DeprecationWarning,
                stacklevel=2
            )

    # The function still calls the original `b64decode`, preserving the
    # old behavior of successfully decoding the string. The fix is the
    # addition of the warning, not a change in the decoding logic itself.
    return base64.b64decode(s, altchars=altchars)

Payload

import base64

# A standard base64 string containing a "+" character.
# In a vulnerable application expecting a URL-safe alphabet (e.g., using altchars='-_'
# or the urlsafe_b64decode function), this string should be rejected but is instead
# successfully decoded.
payload = "+wAA"

# The following line triggers the vulnerability by passing a standard B64 character (+)
# to a function that should only accept the URL-safe alphabet (- and _).
# A vulnerable version will execute without error.
base64.urlsafe_b64decode(payload)

Cite this entry

@misc{vaitp:cve202512781,
  title        = {{Python's base64 decode accepts +/ regardless of the altchars parameter.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2025-12781},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2025-12781/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::