VYPR
High severityNVD Advisory· Published Jun 20, 2025· Updated Apr 15, 2026

CVE-2025-47771

CVE-2025-47771

Description

PowSyBl (Power System Blocks) is a framework to build power system oriented software. In versions 6.3.0 to 6.7.1, there is a deserialization issue in the read method of the SparseMatrix class that can lead to a wide range of privilege escalations depending on the circumstances. This method takes in an InputStream and returns a SparseMatrix object. This issue has been patched in com.powsybl:powsybl-math: 6.7.2. A workaround for this issue involves not using SparseMatrix deserialization (SparseMatrix.read(...) methods).

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
com.powsybl:powsybl-mathMaven
>= 6.3.0, < 6.7.26.7.2

Patches

2
8ed16ce41683

Check object type at SparseMatrix deserialization (GHSA-f5cx-h789-j959)

https://github.com/powsybl/powsybl-coreOlivier PerrinJun 19, 2025via ghsa
2 files changed · +89 4
  • math/src/main/java/com/powsybl/math/matrix/SparseMatrix.java+14 4 modified
    @@ -10,13 +10,13 @@
     import com.powsybl.commons.exceptions.UncheckedClassNotFoundException;
     import com.powsybl.commons.util.trove.TDoubleArrayListHack;
     import com.powsybl.commons.util.trove.TIntArrayListHack;
    +import gnu.trove.list.array.TDoubleArrayList;
    +import gnu.trove.list.array.TIntArrayList;
     
     import java.io.*;
     import java.nio.file.Files;
     import java.nio.file.Path;
    -import java.util.Arrays;
    -import java.util.List;
    -import java.util.Objects;
    +import java.util.*;
     
     /**
      * Sparse matrix implementation in <a href="https://en.wikipedia.org/wiki/Sparse_matrix#Compressed_sparse_column_(CSC_or_CCS)">CSC</a></a> format.
    @@ -26,9 +26,14 @@
      * @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
      */
     public class SparseMatrix extends AbstractMatrix implements Serializable {
    -
         private static final long serialVersionUID = -7810324161942335828L;
     
    +    // Classes allowed during deserialization
    +    private static final Set<Class<?>> ALLOWED_CLASSES = Set.of(SparseMatrix.class,
    +            int[].class, double[].class,
    +            TIntArrayListHack.class, TDoubleArrayListHack.class,
    +            TIntArrayList.class, TDoubleArrayList.class);
    +
         /**
          * Sparse Element implementation.
          * An element in a sparse matrix is defined by its index in the values vector.
    @@ -487,6 +492,11 @@ public void write(OutputStream outputStream) {
         public static SparseMatrix read(InputStream inputStream) {
             Objects.requireNonNull(inputStream);
             try (ObjectInputStream objectInputStream = new ObjectInputStream(inputStream)) {
    +            // Check that the object to deserialize is really a SparseMatrix.
    +            // This check is done prior to its complete deserialization to prevent security problems (RCE).
    +            // - Check that all non-null encountered classes are among the accepted ones (the one composing a SparseMatrix).
    +            ObjectInputFilter allowedClassesFilter = ObjectInputFilter.allowFilter(ALLOWED_CLASSES::contains, ObjectInputFilter.Status.REJECTED);
    +            objectInputStream.setObjectInputFilter(allowedClassesFilter);
                 return (SparseMatrix) objectInputStream.readObject();
             } catch (IOException e) {
                 throw new UncheckedIOException(e);
    
  • math/src/test/java/com/powsybl/math/matrix/SparseMatrixDeserializationTest.java+75 0 added
    @@ -0,0 +1,75 @@
    +/**
    + * Copyright (c) 2025, RTE (http://www.rte-france.com)
    + * This Source Code Form is subject to the terms of the Mozilla Public
    + * License, v. 2.0. If a copy of the MPL was not distributed with this
    + * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    + * SPDX-License-Identifier: MPL-2.0
    + */
    +package com.powsybl.math.matrix;
    +
    +import com.google.common.jimfs.Configuration;
    +import com.google.common.jimfs.Jimfs;
    +import org.junit.jupiter.api.AfterAll;
    +import org.junit.jupiter.api.BeforeAll;
    +import org.junit.jupiter.api.Test;
    +
    +import java.io.*;
    +import java.nio.charset.StandardCharsets;
    +import java.nio.file.FileSystem;
    +import java.nio.file.Files;
    +import java.nio.file.Path;
    +
    +import static org.junit.jupiter.api.Assertions.assertFalse;
    +import static org.junit.jupiter.api.Assertions.assertThrows;
    +
    +/**
    + * @author Olivier Perrin {@literal <olivier.perrin at rte-france.com>}
    + */
    +class SparseMatrixDeserializationTest {
    +    private static FileSystem fileSystem;
    +    protected static Path testDir;
    +
    +    @BeforeAll
    +    static void setUp() throws Exception {
    +        fileSystem = Jimfs.newFileSystem(Configuration.unix());
    +        testDir = fileSystem.getPath("/tmp");
    +        Files.createDirectories(testDir);
    +    }
    +
    +    @AfterAll
    +    static void tearDown() throws Exception {
    +        fileSystem.close();
    +    }
    +
    +    @Test
    +    void testSecureDeserialization() throws IOException {
    +        // Prepare exploit payload
    +        ByteArrayOutputStream baos = new ByteArrayOutputStream();
    +        try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
    +            oos.writeObject(new Exploit());
    +        }
    +
    +        // Try to deserialize the false SparseMatrix object
    +        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
    +        assertThrows(UncheckedIOException.class, () -> SparseMatrix.read(bais), "Exploit may be present.");
    +
    +        // Confirm there is no exploit: the "rce" file should not exist
    +        Path rceFile = testDir.resolve("rce");
    +        assertFalse(Files.exists(rceFile), "The exploit is present.");
    +    }
    +
    +    static class Exploit implements Serializable {
    +        @Serial
    +        private static final long serialVersionUID = 1L;
    +
    +        @Serial
    +        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    +            // Emulate a security problem: when reading the object, create a new file.
    +            // If this file is indeed created when deserializing the payload, then an attacker
    +            // may perform dangerous operations (download and install a malware, connect to an external server, ...)
    +            in.defaultReadObject();
    +            Path rceFile = testDir.resolve("rce");
    +            Files.writeString(rceFile, "Security problem", StandardCharsets.UTF_8);
    +        }
    +    }
    +}
    

Vulnerability mechanics

Generated by null/stub 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.