VYPR
High severityNVD Advisory· Published Feb 21, 2025· Updated Aug 26, 2025

Qiskit SDK denial of service

CVE-2025-1403

Description

A malformed QPY file can cause a segfault in Qiskit SDK versions 0.45.0 through 1.2.4, enabling remote denial of service via crafted symengine serialization data.

AI Insight

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

A malformed QPY file can cause a segfault in Qiskit SDK versions 0.45.0 through 1.2.4, enabling remote denial of service via crafted symengine serialization data.

Vulnerability

Overview

The vulnerability in Qiskit SDK (versions 0.45.0 through 1.2.4) stems from improper deserialization of untrusted QPY files. Specifically, a maliciously crafted QPY file containing a malformed symengine serialization stream, embedded within a ParameterExpression object, can trigger a segmentation fault in the symengine library [2][3]. This flaw is classified under CWE-502: Deserialization of Untrusted Data [2].

Exploitation and

Attack Surface

Exploitation requires no authentication and can be performed remotely by an attacker who supplies a specially constructed QPY file to a vulnerable Qiskit instance [2]. The attack surface is the QPY deserialization functionality, which processes these files without adequate validation of symengine stream integrity. The CVSS v3.1 vector (8.6, AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:H) reflects the low complexity and network-based attack vector [2].

Impact

Successful exploitation results in a denial of service condition: the segmentation fault terminates the hosting process, disrupting legitimate use of the Qiskit SDK. While no confidentiality or integrity impact is indicated, the availability impact is high, as the process crash prevents further computation until restarted [2][3].

Mitigation and

Remediation

IBM has addressed the issue in Qiskit 1.3.0 by introducing QPY format version 13, which avoids the vulnerable symengine serialization path [2]. Older QPY format versions (10, 11, 12) remain vulnerable if symengine ≤ 0.13.0 is installed. While symengine 0.14.0 fixes the segfault, it is backward-incompatible with Qiskit releases [2]. IBM recommends applying a patch to symengine 0.13.0 (commit eb3e292 [4]) to raise a RuntimeError on malformed input instead of crashing, or upgrading to Qiskit 1.3.0 and using QPY format 13 [2].

AI Insight generated on May 20, 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
qiskitPyPI
>= 0.45.0, < 1.3.01.3.0
qiskit-terraPyPI
>= 0.45.0, <= 0.46.3

Affected products

3

Patches

1
eb3e292bf13b

Throw exceptions on incorrect serialization inputs

https://github.com/symengine/symengineIsuru FernandoNov 19, 2024via ghsa
2 files changed · +40 18
  • symengine/serialize-cereal.h+27 18 modified
    @@ -665,37 +665,46 @@ RCP<const Basic> load_basic(
     template <class Archive, class T>
     inline void CEREAL_LOAD_FUNCTION_NAME(Archive &ar, RCP<const T> &ptr)
     {
    -    uint32_t id;
    -    ar(CEREAL_NVP(id));
    +    try {
    +        uint32_t id;
    +        ar(CEREAL_NVP(id));
     
    -    if (id & cereal::detail::msb_32bit) {
    -        TypeID type_code;
    -        ar(type_code);
    -        switch (type_code) {
    +        if (id & cereal::detail::msb_32bit) {
    +            TypeID type_code;
    +            ar(type_code);
    +            switch (type_code) {
     #define SYMENGINE_ENUM(type_enum, Class)                                       \
         case type_enum: {                                                          \
             if (not std::is_base_of<T, Class>::value) {                            \
                 throw std::runtime_error("Cannot convert to type.");               \
             } else {                                                               \
                 RCP<const Class> dummy_ptr;                                        \
    -            ptr = rcp_static_cast<const T>(                                    \
    -                rcp_static_cast<const Basic>(load_basic(ar, dummy_ptr)));      \
    +            RCP<const Basic> basic_ptr = load_basic(ar, dummy_ptr);            \
    +            ptr = rcp_dynamic_cast<const T>(basic_ptr);                        \
                 break;                                                             \
             }                                                                      \
         }
     #include "symengine/type_codes.inc"
     #undef SYMENGINE_ENUM
    -            default:
    -                throw std::runtime_error("Unknown type");
    -        }
    -        std::shared_ptr<void> sharedPtr = std::static_pointer_cast<void>(
    -            std::make_shared<RCP<const Basic>>(ptr));
    +                default:
    +                    throw SerializationError("Unknown type");
    +            }
    +            std::shared_ptr<void> sharedPtr = std::static_pointer_cast<void>(
    +                std::make_shared<RCP<const Basic>>(
    +                    rcp_static_cast<const Basic>(ptr)));
     
    -        ar.registerSharedPointer(id, sharedPtr);
    -    } else {
    -        std::shared_ptr<RCP<const T>> sharedPtr
    -            = std::static_pointer_cast<RCP<const T>>(ar.getSharedPointer(id));
    -        ptr = *sharedPtr.get();
    +            ar.registerSharedPointer(id, sharedPtr);
    +        } else if (id == 0) {
    +            throw SerializationError("Unknown type");
    +        } else {
    +            std::shared_ptr<RCP<const Basic>> sharedPtr
    +                = std::static_pointer_cast<RCP<const Basic>>(
    +                    ar.getSharedPointer(id));
    +            RCP<const Basic> basic_ptr = *sharedPtr.get();
    +            ptr = rcp_dynamic_cast<const T>(basic_ptr);
    +        }
    +    } catch (cereal::Exception &e) {
    +        throw SerializationError(e.what());
         }
     }
     } // namespace SymEngine
    
  • symengine/tests/basic/test_serialize-cereal.cpp+13 0 modified
    @@ -1,6 +1,7 @@
     #include "catch.hpp"
     
     #include <symengine/basic.h>
    +#include <symengine/parser.h>
     #include <symengine/serialize-cereal.h>
     #include <cereal/archives/binary.hpp>
     
    @@ -73,3 +74,15 @@ TEST_CASE("Test serialization using cereal", "[serialize-cereal]")
             real_mpfr(mpfr_class("0.35", 100, 10)));
     #endif
     }
    +
    +TEST_CASE("Test serialization exception", "[serialize-cereal]")
    +{
    +    RCP<const Basic> expr = se::parse("x + y");
    +    std::string data = expr->dumps();
    +    data[45] = char(5);
    +    CHECK_THROWS_AS(Basic::loads(data), se::SerializationError);
    +
    +    data = expr->dumps();
    +    data[47] = char(5);
    +    CHECK_THROWS_AS(Basic::loads(data), se::SerializationError);
    +}
    

Vulnerability mechanics

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

References

5

News mentions

0

No linked articles in our index yet.