[Bug] Auto-trusted serialization allow list skips array component classes

Aperta Adatta ai principianti
#16,569 1 commento 1 reazione 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@Icesource ci sta già lavorando.

Dal 4/11/2026.

  • #16570 di @Icesource — aperta
  • #16575 di @Icesource — aperta

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
78/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
java

Direzione di ricerca

Inizia leggendo SerializeSecurityConfigurator.checkClass e il suo attraversamento a partire dalle firme dei servizi. Segui la gestione degli array e confrontala con il ramo GenericArrayType di checkType; poi esamina i test esistenti sulla sicurezza della serializzazione per individuare il punto giusto in cui aggiungere un caso di regressione. Il lavoro è concluso quando un Payload[] dichiarato fa sì che Payload venga considerato attendibile automaticamente e il test di regressione copre l’errore Hessian2 segnalato in modalità STRICT.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Pre-check
  • I am sure that all the content I provide is in English.
Search before asking
  • I searched existing issues and found no report of this concrete array-component case.

Related reports such as #13752 (generic/subtype allow-list questions) and #16491 (sealed subtypes) have different triggers.

Apache Dubbo Component

Java SDK (apache/dubbo)

Dubbo Version
  • Apache Dubbo 3.3.6, using the official Maven artifact.
  • OpenJDK 17.0.20.1 (Homebrew), macOS 26.3.2.
  • The same array early-return is present on the current 3.3 branch at 2d9730c6ab4358d94c6e3594fdd2dca0009fe912.
Steps to reproduce this issue

Declare a serializable DTO only through an array in a service signature:

public interface ArrayService { Payload[] read(); }
public static class Payload implements Serializable { public String text = "ok"; }

With autoTrustSerializeClass=true, exact-class trust (the default), STRICT checking and Hessian2, an ordinary call to read() fails while the provider serializes the response. Payload[] is auto-trusted, but Payload is not.

The reproduction below uses a real loopback dubbo:// transport with injvm=false, no registry and no custom allow-list. Provider and consumer run in one JVM. Each command starts a fresh JVM so that allow-list state cannot leak between cases.

Complete runnable reproduction

Save this as pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0">
  <modelVersion>4.0.0</modelVersion>
  <groupId>repro</groupId>
  <artifactId>dubbo-array-trust</artifactId>
  <version>1.0</version>
  <dependencies>
    <dependency>
      <groupId>org.apache.dubbo</groupId>
      <artifactId>dubbo</artifactId>
      <version>3.3.6</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-simple</artifactId>
      <version>1.7.36</version>
    </dependency>
  </dependencies>
</project>

Save this as RpcArrayProbe.java:

package com.review.probe;

import java.io.Serializable;
import java.net.ServerSocket;
import org.apache.dubbo.config.*;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;

public class RpcArrayProbe {
    public interface ArrayService { Payload[] read(); }
    public static class Payload implements Serializable { public String text = "ok"; }
    public static class ArrayServiceImpl implements ArrayService {
        public Payload[] read() { return new Payload[]{new Payload()}; }
    }
    public static void main(String[] args) throws Exception {
        int port;
        try (ServerSocket socket = new ServerSocket(0, 1, java.net.InetAddress.getLoopbackAddress())) {
            port = socket.getLocalPort();
        }
        ApplicationConfig app = new ApplicationConfig("array-rpc-probe");
        app.setQosEnable(false);
        app.setSerializeCheckStatus(args[1]);
        ProtocolConfig protocol = new ProtocolConfig("dubbo", port);
        protocol.setHost("127.0.0.1");
        protocol.setSerialization(args[0]);
        protocol.setPreferSerialization(args[0]);
        ServiceConfig<ArrayService> service = new ServiceConfig<>();
        service.setInterface(ArrayService.class);
        service.setRef(new ArrayServiceImpl());
        DubboBootstrap bootstrap = DubboBootstrap.getInstance();
        ReferenceConfig<ArrayService> reference = new ReferenceConfig<>();
        try {
            bootstrap.application(app).registry(new RegistryConfig("N/A")).protocol(protocol).service(service).start();
            reference.setInterface(ArrayService.class);
            reference.setUrl("dubbo://127.0.0.1:" + port + "?serialization=" + args[0]
                + "&prefer.serialization=" + args[0]);
            reference.setInjvm(false);
            reference.setRetries(0);
            reference.setTimeout(5000);
            Payload[] result = reference.get().read();
            if (result.length != 1 || !"ok".equals(result[0].text)) throw new AssertionError();
            System.out.println("RPC_RESULT " + String.join(" ", args) + " PASS");
        } catch (Throwable failure) {
            System.out.println("RPC_RESULT " + String.join(" ", args) + " FAIL " + failure);
        } finally {
            reference.destroy();
            bootstrap.destroy();
        }
    }
}

Run on JDK 17:

mvn -B -ntp dependency:build-classpath -Dmdep.outputFile=classpath.txt
mkdir -p classes
javac -cp "$(cat classpath.txt)" -d classes RpcArrayProbe.java
java -cp "classes:$(cat classpath.txt)" com.review.probe.RpcArrayProbe hessian2 STRICT
java -cp "classes:$(cat classpath.txt)" com.review.probe.RpcArrayProbe hessian2 WARN
java -cp "classes:$(cat classpath.txt)" com.review.probe.RpcArrayProbe fastjson2 STRICT

Observed results on 3.3.6:

Serializer Check mode Result
Hessian2 STRICT Fails: Payload is not in the allow list
Hessian2 WARN Succeeds
Fastjson2 STRICT Succeeds for this concrete array-return case

Relevant failure (transport wrapper omitted):

Failed to send response
java.io.IOException: org.apache.dubbo.common.serialize.SerializationException:
java.lang.IllegalArgumentException: [Serialization Security] Serialized class
com.review.probe.RpcArrayProbe$Payload is not in allow list.
Current mode is `STRICT`, will disallow to deserialize it by default.
What you expected to happen

The declared component class Payload should be auto-trusted when Payload[] is reached during service-signature scanning, along with the fields normally visited for a directly declared Payload.

SerializeSecurityConfigurator.checkClass currently adds the array class and returns immediately when clazz.isArray() is true. It never visits clazz.getComponentType(). A concrete Payload[] is represented as a Class, so the existing GenericArrayType branch in checkType does not compensate for this.

Anything else

This is a functional compatibility issue in automatic allow-list discovery. It does not affect every array call: an explicit allow-list entry, package-prefix trust, or another scanned signature/field referencing Payload directly can mask the omission. The Fastjson2 result above is limited to this reproduction.

A minimal fix is to visit the array component through the existing checkClass traversal. That also covers multidimensional arrays and DTO array fields, while retaining the existing visited-type cache and exact-class trust policy.

Do you have a (mini) reproduction demo?
  • Yes, the complete reproduction is included above.
Are you willing to submit a pull request to fix on your own?
  • Yes, I am submitting a fix with regression tests.
Code of Conduct
Fix and related follow-up

The array component fix for this issue is https://github.com/apache/dubbo/pull/16570 (linked to close this issue on merge).

A separate allow-list scanning problem involving missing optional dependencies is tracked in https://github.com/apache/dubbo/issues/16574, with its independent fix in https://github.com/apache/dubbo/pull/16575. That follow-up addresses traversal failure isolation; it does not replace the array component fix.

Lingua principale
Java
Stelle
41.6k
Fork
26.3k
Merge medio
1g 22h
PR unite (30g)
19

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di apache/dubbo

Tutte le issue di apache/dubbo

Issue simili

Altre issue su Java

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.