Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

[Bug] OceanBase sink JDBC URL sensitive parameters are never filtered (INLONG-11731 fix is incomplete): `autoDeserialize` passes through to Connector/J

Aperta
#12,215 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

@akashchamp ci sta già lavorando.

Dal 23/9/2026.

  • #12216 di @akashchamp — aperta

Valutazione

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

Direzione di ricerca

The fix must be applied in OceanBaseSinkDTO.getFromRequest in inlong-manager/manager-pojo to call the sensitive-parameter filter, similar to MySQLSinkDTO. Then verify that OceanBaseLoadNode.tableOptions in inlong-sort/sort-common receives the filtered URL. Test by creating an OceanBase sink with autoDeserialize=true and ensuring the parameter is removed before reaching the JDBC connector.

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

Descrizione

type/bug
What happened

INLONG-11731 / PR #11732 hardened MySQLSensitiveUrlUtils (case-insensitive matching and the yeſ long-s variant) for the MySQL sink entry. However, the OceanBase sink entry never passes the JDBC URL through any sensitive-parameter filter at all, and the URL is forwarded verbatim to the Flink JDBC connector. A tenant user who creates/updates an OceanBase sink can therefore transport autoDeserialize=true (and other dangerous Connector/J parameters) end-to-end and trigger Java deserialization in the Sort runtime.

Root cause chain (all verified against released artifacts):

  1. inlong-manager/manager-pojo/.../sink/oceanbase/OceanBaseSinkDTO.java
    getFromRequest(...) never calls filterSensitive(...) — although its
    @apiNote explicitly says "filter sensitive params before saving". The raw
    attacker-controlled URL is stored in the sink config.
  2. inlong-sort/sort-common/.../node/load/OceanBaseLoadNode.java
    tableOptions() does options.put("url", url) verbatim (line ~89).
  3. jdbc-inlong connector (Flink 1.15/1.18) JdbcDynamicTableFactory
    passes the URL to Connector/J without any runtime scrubbing
    (JdbcUrlUtils.replaceInvalidUrlProperty exists only in the 1.13 module,
    and even that only replaces the exact string autoDeserialize=true;
    autoDeserialize=yes survives it).
  4. With autoDeserialize=true, Connector/J auto-deserializes Java-serialized
    BLOB values on ResultSet.getObject(). If the Sort classpath contains a
    usable gadget chain, this is RCE in the Flink TaskManager.

The Manager-side MySQL entry (MySQLSinkDTO.getFromRequest) does call
filterSensitive, so the OceanBase entry is the gap left by PR #11732 —
OceanBaseJdbcUtils.establishDatabaseConnection (Manager-side connectivity
check) filters, but that is not the path that feeds Sort.

What you expected to happen

OceanBase sink creation should apply the same sensitive-parameter filtering as
the MySQL sink does after INLONG-11731, i.e.

OceanBaseSinkDTO.getFromRequest(request, extParams)

should neutralize autoDeserialize / allowLoadLocalInfile / allowUrlInLocalInfile
/ allowLoadLocalInfileInPath (and ideally reject queryInterceptors /
statementInterceptors) before the config is saved — so that what reaches
OceanBaseLoadNode.tableOptions() and eventually Connector/J is incapable of
enabling auto-deserialization.

Current actual behaviour (verified): URL containing autoDeserialize=true
submitted via the OceanBase sink request passes unchanged through
OceanBaseSinkDTO.getFromRequest -> OceanBaseLoadNode.tableOptions() ->
Flink jdbc-inlong connector -> Connector/J, and deserialization is executed
during ResultSet.getObject().

How to reproduce

Minimal end-to-end reproduction using released InLong 2.2.0 artifacts and a
real MySQL server (Docker):

  1. Start MySQL:
docker run -d --name ob-poc -e MYSQL_ROOT_PASSWORD=root123 \
    -e MYSQL_DATABASE=testdb -p 3307:3306 mysql:5.7
  1. Prepare the "attacker-controlled" table: write one row whose BLOB column
    contains a Java-serialized object of a class whose readObject() has a
    visible side effect (e.g., creates a marker file). Any real-world exploit
    would use a public gadget chain (e.g., CommonsCollections) instead of the
    marker class.

  2. Run the chain with the official released classes (manager-pojo 2.2.0,
    sort-common 2.2.0, mysql-connector-j 8.0.33):

// 1) Manager entry: exactly what OceanBaseSinkDTO.getFromRequest does with
//    an OceanBaseSinkRequest carrying the attacker URL.
OceanBaseSinkDTO dto = OceanBaseSinkDTO.getFromRequest(request, null);
System.out.println("after getFromRequest url = " + dto.getJdbcUrl());
// -> jdbc:mysql://127.0.0.1:3307/testdb?autoDeserialize=true   (NOT filtered)

// 2) Sort layer: what OceanBaseLoadNode emits for the connector
Map<String, String> opts = new OceanBaseLoadNode(dto.getJdbcUrl(), ...).tableOptions();
System.out.println("tableOptions url = " + opts.get("url"));
// -> jdbc:mysql://127.0.0.1:3307/testdb?autoDeserialize=true   (verbatim)

// 3) Runtime: what the jdbc-inlong connector ultimately does
Connection conn = DriverManager.getConnection(opts.get("url"), "root", "root123");
ResultSet rs = conn.createStatement().executeQuery("SELECT blob_col FROM loot").get(1), ...
Object o = rs.getObject(1);   // triggers deserialization
// -> marker file PWNED.txt created by the serialized object's readObject()

Negative control: the identical query with autoDeserialize absent returns
byte[] instead and creates no marker file — the behaviour difference is
caused solely by this one parameter.

Also reproducible: with the 1.13 JdbcUrlUtils.replaceInvalidUrlProperty,
jdbc:mysql://...?autoDeserialize=yes is NOT neutralized (only the exact
string autoDeserialize=true is replaced), and Connector/J parses
autoDeserialize=yes as true.

Environment
  • OS: Linux x86_64
  • JDK: OpenJDK 1.8.0_452
  • MySQL Server: 5.7 (Docker mysql:5.7)
  • Connector/J: com.mysql:mysql-connector-j 8.0.33 (also verified with mysql:mysql-connector-java 8.0.28)
  • Apache Spark/Flink runtime: not required – the invocation was exercised with the released InLong jars directly
InLong version

master

InLong Component

InLong Manager, InLong Sort

Are you willing to submit PR?
  • Yes, I am willing to submit a PR!
Code of Conduct
Lingua principale
Java
Stelle
1.5k
Fork
570
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

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/inlong

Tutte le issue di apache/inlong

Issue simili

Altre issue su Java

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.